Skip to content

Commit

Permalink
move to new rendering system
Browse files Browse the repository at this point in the history
  • Loading branch information
Ethosa committed May 17, 2024
1 parent 684d1a3 commit 939755d
Show file tree
Hide file tree
Showing 4 changed files with 115 additions and 36 deletions.
12 changes: 7 additions & 5 deletions src/happyx_ui/core.nim
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@ proc rad*(val: SomeNumber): string = $val.float & "rad"
proc turn*(val: SomeNumber): string = $val.float & "turn"
proc rem*(val: SomeNumber): string = $val.float & "rem"


var uniqId = 0
rendererHandlers.add(cast[tuple[key: string, p: AppEventHandler]]((key: "rendered", p: proc() =
{.cast(gcsafe).}:
uniqId = 0
)))
proc uid*: string =
result = "c"
for i in 0..4: result &= $rand(0..9)
result &= "-"
for i in 0..16: result &= $rand(0..9)
result = "c" & $uniqId & $(uniqId+1) & $(uniqId+5)
inc uniqId


type
Expand Down
132 changes: 104 additions & 28 deletions src/happyx_ui/input.nim
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ import


proc Input*(onInput: OnInput = defOnInput, onFocus: OnFocus = defOnFocus,
state: State[string] = nil, id: string = "",
state: State[string] = nil, id: string = "", hint: string = "",
modifier: Modifier = initModifier(), class: string = "",
stmt: TagRef = nil): TagRef =
let i = uid()
buildHtml:
tDiv(class = fmt"hpx-input-container-{i} {class}"):
tDiv(class = fmt"hpx-input-container {class}"):
tInput(
class = fmt"hpx-input-{i} {class}",
class = fmt"hpx-input {class}",
placeholder = " ",
id = id,
value =
Expand All @@ -26,18 +26,25 @@ proc Input*(onInput: OnInput = defOnInput, onFocus: OnFocus = defOnFocus,
onInput($ev.target.value)
if not state.isNil:
state.set($ev.target.value)
if ($ev.target.value).len > 0:
ev.target.Element.parentElement.classList.add("hpx-input-hint-container")
else:
ev.target.Element.parentElement.classList.remove("hpx-input-hint-container")
@focus:
onFocus(ev.target.Element)
tLabel(class = fmt"hpx-input-placeholder-{i}"):
tLabel(class = fmt"hpx-input-placeholder"):
if not stmt.isNil:
stmt
if hint.len > 0:
tLabel(class = fmt"hpx-input-hint"):
{hint}
tStyle: {fmt("""
div.hpx-input-container-<i> {
div.hpx-input-container {
position: relative;
display: flex;
align-items: center;
}
input.hpx-input-<i> {
input.hpx-input {
border: 0;
border-bottom-width: .15rem;
border-bottom-color: <PRIMARY_COLOR>;
Expand All @@ -50,13 +57,13 @@ proc Input*(onInput: OnInput = defOnInput, onFocus: OnFocus = defOnFocus,
font-size: 18px;
padding: .1rem .5rem;
}
input.hpx-input-<i>:hover {
input.hpx-input:hover {
border-bottom-color: <PRIMARY_HOVER_COLOR>;
}
input.hpx-input-<i>:focus {
input.hpx-input:focus {
border-bottom-color: <PRIMARY_ACTIVE_COLOR>;
}
label.hpx-input-placeholder-<i> {
label.hpx-input-placeholder {
position: absolute;
transition: all;
transition-duration: .3s;
Expand All @@ -65,26 +72,41 @@ proc Input*(onInput: OnInput = defOnInput, onFocus: OnFocus = defOnFocus,
font-size: 16px;
padding: .1rem .5rem;
}
input.hpx-input-<i>:focus + label.hpx-input-placeholder-<i> {
label.hpx-input-hint {
position: absolute;
transition: all;
transition-duration: .3s;
opacity: 0;
pointer-events: none;
font-size: 16px;
padding: .1rem .5rem;
}
input#<id>:focus + label.hpx-input-placeholder {
transform: scale(75%) translateX(-15%) translateY(-150%);
opacity: .9;
}
input.hpx-input-<i>:not(:placeholder-shown) + label.hpx-input-placeholder-<i> {
div.hpx-input-container:focus-within label.hpx-input-hint {
opacity: .7;
}
div.hpx-input-hint-container:focus-within label.hpx-input-hint {
opacity: 0;
}
input#<id>:not(:placeholder-shown) + label.hpx-input-placeholder {
transform: scale(75%) translateX(-15%) translateY(-150%);
opacity: .9;
}
""", '<', '>')}


proc OutlineInput*(onInput: OnInput = defOnInput, onFocus: OnFocus = defOnFocus,
state: State[string] = nil, id: string = "",
state: State[string] = nil, id: string = "", hint: string = "",
modifier: Modifier = initModifier(), class: string = "",
stmt: TagRef = nil): TagRef =
let i = uid()
buildHtml:
tDiv(class = fmt"hpx-input-outline-container-{i} {class}"):
tDiv(class = fmt"hpx-input-outline-container {class}"):
tInput(
class = fmt"hpx-input-outline-{i} {class}",
class = fmt"hpx-input-outline {class}",
placeholder = " ",
id = id,
value =
Expand All @@ -97,18 +119,25 @@ proc OutlineInput*(onInput: OnInput = defOnInput, onFocus: OnFocus = defOnFocus,
onInput($ev.target.value)
if not state.isNil:
state.set($ev.target.value)
if ($ev.target.value).len > 0:
ev.target.Element.parentElement.classList.add("hpx-input-outline-hint-container")
else:
ev.target.Element.parentElement.classList.remove("hpx-input-outline-hint-container")
@focus:
onFocus(ev.target.Element)
tLabel(class = fmt"hpx-input-outline-placeholder-{i}"):
tLabel(class = fmt"hpx-input-outline-placeholder"):
if not stmt.isNil:
stmt
if hint.len > 0:
tLabel(class = fmt"hpx-input-outline-hint"):
{hint}
tStyle: {fmt("""
div.hpx-input-outline-container-<i> {
div.hpx-input-outline-container {
position: relative;
display: flex;
align-items: center;
}
input.hpx-input-outline-<i> {
input.hpx-input-outline {
border: .15rem <PRIMARY_COLOR> solid;
transition: all;
transition-duration: .3s;
Expand All @@ -119,13 +148,13 @@ proc OutlineInput*(onInput: OnInput = defOnInput, onFocus: OnFocus = defOnFocus,
font-size: 18px;
padding: .1rem .5rem;
}
input.hpx-input-outline-<i>:hover {
input.hpx-input-outline:hover {
border-color: <PRIMARY_HOVER_COLOR>;
}
input.hpx-input-outline-<i>:focus {
input.hpx-input-outline:focus {
border-color: <PRIMARY_ACTIVE_COLOR>;
}
label.hpx-input-outline-placeholder-<i> {
label.hpx-input-outline-placeholder {
position: absolute;
transition: all;
transition-duration: .3s;
Expand All @@ -134,11 +163,26 @@ proc OutlineInput*(onInput: OnInput = defOnInput, onFocus: OnFocus = defOnFocus,
font-size: 16px;
padding: .1rem .5rem;
}
input.hpx-input-outline-<i>:focus + label.hpx-input-outline-placeholder-<i> {
label.hpx-input-outline-hint {
position: absolute;
transition: all;
transition-duration: .3s;
opacity: 0;
pointer-events: none;
font-size: 16px;
padding: .1rem .5rem;
}
input#<id>:focus + label.hpx-input-outline-placeholder {
transform: scale(75%) translateX(-15%) translateY(-150%);
opacity: .9;
}
input.hpx-input-outline-<i>:not(:placeholder-shown) + label.hpx-input-outline-placeholder-<i> {
div.hpx-input-outline-container:focus-within label.hpx-input-outline-hint {
opacity: .7;
}
div.hpx-input-outline-hint-container:focus-within label.hpx-input-outline-hint {
opacity: 0;
}
input#<id>:not(:placeholder-shown) + label.hpx-input-outline-placeholder {
transform: scale(75%) translateX(-15%) translateY(-150%);
opacity: .9;
}
Expand Down Expand Up @@ -225,9 +269,9 @@ proc Switcher*(onToggle: OnToggle = defOnToggle, state: State[bool] = nil,
i = uid()
switchControlClass =
if not state.isNil and state.val:
fmt"hpx-switch-control-on-{i}"
fmt"hpx-switch-control-on-{i} hpx-switch-control-on-anim"
else:
fmt"hpx-switch-control-off-{i}"
fmt"hpx-switch-control-off-{i} hpx-switch-control-off-anim"
switchClass =
if not state.isNil and state.val:
fmt"hpx-switch-on-{i}"
Expand Down Expand Up @@ -266,13 +310,15 @@ proc Switcher*(onToggle: OnToggle = defOnToggle, state: State[bool] = nil,
position: relative;
align-items: center;
display: flex;
transition: all;
transition-duration: .3s;
}
div.hpx-switch-off-<i> {
div.hpx-switch-on-<i> {
background-color: <PRIMARY_ACTIVE_COLOR>;
}
div.hpx-switch-on-<i> {
div.hpx-switch-off-<i> {
background-color: <PRIMARY_HOVER_COLOR>;
}
Expand All @@ -285,12 +331,12 @@ proc Switcher*(onToggle: OnToggle = defOnToggle, state: State[bool] = nil,
height: 16px;
}
div.hpx-switch-control-off-<i> {
div.hpx-switch-control-on-<i> {
right: 4px;
background-color: <PRIMARY_HOVER_COLOR>;
}
div.hpx-switch-control-on-<i> {
div.hpx-switch-control-off-<i> {
left: 4px;
background-color: <PRIMARY_ACTIVE_COLOR>;
}
Expand All @@ -300,4 +346,34 @@ proc Switcher*(onToggle: OnToggle = defOnToggle, state: State[bool] = nil,
user-select: none;
cursor: pointer;
}
.hpx-switch-control-on-anim {
animation: hpx-switch-control-off .3s;
}
.hpx-switch-control-off-anim {
animation: hpx-switch-control-on .3s;
}
@keyframes hpx-switch-control-on {
0% {
right: 4px;
left: 28px;
}
100% {
right: 28px;
left: 4px;
}
}
@keyframes hpx-switch-control-off {
0% {
right: 28px;
left: 4px;
}
100% {
right: 4px;
left: 28px;
}
}
""", '<', '>')}
1 change: 1 addition & 0 deletions src/happyx_ui/tooltip.nim
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ proc Tooltip*(modifier: Modifier = initModifier(),
if not stmt.isNil:
stmt
tScript: {fmt("""
document.querySelector(".hpx-tooltip-<id>").parentElement._eventListeners = [];
document.querySelector(".hpx-tooltip-<id>").parentElement.addEventListener('mouseover', (ev) =>> {
const e = document.querySelector(".hpx-tooltip-<id>");
e.classList.toggle("hpx-tooltip-on-<id>");
Expand Down
6 changes: 3 additions & 3 deletions tests/test.nim
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,12 @@ appRoutes "app":
Title("Hello, world!")
Text("There are input elements")
Row(1.rem):
Input(state = name, id = "username"):
Input(state = name, id = "username", hint = "First name"):
# placeholder
"Who are you?"
OutlineInput(state = name, id = "username2"):
OutlineInput(id = "username2", hint = "Last name"):
# placeholder
"Who are you?"
"What's your last name?"
Text("There are checkboxes")
Checkbox(state = isMale):
"Are you male?"
Expand Down

0 comments on commit 939755d

Please sign in to comment.