Something went wrong. Try again.
[READ-ONLY] Mirror of https://github.com/crutchcorn/causeeffect. JSX for Effect, with generator types preserved. causeeffect.website
Something went wrong. Try again.
1.9 kB · 58 lines
at main
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859import { Schema } from 'effect';import { Submodel, type Update } from 'foldkit';import { defineMessageUnion } from 'foldkit/message';import { createJsx } from '@causeeffect/foldkit-jsx';
export const Model = Schema.Struct({ count: Schema.Number });export type Model = typeof Model.Type;
export const Message = defineMessageUnion({ ClickedDecrement: {}, ClickedIncrement: {}, ClickedReset: {},});export type Message = typeof Message.Type;
export const init = (): Model => ({ count: 0 });
export const update = (model: Model, message: Message) => Message.match<Update.Return<Model, Message>>(message, { ClickedDecrement: () => ({ model: { count: model.count - 1 } }), ClickedIncrement: () => ({ model: { count: model.count + 1 } }), ClickedReset: () => ({ model: init() }), });
// Parent-driven resets still use the child's update, just like button clicks.export const reset = (model: Model) => update(model, Message.ClickedReset());
export interface ViewInputs { readonly label: string;}
export const view = Submodel.defineView<Model, Message, ViewInputs>( (model, { label }, h) => { // Each view binds JSX to its own Message-typed Foldkit builder. const jsx = createJsx(h);
return ( <section Class="counter" Role="region" AriaLabel={label}> <p Class="eyebrow">Independent submodel</p> <h2>{label}</h2> <p Class="count" Role="status" AriaLive="polite"> {model.count} </p> <div Class="controls"> <button OnClick={Message.ClickedDecrement()} AriaLabel="Decrement"> − </button> <button OnClick={Message.ClickedReset()} Class="reset"> Reset </button> <button OnClick={Message.ClickedIncrement()} AriaLabel="Increment"> + </button> </div> </section> ); },);