Composition / foldkit-composition

Actions

A Button must eventually do something, and a capability ends in an existing Message. A Block names its events, a Catalog lists the actions its pages may reference, each a foldkit-surface Action, and a node stores only which action an event runs, with its input as literals:

ts
const Button = Block.define('Button', { Props, provides: [Content.Flow], events: ['press'] })
const Site = Catalog.make({ blocks, roots: [Content.Section], actions: [AddToCart] })

Composition.Op.setAction(id, 'press', { action: 'addToCart', input: { productId: 'p1' } })

const SiteRenderer = Renderer.forMessages<Message>().make(Site, {
  Button: ({ props, on, h }) => {
    const pressed = on('press') // the Message addToCart makes, or none
    return h.button(Option.match(pressed, { onNone: () => [], onSome: sent => [h.OnClick(sent)] }), [
      props.label,
    ])
  },
})
  • Checked, by validate and by setAction: an event the Block does not have or input the action's Schema refuses is composition:invalid-action, and an action the Catalog lacks is composition:unknown-action.
  • Nothing stored runs. on(event) decodes the stored input by the action's Schema and makes its Message, an Option, none when there is none; update stays the only place a Message has effects.
  • The same Action is an agent's capability through Agent.action, declared once for both.