Skip to content

Instantly share code, notes, and snippets.

@davemackintosh
Last active January 25, 2024 13:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save davemackintosh/e7d6e834ba0b38eb8000f26746a0f193 to your computer and use it in GitHub Desktop.
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.
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")
}
}
}
}
}
}
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")
}
}
}
}
}
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