Primitives / DOM
Start with one: copy to the clipboard
import { mapMessage } from 'foldkit/command'
import { defineMessageUnion } from 'foldkit/message'
import { ClipboardMessage, copyText } from 'foldkit-primitives/dom'
const Message = defineMessageUnion({
CopyClicked: {},
Clipboard: { message: ClipboardMessage },
})
type Model = { readonly text: string; readonly status: string }
const update = (model: Model, message: typeof Message.Type) =>
Message.match(message, {
CopyClicked: () => ({
model,
commands: [mapMessage(copyText(model.text), message => Message.Clipboard({ message }))],
}),
Clipboard: ({ message }) => ({
model: {
...model,
status: ClipboardMessage.match(message, {
Copied: () => 'Copied',
CopyFailed: ({ message }) => message,
}),
},
}),
})copyText describes a Command; returning it from update lets the runtime
perform the write. mapMessage wraps its result into the parent's union, so
success and failure land in the same reducer, and the clipboard never enters
the Model: it is not application state. readText() reads the same way.
The Commands
share(data) posts { title?, text?, url? } to the platform sheet:
Shared on success, Dismissed when the user cancels the sheet (its own
outcome, not a failure), ShareFailed otherwise.
loadScript(src) appends a head script unless one carries the URL
already, so concurrent loads collapse onto the first tag and share its fate,
yielding Loaded or LoadFailed. A dead tag is removed, so a retry fetches
afresh.
Denial, an insecure context, a missing API (a server), and a network error all become the failure Message. No Command here throws.