import { Layer, Option, Schema as S } from 'effect' import { Composition, Engine, State, StateGroup, Ui, mount, provide, scene, type CapturedScene, type DerivedContract, ui, } from '@playfast/reform' import { type EngineServices, type WiredUi } from '@playfast/reform/internal' const LabelBase: State.StateDefinition< 'label', Option.Option, S.OptionFromSelf > = State.make('label', S.OptionFromSelf(S.String)) class Label extends LabelBase {} class Labels extends StateGroup.make(Label) {} const OptionalUiBase: WiredUi< DerivedContract<{ props: S.Struct<{ label: S.Option }> }>, 'Optional' > = ui('Optional', { props: S.Struct({ label: S.Option(S.String) }) }) export class OptionalUi extends OptionalUiBase {} class Optional extends Composition.make('Optional', { title: 'Optional', ui: OptionalUi, states: [Label], })() {} type OptionalScene = CapturedScene< typeof OptionalUi.Contract, readonly [typeof Label], | EngineServices | State.StateStore<'label', Option.Option> | Ui.UiService<'Optional'> | Composition.CompositionId<'Optional', Optional, never>, unknown, 'Optional', Optional > const makeOptionScene = (initial: Option.Option = Option.some('hi')): OptionalScene => { const presentation = Layer.mergeAll( provide( OptionalUi, Ui.make(OptionalUi, () => null), ), StateGroup.live(Labels, { label: initial }), ) const app = Layer.mergeAll( Composition.live(Optional, function* () { const label = yield* StateGroup.select(Labels, 'label') return mount({ props: { label }, slots: {} }) }), ).pipe(Layer.provideMerge(presentation), Layer.provideMerge(Engine)) return scene(Optional, { provide: [app] }) } export const optionScene: typeof makeOptionScene = makeOptionScene