Last active
January 25, 2024 13:58
-
-
Save davemackintosh/e7d6e834ba0b38eb8000f26746a0f193 to your computer and use it in GitHub Desktop.
Polling about ergonomics for Elp view and component state management and implementation. Files extensions are chosen for their syntax highlighting only.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { App, Window } from "elp/app" | |
import { Form, Label, Input, Button } from "elp/app/elements" | |
import { Message, User } from "$types/chat" | |
import { Message as MessageView } from "$components/message" | |
export object ChatAppState implements Contextual { | |
.name: *string | |
.messages: []Message | |
.members: []User | |
.loggedIn: bool = false | |
} | |
// The Contextual type here actually transforms Chat into a context provider which | |
// along with the implements on ChatAppState gives all child components writeable | |
// state if it is passed down and the property is not marked as const. | |
// So when we pass message down by reference we can actually do .message.reactions.push(newReaction) | |
// and it will cause reactivity all the way up the view chain where that property is read. | |
export fn Chat(name: *string) implements App, Contextual<ChatAppState> -> Window { | |
Window { | |
if .name not Empty or not .loggedIn { | |
ForEach(.messages) { message in | |
// We borrow the message to pass down which extends it's lifetime | |
// and allows for mutation and avoids copying. | |
MessageView( message = &message) | |
} | |
} else { | |
Form(preventDefault, onSubmit={fn { .loggedIn = true }}) { | |
Label("Enter your display name") { | |
Input(name="display-name", type="text", value={.name}) | |
Button { | |
Text("Log in") | |
} | |
} | |
} | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { App } from "elp/app" | |
import { Message, User } from "$types/chat" | |
import { Message as MessageView } from "$components/message" | |
export object ChatAppState { | |
.name: *string | |
.messages: []Message | |
.members: []User | |
} | |
export fn Chat(name: *string) { | |
state app: App | |
state chatApp: typeof Contextual(ChatAppState(name)) | |
Window { | |
if chatApp.name not Empty or not chatApp.loggedIn { | |
ForEach(chatApp.messages) { message in | |
// We borrow the message to pass down which extends it's lifetime | |
// and allows for mutation and avoids copying. | |
MessageView( message = &message) | |
} | |
} else { | |
Form(preventDefault, onSubmit={fn { chatApp.loggedIn = true }}) { | |
Label("Enter your display name") { | |
Input(name="display-name", type="text", value={chatApp.name}) | |
Button { | |
Text("Log in") | |
} | |
} | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { UUID } from "elp/types" | |
export object User { | |
.displayName: string | |
} | |
export object Message { | |
.body: const string | |
.user: const User | |
reactions: []string | |
} | |
export enum Actions { | |
.LOGIN(user: User) | |
.SEND_MESSAGE(body: string) | |
.DELETE_MESSAGE(id: UUID) | |
.LOGOUT | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment