Trying to make a text input. this shit is hard
This commit is contained in:
parent
fadf59c6aa
commit
a9e10b3123
3 changed files with 125 additions and 67 deletions
|
|
@ -25,6 +25,7 @@ console.log(ast);
|
|||
|
||||
const env: Env = new Map(Object.entries(builtins));
|
||||
const appRecord = evaluate(ast, env);
|
||||
console.log("appRecord", appRecord);
|
||||
|
||||
if (appRecord.kind !== 'record')
|
||||
throw new Error('Expected record');
|
||||
|
|
|
|||
|
|
@ -1,78 +1,48 @@
|
|||
# Helpers
|
||||
|
||||
insertChar = text pos char \
|
||||
before = slice text 0 pos;
|
||||
after = slice text pos (len text);
|
||||
before & char & after;
|
||||
|
||||
deleteChar = text pos \
|
||||
(pos == 0
|
||||
| True \ text
|
||||
routeKeyToFocused = state event \
|
||||
(state.focusedInput == "email"
|
||||
| True \
|
||||
newInputState = textInput2.update state.email event;
|
||||
state.{ email = newInputState }
|
||||
| False \
|
||||
(before = slice text 0 (pos - 1);
|
||||
after = slice text pos (len text);
|
||||
before & after));
|
||||
|
||||
# test app
|
||||
newInputState = textInput2.update state.password event;
|
||||
state.{ password = newInputState });
|
||||
|
||||
init = {
|
||||
text = "hello world",
|
||||
cursorPos = 5
|
||||
focusedInput = "email",
|
||||
email = textInput2.init "",
|
||||
password = textInput2.init ""
|
||||
};
|
||||
|
||||
update = state event \ event
|
||||
| ArrowLeft \ state.{ cursorPos = max 0 (state.cursorPos - 1) }
|
||||
| ArrowRight \ state.{ cursorPos = min (len state.text) (state.cursorPos + 1) }
|
||||
| Backspace \ {
|
||||
text = deleteChar state.text state.cursorPos,
|
||||
cursorPos = max 0 (state.cursorPos - 1)
|
||||
}
|
||||
| Char c \ {
|
||||
text = insertChar state.text state.cursorPos c,
|
||||
cursorPos = state.cursorPos + 1
|
||||
}
|
||||
| FocusEmail \ state.{ focusedInput = "email" }
|
||||
| FocusPassword \ state.{ focusedInput = "password" }
|
||||
| ArrowLeft \ routeKeyToFocused state ArrowLeft
|
||||
| ArrowRight \ routeKeyToFocused state ArrowRight
|
||||
| Backspace \ routeKeyToFocused state Backspace
|
||||
| Char c \ routeKeyToFocused state (Char c)
|
||||
| _ \ state;
|
||||
|
||||
view = state viewport \
|
||||
# charWidth = 9.65;
|
||||
# cursorX = state.cursorPos * charWidth;
|
||||
textBeforeCursor = slice state.text 0 state.cursorPos;
|
||||
cursorX = measureText textBeforeCursor;
|
||||
|
||||
Column {
|
||||
gap = 20,
|
||||
children = [
|
||||
Text {
|
||||
content = "Text: " & state.text & " | Cursor: " & str(state.cursorPos),
|
||||
x = 0,
|
||||
y = 20
|
||||
},
|
||||
|
||||
# Text Input Component
|
||||
Stack {
|
||||
children = [
|
||||
Rect { w = 300, h = 40, color = "white", radius = 4 },
|
||||
|
||||
# Text content
|
||||
Positioned {
|
||||
x = 8,
|
||||
y = 8,
|
||||
child = Text { content = state.text, x = 0, y = 17 }
|
||||
},
|
||||
|
||||
# Cursor
|
||||
Positioned {
|
||||
x = 8 + cursorX,
|
||||
y = 8,
|
||||
child = Rect {
|
||||
w = 2,
|
||||
h = 24,
|
||||
color = "black"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
Positioned {
|
||||
x = 30,
|
||||
y = 30,
|
||||
child = Column {
|
||||
gap = 10,
|
||||
children = [
|
||||
(textInput2.view state.email) {
|
||||
focused = state.focusedInput == "email",
|
||||
onFocus = FocusEmail,
|
||||
w = 300,
|
||||
h = 40
|
||||
},
|
||||
(textInput2.view state.password) {
|
||||
focused = state.focusedInput == "password",
|
||||
onFocus = FocusPassword,
|
||||
w = 300,
|
||||
h = 40
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
{ init = init, update = update, view = view }
|
||||
|
|
|
|||
|
|
@ -9,3 +9,90 @@ button = config \
|
|||
]
|
||||
}
|
||||
};
|
||||
|
||||
insertChar = text pos char \
|
||||
before = slice text 0 pos;
|
||||
after = slice text pos (len text);
|
||||
before & char & after;
|
||||
|
||||
deleteChar = text pos \
|
||||
(pos == 0
|
||||
| True \ text
|
||||
| False \
|
||||
(before = slice text 0 (pos - 1);
|
||||
after = slice text pos (len text);
|
||||
before & after));
|
||||
|
||||
calcScrollOffset = text cursorPos scrollOffset inputWidth \
|
||||
textBeforeCursor = slice text 0 cursorPos;
|
||||
cursorX = measureText textBeforeCursor;
|
||||
(cursorX < scrollOffset
|
||||
| True \ max 0 (cursorX - 20)
|
||||
| False \
|
||||
(cursorX > (scrollOffset + inputWidth)
|
||||
| True \ cursorX - inputWidth + 20
|
||||
| False \ scrollOffset));
|
||||
|
||||
textInput2 = {
|
||||
# init : String \ State
|
||||
init = text \ { text = text, cursorPos = 0, scrollOffset = 0 },
|
||||
|
||||
# update : State \ Event \ State
|
||||
update = state event \ event
|
||||
| ArrowLeft \ (
|
||||
newCursorPos = max 0 (state.cursorPos - 1);
|
||||
newScroll = calcScrollOffset state.text newCursorPos state.scrollOffset 284;
|
||||
{ text = state.text, cursorPos = newCursorPos, scrollOffset = newScroll }
|
||||
)
|
||||
|
||||
| ArrowRight \ (
|
||||
newCursorPos = min (len state.text) (state.cursorPos + 1);
|
||||
newScroll = calcScrollOffset state.text newCursorPos state.scrollOffset 284;
|
||||
{ text = state.text, cursorPos = newCursorPos, scrollOffset = newScroll }
|
||||
)
|
||||
|
||||
| Backspace \ (
|
||||
newText = deleteChar state.text state.cursorPos;
|
||||
newCursorPos = max 0 (state.cursorPos - 1);
|
||||
newScroll = calcScrollOffset newText newCursorPos state.scrollOffset 284;
|
||||
{ text = newText, cursorPos = newCursorPos, scrollOffset = newScroll }
|
||||
)
|
||||
|
||||
| Char c \ (
|
||||
newText = insertChar state.text state.cursorPos c;
|
||||
newCursorPos = state.cursorPos + 1;
|
||||
newScroll = calcScrollOffset newText newCursorPos state.scrollOffset 284;
|
||||
{ text = newText, cursorPos = newCursorPos, scrollOffset = newScroll }
|
||||
)
|
||||
|
||||
| _ \ state,
|
||||
|
||||
view = state config \
|
||||
textBeforeCursor = slice state.text 0 state.cursorPos;
|
||||
cursorX = measureText textBeforeCursor;
|
||||
padding = 8;
|
||||
|
||||
Clickable {
|
||||
event = config.onFocus,
|
||||
child =
|
||||
Stack {
|
||||
children = [
|
||||
Rect { w = config.w, h = config.h, color = "rgba(240,240,240,0.9)", radius = 4 },
|
||||
|
||||
Positioned {
|
||||
x = 8 - state.scrollOffset,
|
||||
y = 8,
|
||||
child = Text { content = state.text, x = 0, y = 17 }
|
||||
},
|
||||
|
||||
(config.focused
|
||||
| True \ Positioned {
|
||||
x = 8 + cursorX - state.scrollOffset,
|
||||
y = 8,
|
||||
child = Rect { w = 2, h = 24, color = "black" }
|
||||
}
|
||||
| _ \ Rect { w = 0, h = 0, color = "transparent" })
|
||||
]
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue