@playfast/reform 0.0.4 → 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (209) hide show
  1. package/dist/boundary/boundary.d.ts +72 -0
  2. package/dist/boundary/boundary.d.ts.map +1 -0
  3. package/dist/boundary/boundary.js +83 -0
  4. package/dist/boundary/boundary.js.map +1 -0
  5. package/dist/calc/asyncCalc.d.ts +91 -0
  6. package/dist/calc/asyncCalc.d.ts.map +1 -0
  7. package/dist/calc/asyncCalc.js +95 -0
  8. package/dist/calc/asyncCalc.js.map +1 -0
  9. package/{src/calc/asyncData.ts → dist/calc/asyncData.d.ts} +22 -53
  10. package/dist/calc/asyncData.d.ts.map +1 -0
  11. package/dist/calc/asyncData.js +34 -0
  12. package/dist/calc/asyncData.js.map +1 -0
  13. package/dist/calc/calc.d.ts +57 -0
  14. package/dist/calc/calc.d.ts.map +1 -0
  15. package/dist/calc/calc.js +58 -0
  16. package/dist/calc/calc.js.map +1 -0
  17. package/dist/calc/calcFamily.d.ts +57 -0
  18. package/dist/calc/calcFamily.d.ts.map +1 -0
  19. package/dist/calc/calcFamily.js +124 -0
  20. package/dist/calc/calcFamily.js.map +1 -0
  21. package/dist/calc/compose.d.ts +16 -0
  22. package/dist/calc/compose.d.ts.map +1 -0
  23. package/dist/calc/compose.js +7 -0
  24. package/dist/calc/compose.js.map +1 -0
  25. package/dist/channel/channel.d.ts +115 -0
  26. package/dist/channel/channel.d.ts.map +1 -0
  27. package/dist/channel/channel.js +138 -0
  28. package/dist/channel/channel.js.map +1 -0
  29. package/dist/compose/composition.d.ts +72 -0
  30. package/dist/compose/composition.d.ts.map +1 -0
  31. package/dist/compose/composition.js +46 -0
  32. package/dist/compose/composition.js.map +1 -0
  33. package/{src/compose/host.ts → dist/compose/host.d.ts} +8 -6
  34. package/dist/compose/host.d.ts.map +1 -0
  35. package/dist/compose/host.js +6 -0
  36. package/dist/compose/host.js.map +1 -0
  37. package/dist/compose/props.d.ts +13 -0
  38. package/dist/compose/props.d.ts.map +1 -0
  39. package/{src/compose/props.ts → dist/compose/props.js} +5 -3
  40. package/dist/compose/props.js.map +1 -0
  41. package/dist/compose/provide.d.ts +22 -0
  42. package/dist/compose/provide.d.ts.map +1 -0
  43. package/dist/compose/provide.js +28 -0
  44. package/dist/compose/provide.js.map +1 -0
  45. package/{src/compose/slot.ts → dist/compose/slot.d.ts} +19 -36
  46. package/dist/compose/slot.d.ts.map +1 -0
  47. package/dist/compose/slot.js +23 -0
  48. package/dist/compose/slot.js.map +1 -0
  49. package/dist/compose/ui.d.ts +135 -0
  50. package/dist/compose/ui.d.ts.map +1 -0
  51. package/dist/compose/ui.js +63 -0
  52. package/dist/compose/ui.js.map +1 -0
  53. package/dist/definition/definition.d.ts +33 -0
  54. package/dist/definition/definition.d.ts.map +1 -0
  55. package/dist/definition/definition.js +42 -0
  56. package/dist/definition/definition.js.map +1 -0
  57. package/dist/event/event.d.ts +33 -0
  58. package/dist/event/event.d.ts.map +1 -0
  59. package/dist/event/event.js +30 -0
  60. package/dist/event/event.js.map +1 -0
  61. package/dist/event/eventGroup.d.ts +9 -0
  62. package/dist/event/eventGroup.d.ts.map +1 -0
  63. package/dist/event/eventGroup.js +4 -0
  64. package/dist/event/eventGroup.js.map +1 -0
  65. package/{src/feature/feature.ts → dist/feature/feature.d.ts} +92 -178
  66. package/dist/feature/feature.d.ts.map +1 -0
  67. package/dist/feature/feature.js +98 -0
  68. package/dist/feature/feature.js.map +1 -0
  69. package/dist/index.d.ts +53 -0
  70. package/dist/index.d.ts.map +1 -0
  71. package/dist/index.js +62 -0
  72. package/dist/index.js.map +1 -0
  73. package/{src/internal/capture.ts → dist/internal/capture.d.ts} +11 -13
  74. package/dist/internal/capture.d.ts.map +1 -0
  75. package/dist/internal/capture.js +12 -0
  76. package/dist/internal/capture.js.map +1 -0
  77. package/{src/internal/ctx.ts → dist/internal/ctx.d.ts} +4 -8
  78. package/dist/internal/ctx.d.ts.map +1 -0
  79. package/dist/internal/ctx.js +2 -0
  80. package/dist/internal/ctx.js.map +1 -0
  81. package/dist/internal/errors.d.ts +89 -0
  82. package/dist/internal/errors.d.ts.map +1 -0
  83. package/dist/internal/errors.js +102 -0
  84. package/dist/internal/errors.js.map +1 -0
  85. package/dist/internal/inspect.d.ts +17 -0
  86. package/dist/internal/inspect.d.ts.map +1 -0
  87. package/dist/internal/inspect.js +32 -0
  88. package/dist/internal/inspect.js.map +1 -0
  89. package/dist/internal/queryDriver.d.ts +65 -0
  90. package/dist/internal/queryDriver.d.ts.map +1 -0
  91. package/dist/internal/queryDriver.js +134 -0
  92. package/dist/internal/queryDriver.js.map +1 -0
  93. package/dist/internal/reuse.d.ts +10 -0
  94. package/dist/internal/reuse.d.ts.map +1 -0
  95. package/dist/internal/reuse.js +68 -0
  96. package/dist/internal/reuse.js.map +1 -0
  97. package/dist/internal/scheduler.d.ts +47 -0
  98. package/dist/internal/scheduler.d.ts.map +1 -0
  99. package/dist/internal/scheduler.js +70 -0
  100. package/dist/internal/scheduler.js.map +1 -0
  101. package/{src/internal/seeds.ts → dist/internal/seeds.d.ts} +3 -6
  102. package/dist/internal/seeds.d.ts.map +1 -0
  103. package/dist/internal/seeds.js +17 -0
  104. package/dist/internal/seeds.js.map +1 -0
  105. package/dist/internal/sources.d.ts +39 -0
  106. package/dist/internal/sources.d.ts.map +1 -0
  107. package/dist/internal/sources.js +59 -0
  108. package/dist/internal/sources.js.map +1 -0
  109. package/dist/internal/stateRegistry.d.ts +2 -0
  110. package/dist/internal/stateRegistry.d.ts.map +1 -0
  111. package/dist/internal/stateRegistry.js +28 -0
  112. package/dist/internal/stateRegistry.js.map +1 -0
  113. package/dist/internal/store.d.ts +47 -0
  114. package/dist/internal/store.d.ts.map +1 -0
  115. package/dist/internal/store.js +73 -0
  116. package/dist/internal/store.js.map +1 -0
  117. package/{src/internal/track.ts → dist/internal/track.d.ts} +11 -15
  118. package/dist/internal/track.d.ts.map +1 -0
  119. package/dist/internal/track.js +19 -0
  120. package/dist/internal/track.js.map +1 -0
  121. package/dist/procedure/procedure.d.ts +40 -0
  122. package/dist/procedure/procedure.d.ts.map +1 -0
  123. package/dist/procedure/procedure.js +50 -0
  124. package/dist/procedure/procedure.js.map +1 -0
  125. package/dist/reducer/reducer.d.ts +44 -0
  126. package/dist/reducer/reducer.d.ts.map +1 -0
  127. package/dist/reducer/reducer.js +63 -0
  128. package/dist/reducer/reducer.js.map +1 -0
  129. package/dist/remote/remoteState.d.ts +119 -0
  130. package/dist/remote/remoteState.d.ts.map +1 -0
  131. package/dist/remote/remoteState.js +270 -0
  132. package/dist/remote/remoteState.js.map +1 -0
  133. package/dist/runtime/bus.d.ts +27 -0
  134. package/dist/runtime/bus.d.ts.map +1 -0
  135. package/{src/runtime/bus.ts → dist/runtime/bus.js} +8 -23
  136. package/dist/runtime/bus.js.map +1 -0
  137. package/dist/runtime/loop.d.ts +45 -0
  138. package/dist/runtime/loop.d.ts.map +1 -0
  139. package/dist/runtime/loop.js +117 -0
  140. package/dist/runtime/loop.js.map +1 -0
  141. package/dist/scene/scene.d.ts +44 -0
  142. package/dist/scene/scene.d.ts.map +1 -0
  143. package/dist/scene/scene.js +31 -0
  144. package/dist/scene/scene.js.map +1 -0
  145. package/dist/state/state.d.ts +37 -0
  146. package/dist/state/state.d.ts.map +1 -0
  147. package/dist/state/state.js +46 -0
  148. package/dist/state/state.js.map +1 -0
  149. package/dist/state/stateFamily.d.ts +79 -0
  150. package/dist/state/stateFamily.d.ts.map +1 -0
  151. package/dist/state/stateFamily.js +99 -0
  152. package/dist/state/stateFamily.js.map +1 -0
  153. package/dist/state/stateGroup.d.ts +50 -0
  154. package/dist/state/stateGroup.d.ts.map +1 -0
  155. package/dist/state/stateGroup.js +54 -0
  156. package/dist/state/stateGroup.js.map +1 -0
  157. package/{src/state/token.ts → dist/state/token.d.ts} +13 -21
  158. package/dist/state/token.d.ts.map +1 -0
  159. package/dist/state/token.js +20 -0
  160. package/dist/state/token.js.map +1 -0
  161. package/dist/synced/syncedStore.d.ts +51 -0
  162. package/dist/synced/syncedStore.d.ts.map +1 -0
  163. package/dist/synced/syncedStore.js +43 -0
  164. package/dist/synced/syncedStore.js.map +1 -0
  165. package/{src/ui/node.ts → dist/ui/node.d.ts} +3 -3
  166. package/dist/ui/node.d.ts.map +1 -0
  167. package/dist/ui/node.js +2 -0
  168. package/dist/ui/node.js.map +1 -0
  169. package/{src/ui/trigger.ts → dist/ui/trigger.d.ts} +2 -1
  170. package/dist/ui/trigger.d.ts.map +1 -0
  171. package/dist/ui/trigger.js +2 -0
  172. package/dist/ui/trigger.js.map +1 -0
  173. package/dist/wire/tree.d.ts +66 -0
  174. package/dist/wire/tree.d.ts.map +1 -0
  175. package/dist/wire/tree.js +60 -0
  176. package/dist/wire/tree.js.map +1 -0
  177. package/dist/wire/triggers.d.ts +44 -0
  178. package/dist/wire/triggers.d.ts.map +1 -0
  179. package/dist/wire/triggers.js +31 -0
  180. package/dist/wire/triggers.js.map +1 -0
  181. package/package.json +32 -11
  182. package/src/boundary/boundary.ts +0 -192
  183. package/src/calc/asyncCalc.ts +0 -267
  184. package/src/calc/calc.ts +0 -120
  185. package/src/calc/calcFamily.ts +0 -194
  186. package/src/calc/compose.ts +0 -69
  187. package/src/channel/channel.ts +0 -265
  188. package/src/compose/composition.ts +0 -112
  189. package/src/compose/provide.ts +0 -70
  190. package/src/compose/ui.ts +0 -97
  191. package/src/definition/definition.ts +0 -74
  192. package/src/event/event.ts +0 -65
  193. package/src/event/eventGroup.ts +0 -14
  194. package/src/index.ts +0 -140
  195. package/src/internal/errors.ts +0 -69
  196. package/src/internal/inspect.ts +0 -34
  197. package/src/internal/queryDriver.ts +0 -247
  198. package/src/internal/reuse.ts +0 -73
  199. package/src/internal/scheduler.ts +0 -91
  200. package/src/internal/sources.ts +0 -104
  201. package/src/internal/store.ts +0 -105
  202. package/src/procedure/procedure.ts +0 -89
  203. package/src/reducer/reducer.ts +0 -137
  204. package/src/remote/remoteState.ts +0 -571
  205. package/src/runtime/loop.ts +0 -169
  206. package/src/scene/scene.ts +0 -76
  207. package/src/state/state.ts +0 -91
  208. package/src/state/stateFamily.ts +0 -171
  209. package/src/state/stateGroup.ts +0 -78
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scene.js","sourceRoot":"","sources":["../../src/scene/scene.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAA;AAG9B,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAA;AAgCxD;;;GAGG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,CACnB,WAAyC,EACzC,MAGC,EACS,EAAE,CAAC,CAAC;IACd,IAAI,EAAE,OAAO;IACb,WAAW;IACX,OAAO,EAAE,MAAM,CAAC,OAAO;IACvB,GAAG,CAAC,MAAM,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;CAC5D,CAAC,CAAA;AAEF;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,CACvB,IAAc,EACd,KAAwC,EAC9B,EAAE,CACZ,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,KAAK,CAAC;IAC7B,CAAC,CAAC,IAAI;IACN,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,oBAAoB,EAAE,KAAK,CAAC,CAAC,EAAE,CAAA;AAExF,wDAAwD;AACxD,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,CAAU,EAAc,EAAE,CAChD,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI,IAAK,CAAiC,CAAC,IAAI,KAAK,OAAO,CAAA"}
@@ -0,0 +1,37 @@
1
+ import { Context, Effect, Layer, Schema } from 'effect';
2
+ import { type Manifest } from '../definition/definition';
3
+ import { type Store } from '../internal/store';
4
+ export interface StateOptions {
5
+ readonly title?: string;
6
+ readonly description?: string;
7
+ }
8
+ export interface StateManifest<N extends string, A> extends Manifest {
9
+ readonly kind: 'State';
10
+ readonly name: N;
11
+ readonly schema: Schema.Schema<A, any>;
12
+ readonly title?: string;
13
+ readonly description?: string;
14
+ }
15
+ export interface StateClass<out N extends string, in out A> extends Effect.Effect<A, never, Store<A>> {
16
+ new (): {};
17
+ readonly manifest: StateManifest<N, A>;
18
+ /** Internal DI tag holding the live store. The loop reads/writes through it. */
19
+ readonly store: Context.Tag<Store<A>, Store<A>>;
20
+ }
21
+ export type AnyState = StateClass<string, any>;
22
+ export type StateValue<S> = S extends StateClass<string, infer A> ? A : never;
23
+ export type StateName<S> = S extends StateClass<infer N, any> ? N : never;
24
+ /**
25
+ * Atomic reactive state. `State.make` is the *definition* (a reflectable
26
+ * manifest + an internal store tag); it carries no starting value — the seed is
27
+ * an implementation detail supplied at create-time by `State.live(state, seed)`.
28
+ * Composed into a `StateGroup` exactly as `@effect/rpc` composes rpcs.
29
+ */
30
+ export declare const make: <const N extends string, A>(name: N, schema: Schema.Schema<A, any>, options?: StateOptions) => StateClass<N, A>;
31
+ /**
32
+ * Allocate a state's store, seeded with `initial` — `State.live(Feed, seed)`.
33
+ * The seed lives here (implementation), not on the definition, so the same
34
+ * definition can boot from different values in app vs. test wiring.
35
+ */
36
+ export declare const live: <S extends AnyState>(state: S, initial: StateValue<S>) => Layer.Layer<Store<StateValue<S>>>;
37
+ //# sourceMappingURL=state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../src/state/state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAY,KAAK,EAAU,MAAM,EAAE,MAAM,QAAQ,CAAA;AACzE,OAAO,EAAE,KAAK,QAAQ,EAAkB,MAAM,0BAA0B,CAAA;AAIxE,OAAO,EAAa,KAAK,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAGzD,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAC9B;AAED,MAAM,WAAW,aAAa,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,CAAE,SAAQ,QAAQ;IAClE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;IACtB,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAA;IAChB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;IACtC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAC9B;AAED,MAAM,WAAW,UAAU,CAAC,GAAG,CAAC,CAAC,SAAS,MAAM,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,CAAE,SAAQ,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;IACnG,QAAQ,EAAE,CAAA;IACV,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IACtC,gFAAgF;IAChF,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;CAChD;AAED,MAAM,MAAM,QAAQ,GAAG,UAAU,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;AAC9C,MAAM,MAAM,UAAU,CAAC,CAAC,IAAI,CAAC,SAAS,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAA;AAC7E,MAAM,MAAM,SAAS,CAAC,CAAC,IAAI,CAAC,SAAS,UAAU,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAA;AAEzE;;;;;GAKG;AACH,eAAO,MAAM,IAAI,GAAI,KAAK,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,EAC5C,MAAM,CAAC,EACP,QAAQ,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,GAAG,CAAC,EAC7B,UAAS,YAAiB,KACzB,UAAU,CAAC,CAAC,EAAE,CAAC,CAajB,CAAA;AAwBD;;;;GAIG;AACH,eAAO,MAAM,IAAI,GAAI,CAAC,SAAS,QAAQ,EACrC,OAAO,CAAC,EACR,SAAS,UAAU,CAAC,CAAC,CAAC,KACrB,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAMhC,CAAA"}
@@ -0,0 +1,46 @@
1
+ import { Context, Effect, FiberRef, Layer, Option, Schema } from 'effect';
2
+ import { yieldableClass } from '../definition/definition';
3
+ import { resolveScheduler } from '../internal/scheduler';
4
+ import { CurrentSeedOverrides } from '../internal/seeds';
5
+ import { claimStateTag } from '../internal/stateRegistry';
6
+ import { makeStore } from '../internal/store';
7
+ import { readTracked } from '../internal/track';
8
+ /**
9
+ * Atomic reactive state. `State.make` is the *definition* (a reflectable
10
+ * manifest + an internal store tag); it carries no starting value — the seed is
11
+ * an implementation detail supplied at create-time by `State.live(state, seed)`.
12
+ * Composed into a `StateGroup` exactly as `@effect/rpc` composes rpcs.
13
+ */
14
+ export const make = (name, schema, options = {}) => {
15
+ const identifier = `reform/state/${name}`;
16
+ claimStateTag(identifier);
17
+ const store = Context.GenericTag(identifier);
18
+ const manifest = {
19
+ kind: 'State',
20
+ name,
21
+ schema,
22
+ ...(options.title !== undefined ? { title: options.title } : {}),
23
+ ...(options.description !== undefined ? { description: options.description } : {}),
24
+ };
25
+ const read = Effect.flatMap(store, readTracked);
26
+ return yieldableClass(read, { manifest, store });
27
+ };
28
+ /**
29
+ * Resolve the value a store should boot from: the ambient seed override when
30
+ * one is present (and valid) for this state's member name, else the authored
31
+ * `initial`. Reads `CurrentSeedOverrides` — empty outside the tooling seam
32
+ * (`Scene.seedScene`), so production wiring always boots from `initial`. An
33
+ * override is decoded against the state's schema; an invalid value silently
34
+ * falls back to `initial` — a half-typed override from the dev tool must never
35
+ * crash a preview.
36
+ */
37
+ const resolveSeed = (state, initial) => Effect.map(FiberRef.get(CurrentSeedOverrides), (overrides) => state.manifest.name in overrides
38
+ ? Option.getOrElse(Schema.decodeUnknownOption(state.manifest.schema)(overrides[state.manifest.name]), () => initial)
39
+ : initial);
40
+ /**
41
+ * Allocate a state's store, seeded with `initial` — `State.live(Feed, seed)`.
42
+ * The seed lives here (implementation), not on the definition, so the same
43
+ * definition can boot from different values in app vs. test wiring.
44
+ */
45
+ export const live = (state, initial) => Layer.effect(state.store, Effect.zipWith(resolveScheduler, resolveSeed(state, initial), (scheduler, seed) => makeStore(seed, scheduler)));
46
+ //# sourceMappingURL=state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.js","sourceRoot":"","sources":["../../src/state/state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AACzE,OAAO,EAAiB,cAAc,EAAE,MAAM,0BAA0B,CAAA;AACxE,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AACxD,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAA;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAA;AACzD,OAAO,EAAE,SAAS,EAAc,MAAM,mBAAmB,CAAA;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AA0B/C;;;;;GAKG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,CAClB,IAAO,EACP,MAA6B,EAC7B,UAAwB,EAAE,EACR,EAAE;IACpB,MAAM,UAAU,GAAG,gBAAgB,IAAI,EAAE,CAAA;IACzC,aAAa,CAAC,UAAU,CAAC,CAAA;IACzB,MAAM,KAAK,GAAG,OAAO,CAAC,UAAU,CAAqB,UAAU,CAAC,CAAA;IAChE,MAAM,QAAQ,GAAwB;QACpC,IAAI,EAAE,OAAO;QACb,IAAI;QACJ,MAAM;QACN,GAAG,CAAC,OAAO,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAChE,GAAG,CAAC,OAAO,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACnF,CAAA;IACD,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,WAAW,CAAC,CAAA;IAC/C,OAAO,cAAc,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAA;AAClD,CAAC,CAAA;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,GAAG,CAClB,KAAQ,EACR,OAAsB,EACQ,EAAE,CAChC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,oBAAoB,CAAC,EAAE,CAAC,SAAS,EAAE,EAAE,CAC3D,KAAK,CAAC,QAAQ,CAAC,IAAI,IAAI,SAAS;IAC9B,CAAC,CAAC,MAAM,CAAC,SAAS,CACd,MAAM,CAAC,mBAAmB,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,EACjF,GAAG,EAAE,CAAC,OAAO,CACd;IACH,CAAC,CAAC,OAAO,CACZ,CAAA;AAEH;;;;GAIG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,CAClB,KAAQ,EACR,OAAsB,EACa,EAAE,CACrC,KAAK,CAAC,MAAM,CACV,KAAK,CAAC,KAAK,EACX,MAAM,CAAC,OAAO,CAAC,gBAAgB,EAAE,WAAW,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,IAAI,EAAE,EAAE,CAChF,SAAS,CAAC,IAAI,EAAE,SAAS,CAAC,CAC3B,CACF,CAAA"}
@@ -0,0 +1,79 @@
1
+ import { Context, Effect, Layer, type Schema } from 'effect';
2
+ import { type Manifest } from '../definition/definition';
3
+ import { type Store } from '../internal/store';
4
+ /**
5
+ * A reducer fold returns this to evict the key it folded over, instead of a new
6
+ * value. The loop drops the entry's store from the family, so a normalized
7
+ * collection (chat messages, search hits, transient rows) does not grow without
8
+ * bound — the one fix for the otherwise-unbounded per-key `Map`.
9
+ */
10
+ export declare const Tombstone: unique symbol;
11
+ export type Tombstone = typeof Tombstone;
12
+ /** Per-key stores, created lazily so a write to one key wakes only its subscribers. */
13
+ export interface FamilyStore<K, V> {
14
+ at(key: K): Store<V>;
15
+ /**
16
+ * Drop a key's store so it stops occupying memory. A live subscriber keeps its
17
+ * own closure over the previous store, so eviction is for keys whose entity is
18
+ * gone (the component is unmounting) — re-`at`-ing the key allocates a fresh,
19
+ * reseeded store.
20
+ */
21
+ forget(key: K): void;
22
+ /** Drop every key's store — a wholesale reset of the family. */
23
+ clear(): void;
24
+ /** Number of live keys — for tests/diagnostics. */
25
+ size(): number;
26
+ }
27
+ /** Options for a family's keyed store. */
28
+ export interface FamilyOptions {
29
+ /**
30
+ * Drop a key's store automatically once it has no live subscribers (checked on
31
+ * the next microtask, so a same-commit re-subscribe — e.g. a key that just moved
32
+ * position in a list — cancels the eviction). This bounds an otherwise-unbounded
33
+ * family without explicit `Tombstone`s, but it also DISCARDS the key's value —
34
+ * re-`at`-ing a dropped key reseeds from `initial`. Use only for keys whose value
35
+ * is disposable when nothing renders them (search hits, transient rows); for a
36
+ * source-of-truth entity that may be temporarily off-screen (a virtualized list),
37
+ * keep this off and reclaim with an explicit reducer `Tombstone`. Default: off.
38
+ */
39
+ readonly evictWhenUnused?: boolean;
40
+ }
41
+ export interface StateFamilyManifest<N extends string, K, V> extends Manifest {
42
+ readonly kind: 'StateFamily';
43
+ readonly name: N;
44
+ readonly key: Schema.Schema<K, any>;
45
+ readonly value: Schema.Schema<V, any>;
46
+ readonly title?: string;
47
+ readonly description?: string;
48
+ }
49
+ export interface StateFamilyClass<out N extends string, in out K, in out V> {
50
+ /** Instance carries the key phantom so `Family['Key']` resolves in `keyOf` types. */
51
+ new (): {
52
+ readonly Key: K;
53
+ };
54
+ readonly manifest: StateFamilyManifest<N, K, V>;
55
+ readonly store: Context.Tag<FamilyStore<K, V>, FamilyStore<K, V>>;
56
+ }
57
+ export type AnyFamily = StateFamilyClass<string, any, any>;
58
+ export type FamilyKey<F> = F extends StateFamilyClass<any, infer K, any> ? K : never;
59
+ export type FamilyValue<F> = F extends StateFamilyClass<any, any, infer V> ? V : never;
60
+ /**
61
+ * Normalized keyed state: one logical State per key, backed by a single family
62
+ * store. Scales with the collection without re-rendering unrelated entries.
63
+ */
64
+ export declare const make: <const N extends string, K, V>(name: N, key: Schema.Schema<K, any>, value: Schema.Schema<V, any>, options?: {
65
+ readonly title?: string;
66
+ readonly description?: string;
67
+ }) => StateFamilyClass<N, K, V>;
68
+ /**
69
+ * Read one entry by key — `StateFamily.read(ItemUi, id)`. Inside a render it
70
+ * subscribes that key's slice; elsewhere it just snapshots (D5).
71
+ */
72
+ export declare const read: <N extends string, K, V>(family: StateFamilyClass<N, K, V>, key: K) => Effect.Effect<V, never, FamilyStore<K, V>>;
73
+ /**
74
+ * Allocate a family's keyed store — `StateFamily.live(ItemUi, seed)`. The seed
75
+ * is a plain value or a factory; a factory receives the key, so a new entry can
76
+ * derive its starting value from its own id (`(id) => ({ ...blank, id }))`).
77
+ */
78
+ export declare const live: <N extends string, K, V>(family: StateFamilyClass<N, K, V>, initial: V | ((key: K) => V), options?: FamilyOptions) => Layer.Layer<FamilyStore<K, V>>;
79
+ //# sourceMappingURL=stateFamily.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stateFamily.d.ts","sourceRoot":"","sources":["../../src/state/stateFamily.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,99 @@
1
+ import { Context, Effect, Layer } from 'effect';
2
+ import { definitionClass } from '../definition/definition';
3
+ import { resolveScheduler } from '../internal/scheduler';
4
+ import { claimStateTag } from '../internal/stateRegistry';
5
+ import { makeStore } from '../internal/store';
6
+ import { readTracked } from '../internal/track';
7
+ /**
8
+ * A reducer fold returns this to evict the key it folded over, instead of a new
9
+ * value. The loop drops the entry's store from the family, so a normalized
10
+ * collection (chat messages, search hits, transient rows) does not grow without
11
+ * bound — the one fix for the otherwise-unbounded per-key `Map`.
12
+ */
13
+ export const Tombstone = Symbol.for('reform/StateFamily/Tombstone');
14
+ const makeFamilyStore = (seed, scheduler, options = {}) => {
15
+ const entries = new Map();
16
+ const evictWhenUnused = options.evictWhenUnused === true;
17
+ // Live subscriber count per key — maintained only when eviction is on.
18
+ const subscribers = new Map();
19
+ // Wrap a store's `subscribe` to ref-count, evicting the key when it falls idle.
20
+ // `get`/`set`/`getVersion` are delegated unchanged, so the loop writes and the
21
+ // host reads see the same cell; only subscribe/unsubscribe are instrumented.
22
+ const refCounted = (key, store) => ({
23
+ ...store,
24
+ subscribe: (listener) => {
25
+ subscribers.set(key, (subscribers.get(key) ?? 0) + 1);
26
+ const off = store.subscribe(listener);
27
+ const released = { done: false };
28
+ return () => {
29
+ if (released.done)
30
+ return;
31
+ released.done = true;
32
+ off();
33
+ const remaining = (subscribers.get(key) ?? 1) - 1;
34
+ if (remaining > 0) {
35
+ subscribers.set(key, remaining);
36
+ return;
37
+ }
38
+ subscribers.delete(key);
39
+ queueMicrotask(() => {
40
+ if ((subscribers.get(key) ?? 0) === 0)
41
+ entries.delete(key);
42
+ });
43
+ };
44
+ },
45
+ });
46
+ return {
47
+ at: (key) => {
48
+ const existing = entries.get(key);
49
+ if (existing !== undefined)
50
+ return existing;
51
+ const base = makeStore(seed(key), scheduler);
52
+ const created = evictWhenUnused ? refCounted(key, base) : base;
53
+ entries.set(key, created);
54
+ return created;
55
+ },
56
+ forget: (key) => {
57
+ entries.delete(key);
58
+ subscribers.delete(key);
59
+ },
60
+ clear: () => {
61
+ entries.clear();
62
+ subscribers.clear();
63
+ },
64
+ size: () => entries.size,
65
+ };
66
+ };
67
+ /**
68
+ * Normalized keyed state: one logical State per key, backed by a single family
69
+ * store. Scales with the collection without re-rendering unrelated entries.
70
+ */
71
+ export const make = (name, key, value, options = {}) => {
72
+ const identifier = `reform/family/${name}`;
73
+ claimStateTag(identifier);
74
+ const store = Context.GenericTag(identifier);
75
+ const manifest = {
76
+ kind: 'StateFamily',
77
+ name,
78
+ key,
79
+ value,
80
+ ...(options.title !== undefined ? { title: options.title } : {}),
81
+ ...(options.description !== undefined ? { description: options.description } : {}),
82
+ };
83
+ return definitionClass({ manifest, store });
84
+ };
85
+ /**
86
+ * Read one entry by key — `StateFamily.read(ItemUi, id)`. Inside a render it
87
+ * subscribes that key's slice; elsewhere it just snapshots (D5).
88
+ */
89
+ export const read = (family, key) => Effect.flatMap(family.store, (fs) => readTracked(fs.at(key)));
90
+ /**
91
+ * Allocate a family's keyed store — `StateFamily.live(ItemUi, seed)`. The seed
92
+ * is a plain value or a factory; a factory receives the key, so a new entry can
93
+ * derive its starting value from its own id (`(id) => ({ ...blank, id }))`).
94
+ */
95
+ export const live = (family, initial, options = {}) => {
96
+ const seed = typeof initial === 'function' ? initial : () => initial;
97
+ return Layer.effect(family.store, Effect.map(resolveScheduler, (scheduler) => makeFamilyStore(seed, scheduler, options)));
98
+ };
99
+ //# sourceMappingURL=stateFamily.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stateFamily.js","sourceRoot":"","sources":["../../src/state/stateFamily.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ import { Layer } from 'effect';
2
+ import { type StoresOf } from '../internal/sources';
3
+ import { type AnyState, type StateClass, type StateName } from './state';
4
+ import { StateToken } from './token';
5
+ type ValueForName<Members extends ReadonlyArray<AnyState>, N extends string> = Extract<Members[number], StateClass<N, any>> extends StateClass<any, infer A> ? A : never;
6
+ export interface StateGroupClass<Members extends ReadonlyArray<AnyState>> {
7
+ new (): {};
8
+ readonly kind: 'StateGroup';
9
+ readonly members: Members;
10
+ /** Members indexed by name, so `select` is an O(1) lookup instead of a scan. */
11
+ readonly byName: ReadonlyMap<string, AnyState>;
12
+ }
13
+ export type AnyStateGroup = StateGroupClass<ReadonlyArray<AnyState>>;
14
+ /**
15
+ * Compile-time uniqueness guard for `StateGroup.make`. Member names key the tag,
16
+ * the seed record, `byName`, and `select` — duplicates are unaddressable, so a
17
+ * repeated name is replaced (positionally) by this marker tuple, which a real
18
+ * `StateClass` is not assignable to. The offending argument fails to typecheck
19
+ * with the colliding name spelled out in the message, rather than collapsing
20
+ * silently. Runtime `make` throws the same clash for seeds the root tsconfig
21
+ * never typechecks (test files live outside it).
22
+ */
23
+ type DuplicateStateName<N extends string> = readonly ['reform: duplicate state name in group', N];
24
+ type NoDuplicateNames<Members extends ReadonlyArray<AnyState>, Seen extends string = never> = Members extends readonly [infer Head extends AnyState, ...infer Tail extends ReadonlyArray<AnyState>] ? readonly [
25
+ StateName<Head> extends Seen ? DuplicateStateName<StateName<Head>> : Head,
26
+ ...NoDuplicateNames<Tail, Seen | StateName<Head>>
27
+ ] : readonly [];
28
+ export type GroupSeeds<G extends AnyStateGroup> = G extends StateGroupClass<infer Members> ? {
29
+ readonly [N in StateName<Members[number]>]: ValueForName<Members, N>;
30
+ } : never;
31
+ /** Compose atomic States into a group provided (and addressed) as a unit. */
32
+ export declare const make: <const Members extends ReadonlyArray<AnyState>>(...members: Members & NoDuplicateNames<Members>) => StateGroupClass<Members>;
33
+ /**
34
+ * Address a member by its tag — `StateGroup.select(TodosStates, 'feed')` —
35
+ * yielding a `StateToken` for reads and calc inputs (still `yield*`-able).
36
+ *
37
+ * Data-first only (not `dual`): the member name's type depends on the group, and
38
+ * a group is not `Pipeable`, so a data-last form would be both more verbose and
39
+ * harder to type than the direct call. Effect reserves `dual` for operators on a
40
+ * `Pipeable` self with an independent value arg (e.g. `ref.pipe(Ref.set(v))`);
41
+ * this is not that shape.
42
+ */
43
+ export declare const select: <Members extends ReadonlyArray<AnyState>, N extends StateName<Members[number]>>(group: StateGroupClass<Members>, name: N) => StateToken<N, ValueForName<Members, N>>;
44
+ /**
45
+ * Allocate every member's store as one merged layer, each seeded from `seeds`
46
+ * keyed by member name — `StateGroup.live(BoardStates, { board: { _tag: 'Idle' } })`.
47
+ */
48
+ export declare const live: <Members extends ReadonlyArray<AnyState>>(group: StateGroupClass<Members>, seeds: GroupSeeds<StateGroupClass<Members>>) => Layer.Layer<StoresOf<Members>>;
49
+ export {};
50
+ //# sourceMappingURL=stateGroup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stateGroup.d.ts","sourceRoot":"","sources":["../../src/state/stateGroup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAA;AAM9B,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AACnD,OAAO,EAAE,KAAK,QAAQ,EAAqB,KAAK,UAAU,EAAE,KAAK,SAAS,EAAE,MAAM,SAAS,CAAA;AAC3F,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAEpC,KAAK,YAAY,CAAC,OAAO,SAAS,aAAa,CAAC,QAAQ,CAAC,EAAE,CAAC,SAAS,MAAM,IACzE,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,SAAS,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAA;AAE3F,MAAM,WAAW,eAAe,CAAC,OAAO,SAAS,aAAa,CAAC,QAAQ,CAAC;IACtE,QAAQ,EAAE,CAAA;IACV,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAA;IAC3B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,gFAAgF;IAChF,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;CAC/C;AAED,MAAM,MAAM,aAAa,GAAG,eAAe,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAA;AAEpE;;;;;;;;GAQG;AACH,KAAK,kBAAkB,CAAC,CAAC,SAAS,MAAM,IAAI,SAAS,CAAC,uCAAuC,EAAE,CAAC,CAAC,CAAA;AAEjG,KAAK,gBAAgB,CACnB,OAAO,SAAS,aAAa,CAAC,QAAQ,CAAC,EACvC,IAAI,SAAS,MAAM,GAAG,KAAK,IACzB,OAAO,SAAS,SAAS,CAAC,MAAM,IAAI,SAAS,QAAQ,EAAE,GAAG,MAAM,IAAI,SAAS,aAAa,CAAC,QAAQ,CAAC,CAAC,GACrG,SAAS;IACP,SAAS,CAAC,IAAI,CAAC,SAAS,IAAI,GAAG,kBAAkB,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI;IACzE,GAAG,gBAAgB,CAAC,IAAI,EAAE,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;CAClD,GACD,SAAS,EAAE,CAAA;AAMf,MAAM,MAAM,UAAU,CAAC,CAAC,SAAS,aAAa,IAC5C,CAAC,SAAS,eAAe,CAAC,MAAM,OAAO,CAAC,GACpC;IAAE,QAAQ,EAAE,CAAC,IAAI,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,YAAY,CAAC,OAAO,EAAE,CAAC,CAAC;CAAE,GACxE,KAAK,CAAA;AAEX,6EAA6E;AAC7E,eAAO,MAAM,IAAI,GAAI,KAAK,CAAC,OAAO,SAAS,aAAa,CAAC,QAAQ,CAAC,EAChE,GAAG,SAAS,OAAO,GAAG,gBAAgB,CAAC,OAAO,CAAC,KAC9C,eAAe,CAAC,OAAO,CAWzB,CAAA;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,MAAM,GAAI,OAAO,SAAS,aAAa,CAAC,QAAQ,CAAC,EAAE,CAAC,SAAS,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,EAClG,OAAO,eAAe,CAAC,OAAO,CAAC,EAC/B,MAAM,CAAC,KACN,UAAU,CAAC,CAAC,EAAE,YAAY,CAAC,OAAO,EAAE,CAAC,CAAC,CAIxC,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,IAAI,GAAI,OAAO,SAAS,aAAa,CAAC,QAAQ,CAAC,EAC1D,OAAO,eAAe,CAAC,OAAO,CAAC,EAC/B,OAAO,UAAU,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,KAC1C,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAS/B,CAAA"}
@@ -0,0 +1,54 @@
1
+ import { Layer } from 'effect';
2
+ import { definitionClass } from '../definition/definition';
3
+ import { DuplicateRegistration, UnknownGroupState } from '../internal/errors';
4
+ // A group's members each carry a `store` tag, so the shared `StoresOf` (used for
5
+ // calc inputs too) distributes them into the union of distinct stores their
6
+ // `live` layer provides — no group-specific mapped type needed.
7
+ import {} from '../internal/sources';
8
+ import { live as stateLive } from './state';
9
+ import { StateToken } from './token';
10
+ /** Compose atomic States into a group provided (and addressed) as a unit. */
11
+ export const make = (...members) => {
12
+ // `byName` already de-dupes, so a smaller map than the member list means two
13
+ // members claimed one name — unaddressable, and a silent footgun on merge.
14
+ const names = members.map((m) => m.manifest.name);
15
+ const duplicate = names.find((name, i) => names.indexOf(name) !== i);
16
+ if (duplicate !== undefined)
17
+ throw new DuplicateRegistration({ kind: 'state in group', name: duplicate });
18
+ return definitionClass({
19
+ kind: 'StateGroup',
20
+ members,
21
+ byName: new Map(members.map((m) => [m.manifest.name, m])),
22
+ });
23
+ };
24
+ /**
25
+ * Address a member by its tag — `StateGroup.select(TodosStates, 'feed')` —
26
+ * yielding a `StateToken` for reads and calc inputs (still `yield*`-able).
27
+ *
28
+ * Data-first only (not `dual`): the member name's type depends on the group, and
29
+ * a group is not `Pipeable`, so a data-last form would be both more verbose and
30
+ * harder to type than the direct call. Effect reserves `dual` for operators on a
31
+ * `Pipeable` self with an independent value arg (e.g. `ref.pipe(Ref.set(v))`);
32
+ * this is not that shape.
33
+ */
34
+ export const select = (group, name) => {
35
+ const member = group.byName.get(name);
36
+ if (member === undefined)
37
+ throw new UnknownGroupState({ name });
38
+ return new StateToken(name, member.store);
39
+ };
40
+ /**
41
+ * Allocate every member's store as one merged layer, each seeded from `seeds`
42
+ * keyed by member name — `StateGroup.live(BoardStates, { board: { _tag: 'Idle' } })`.
43
+ */
44
+ export const live = (group, seeds) => {
45
+ // Index the typed seed record by the member's runtime name — a genuine
46
+ // reflection boundary (string key into a mapped type). Each member's store
47
+ // layer is then merged; the union of stores is exactly `StoresOf<Members>`,
48
+ // which `reduce`'s single-layer accumulator can't express, so restate it.
49
+ const seedRecord = seeds;
50
+ return group.members
51
+ .map((m) => stateLive(m, seedRecord[m.manifest.name]))
52
+ .reduce((a, b) => Layer.merge(a, b));
53
+ };
54
+ //# sourceMappingURL=stateGroup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stateGroup.js","sourceRoot":"","sources":["../../src/state/stateGroup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAA;AAC9B,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AAC1D,OAAO,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AAC7E,iFAAiF;AACjF,4EAA4E;AAC5E,gEAAgE;AAChE,OAAO,EAAiB,MAAM,qBAAqB,CAAA;AACnD,OAAO,EAAiB,IAAI,IAAI,SAAS,EAAmC,MAAM,SAAS,CAAA;AAC3F,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AA6CpC,6EAA6E;AAC7E,MAAM,CAAC,MAAM,IAAI,GAAG,CAClB,GAAG,OAA4C,EACrB,EAAE;IAC5B,6EAA6E;IAC7E,2EAA2E;IAC3E,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;IACjD,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAA;IACpE,IAAI,SAAS,KAAK,SAAS;QAAE,MAAM,IAAI,qBAAqB,CAAC,EAAE,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAA;IACzG,OAAO,eAAe,CAA2B;QAC/C,IAAI,EAAE,YAAqB;QAC3B,OAAO;QACP,MAAM,EAAE,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAU,CAAC,CAAC;KACnE,CAAC,CAAA;AACJ,CAAC,CAAA;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,CACpB,KAA+B,EAC/B,IAAO,EACkC,EAAE;IAC3C,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;IACrC,IAAI,MAAM,KAAK,SAAS;QAAE,MAAM,IAAI,iBAAiB,CAAC,EAAE,IAAI,EAAE,CAAC,CAAA;IAC/D,OAAO,IAAI,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,KAAK,CAA4C,CAAA;AACtF,CAAC,CAAA;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,CAClB,KAA+B,EAC/B,KAA2C,EACX,EAAE;IAClC,uEAAuE;IACvE,2EAA2E;IAC3E,4EAA4E;IAC5E,0EAA0E;IAC1E,MAAM,UAAU,GAAG,KAAgC,CAAA;IACnD,OAAO,KAAK,CAAC,OAAO;SACjB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;SACrD,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAmC,CAAA;AAC1E,CAAC,CAAA"}
@@ -1,24 +1,16 @@
1
- import { Context, Effect, Effectable } from 'effect'
2
- import type { Store } from '../internal/store'
3
- import { readTracked } from '../internal/track'
4
-
1
+ import { Context, Effect, Effectable } from 'effect';
2
+ import type { Store } from '../internal/store';
5
3
  /**
6
4
  * A reference to one slice of state: yieldable to its current value (`yield*`
7
5
  * reads + — under React — subscribes) and carrying the metadata calcs need
8
6
  * (its `name` and backing store tag). Returned by `StateGroup.select(group, name)`.
9
7
  */
10
- export class StateToken<out N extends string, in out A> extends Effectable.Class<A, never, Store<A>> {
11
- constructor(
12
- readonly name: N,
13
- readonly store: Context.Tag<Store<A>, Store<A>>,
14
- ) {
15
- super()
16
- }
17
- commit(): Effect.Effect<A, never, Store<A>> {
18
- return Effect.flatMap(this.store, readTracked)
19
- }
8
+ export declare class StateToken<out N extends string, in out A> extends Effectable.Class<A, never, Store<A>> {
9
+ readonly name: N;
10
+ readonly store: Context.Tag<Store<A>, Store<A>>;
11
+ constructor(name: N, store: Context.Tag<Store<A>, Store<A>>);
12
+ commit(): Effect.Effect<A, never, Store<A>>;
20
13
  }
21
-
22
14
  /**
23
15
  * Anything a derived value can read and depend on: a named slice backed by a
24
16
  * subscribable store tag. A `StateToken` (group member), a `Calc`, and an
@@ -29,10 +21,10 @@ export class StateToken<out N extends string, in out A> extends Effectable.Class
29
21
  * satisfy the same shape so the three are interchangeable as calc inputs.
30
22
  */
31
23
  export interface Source<out N extends string, in out A> {
32
- readonly name: N
33
- readonly store: Context.Tag<Store<A>, Store<A>>
24
+ readonly name: N;
25
+ readonly store: Context.Tag<Store<A>, Store<A>>;
34
26
  }
35
-
36
- export type AnySource = Source<string, any>
37
- export type SourceName<S> = S extends Source<infer N, any> ? N : never
38
- export type SourceValue<S> = S extends Source<any, infer A> ? A : never
27
+ export type AnySource = Source<string, any>;
28
+ export type SourceName<S> = S extends Source<infer N, any> ? N : never;
29
+ export type SourceValue<S> = S extends Source<any, infer A> ? A : never;
30
+ //# sourceMappingURL=token.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token.d.ts","sourceRoot":"","sources":["../../src/state/token.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AACpD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAG9C;;;;GAIG;AACH,qBAAa,UAAU,CAAC,GAAG,CAAC,CAAC,SAAS,MAAM,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,CAAE,SAAQ,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;IAClG,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAA;IAChB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;gBACnC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;IAK3D,MAAM,IAAI,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;CAG5C;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,MAAM,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC;IACpD,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAA;IAChB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;CAChD;AAED,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;AAC3C,MAAM,MAAM,UAAU,CAAC,CAAC,IAAI,CAAC,SAAS,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAA;AACtE,MAAM,MAAM,WAAW,CAAC,CAAC,IAAI,CAAC,SAAS,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAA"}
@@ -0,0 +1,20 @@
1
+ import { Context, Effect, Effectable } from 'effect';
2
+ import { readTracked } from '../internal/track';
3
+ /**
4
+ * A reference to one slice of state: yieldable to its current value (`yield*`
5
+ * reads + — under React — subscribes) and carrying the metadata calcs need
6
+ * (its `name` and backing store tag). Returned by `StateGroup.select(group, name)`.
7
+ */
8
+ export class StateToken extends Effectable.Class {
9
+ name;
10
+ store;
11
+ constructor(name, store) {
12
+ super();
13
+ this.name = name;
14
+ this.store = store;
15
+ }
16
+ commit() {
17
+ return Effect.flatMap(this.store, readTracked);
18
+ }
19
+ }
20
+ //# sourceMappingURL=token.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token.js","sourceRoot":"","sources":["../../src/state/token.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AAEpD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAE/C;;;;GAIG;AACH,MAAM,OAAO,UAA2C,SAAQ,UAAU,CAAC,KAAyB;IACzF,IAAI,CAAG;IACP,KAAK,CAAiC;IAC/C,YAAY,IAAO,EAAE,KAAsC;QACzD,KAAK,EAAE,CAAA;QACP,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;QAChB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAA;IACpB,CAAC;IACD,MAAM;QACJ,OAAO,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,WAAW,CAAC,CAAA;IAChD,CAAC;CACF"}
@@ -0,0 +1,51 @@
1
+ import { Context, Effect, Layer, type Schema, type Scope } from 'effect';
2
+ import { type Manifest } from '../definition/definition';
3
+ import { type Store } from '../internal/store';
4
+ import type { Source } from '../state/token';
5
+ import type { StateOptions } from '../state/state';
6
+ /**
7
+ * The contract an external reactive source implements. `snapshot` must return a
8
+ * stable reference until the value actually changes (the `makeDerivedStore`
9
+ * memoization contract `useSyncExternalStore` requires); `subscribe` returns an
10
+ * unsubscribe thunk, fired on every upstream change.
11
+ */
12
+ export interface SyncedSource<A> {
13
+ readonly snapshot: () => A;
14
+ readonly subscribe: (onChange: () => void) => () => void;
15
+ }
16
+ export interface SyncedStoreManifest<N extends string, A> extends Manifest {
17
+ readonly kind: 'SyncedStore';
18
+ readonly name: N;
19
+ readonly schema: Schema.Schema<A, any>;
20
+ readonly title?: string;
21
+ readonly description?: string;
22
+ }
23
+ export interface SyncedStoreClass<out N extends string, in out A> extends Effect.Effect<A, never, Store<A>>, Source<N, A> {
24
+ new (): {};
25
+ readonly manifest: SyncedStoreManifest<N, A>;
26
+ /** Internal DI tag holding the live store. `SyncedStore.live` allocates it. */
27
+ readonly store: Context.Tag<Store<A>, Store<A>>;
28
+ /** The name, so the class doubles as a `Source` input to a calc/composition. */
29
+ readonly name: N;
30
+ }
31
+ export type AnySyncedStore = SyncedStoreClass<string, any>;
32
+ export type SyncedValue<S> = S extends SyncedStoreClass<string, infer A> ? A : never;
33
+ /**
34
+ * Define an externally-synced slice: a reflectable manifest + an internal store
35
+ * tag, yieldable to its current value and usable as a calc/composition `Source`.
36
+ * Carries no source — that is supplied at wiring time by `SyncedStore.live`,
37
+ * exactly as `State.make` defers its seed to `State.live`.
38
+ */
39
+ export declare const make: <const N extends string, A>(name: N, schema: Schema.Schema<A, any>, options?: StateOptions) => SyncedStoreClass<N, A>;
40
+ /**
41
+ * Allocate a synced store's backing cell and bind it to an external source.
42
+ * `acquire` yields the source within the layer's scope (so it can open a live
43
+ * query / subscription whose `R` — e.g. a `Db` driver — is captured here); the
44
+ * store mirrors `snapshot()` and re-notifies on every `subscribe` change through
45
+ * the runtime's coalescing scheduler. The upstream subscription is released with
46
+ * the layer's scope.
47
+ */
48
+ export declare const live: <A, R>(def: {
49
+ readonly store: Context.Tag<Store<A>, Store<A>>;
50
+ }, acquire: Effect.Effect<SyncedSource<A>, never, R>) => Layer.Layer<Store<A>, never, Exclude<R, Scope.Scope>>;
51
+ //# sourceMappingURL=syncedStore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"syncedStore.d.ts","sourceRoot":"","sources":["../../src/synced/syncedStore.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,MAAM,EAAE,KAAK,KAAK,EAAE,MAAM,QAAQ,CAAA;AACxE,OAAO,EAAE,KAAK,QAAQ,EAAkB,MAAM,0BAA0B,CAAA;AAExE,OAAO,EAAoB,KAAK,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAEhE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AAC5C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAYlD;;;;;GAKG;AACH,MAAM,WAAW,YAAY,CAAC,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;IAC1B,QAAQ,CAAC,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,IAAI,KAAK,MAAM,IAAI,CAAA;CACzD;AAED,MAAM,WAAW,mBAAmB,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,CAAE,SAAQ,QAAQ;IACxE,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAA;IAC5B,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAA;IAChB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;IACtC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAC9B;AAED,MAAM,WAAW,gBAAgB,CAAC,GAAG,CAAC,CAAC,SAAS,MAAM,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,CAC9D,SAAQ,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,EACvC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC;IACd,QAAQ,EAAE,CAAA;IACV,QAAQ,CAAC,QAAQ,EAAE,mBAAmB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IAC5C,+EAA+E;IAC/E,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;IAC/C,gFAAgF;IAChF,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAA;CACjB;AAED,MAAM,MAAM,cAAc,GAAG,gBAAgB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;AAC1D,MAAM,MAAM,WAAW,CAAC,CAAC,IAAI,CAAC,SAAS,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAA;AAEpF;;;;;GAKG;AACH,eAAO,MAAM,IAAI,GAAI,KAAK,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,EAC5C,MAAM,CAAC,EACP,QAAQ,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,GAAG,CAAC,EAC7B,UAAS,YAAiB,KACzB,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAWvB,CAAA;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,IAAI,GAAI,CAAC,EAAE,CAAC,EAIvB,KAAK;IAAE,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;CAAE,EACxD,SAAS,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,KAChD,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,CAUpD,CAAA"}
@@ -0,0 +1,43 @@
1
+ import { Context, Effect, Layer } from 'effect';
2
+ import { yieldableClass } from '../definition/definition';
3
+ import { resolveScheduler } from '../internal/scheduler';
4
+ import { makeDerivedStore } from '../internal/store';
5
+ import { readTracked } from '../internal/track';
6
+ /**
7
+ * Define an externally-synced slice: a reflectable manifest + an internal store
8
+ * tag, yieldable to its current value and usable as a calc/composition `Source`.
9
+ * Carries no source — that is supplied at wiring time by `SyncedStore.live`,
10
+ * exactly as `State.make` defers its seed to `State.live`.
11
+ */
12
+ export const make = (name, schema, options = {}) => {
13
+ const store = Context.GenericTag(`reform/syncedStore/${name}`);
14
+ const manifest = {
15
+ kind: 'SyncedStore',
16
+ name,
17
+ schema,
18
+ ...(options.title !== undefined ? { title: options.title } : {}),
19
+ ...(options.description !== undefined ? { description: options.description } : {}),
20
+ };
21
+ const read = Effect.flatMap(store, readTracked);
22
+ return yieldableClass(read, { manifest, store, name });
23
+ };
24
+ /**
25
+ * Allocate a synced store's backing cell and bind it to an external source.
26
+ * `acquire` yields the source within the layer's scope (so it can open a live
27
+ * query / subscription whose `R` — e.g. a `Db` driver — is captured here); the
28
+ * store mirrors `snapshot()` and re-notifies on every `subscribe` change through
29
+ * the runtime's coalescing scheduler. The upstream subscription is released with
30
+ * the layer's scope.
31
+ */
32
+ export const live = (
33
+ // A minimal store-carrier — satisfied by a `SyncedStoreClass` and by any
34
+ // companion primitive (e.g. `@playfast/reform-db`'s `DbQuery`) that allocates
35
+ // its own `Store` tag, so the seam is reusable beyond `SyncedStore` itself.
36
+ def, acquire) => Layer.scoped(def.store, Effect.gen(function* () {
37
+ const scheduler = yield* resolveScheduler;
38
+ const source = yield* acquire;
39
+ const { store, unsubscribe } = makeDerivedStore(source.snapshot, source.subscribe, scheduler);
40
+ yield* Effect.addFinalizer(() => Effect.sync(unsubscribe));
41
+ return store;
42
+ }));
43
+ //# sourceMappingURL=syncedStore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"syncedStore.js","sourceRoot":"","sources":["../../src/synced/syncedStore.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAA2B,MAAM,QAAQ,CAAA;AACxE,OAAO,EAAiB,cAAc,EAAE,MAAM,0BAA0B,CAAA;AACxE,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AACxD,OAAO,EAAE,gBAAgB,EAAc,MAAM,mBAAmB,CAAA;AAChE,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AA+C/C;;;;;GAKG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,CAClB,IAAO,EACP,MAA6B,EAC7B,UAAwB,EAAE,EACF,EAAE;IAC1B,MAAM,KAAK,GAAG,OAAO,CAAC,UAAU,CAAqB,sBAAsB,IAAI,EAAE,CAAC,CAAA;IAClF,MAAM,QAAQ,GAA8B;QAC1C,IAAI,EAAE,aAAa;QACnB,IAAI;QACJ,MAAM;QACN,GAAG,CAAC,OAAO,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAChE,GAAG,CAAC,OAAO,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACnF,CAAA;IACD,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,WAAW,CAAC,CAAA;IAC/C,OAAO,cAAc,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;AACxD,CAAC,CAAA;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG;AAClB,yEAAyE;AACzE,8EAA8E;AAC9E,4EAA4E;AAC5E,GAAwD,EACxD,OAAiD,EACM,EAAE,CACzD,KAAK,CAAC,MAAM,CACV,GAAG,CAAC,KAAK,EACT,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,gBAAgB,CAAA;IACzC,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,OAAO,CAAA;IAC7B,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,GAAG,gBAAgB,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,SAAS,EAAE,SAAS,CAAC,CAAA;IAC7F,KAAK,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAA;IAC1D,OAAO,KAAK,CAAA;AACd,CAAC,CAAC,CACH,CAAA"}
@@ -1,9 +1,9 @@
1
- import type { ReactNode } from 'react'
2
-
1
+ import type { ReactNode } from 'react';
3
2
  /**
4
3
  * What a view renders. Reform targets React, so a node is a `ReactNode` — this
5
4
  * is a *type-only* dependency: core never imports the React runtime nor renders
6
5
  * anything itself (that is `@reform/react`). Typing it precisely lets the `.ui`
7
6
  * presentations author real JSX and lets slots be valid components.
8
7
  */
9
- export type Node = ReactNode
8
+ export type Node = ReactNode;
9
+ //# sourceMappingURL=node.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../../src/ui/node.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAEtC;;;;;GAKG;AACH,MAAM,MAAM,IAAI,GAAG,SAAS,CAAA"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node.js","sourceRoot":"","sources":["../../src/ui/node.ts"],"names":[],"mappings":""}