@lumencast/runtime 0.1.0

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 (204) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +79 -0
  3. package/dist/.tsbuildinfo +1 -0
  4. package/dist/animate/crossfade.d.ts +13 -0
  5. package/dist/animate/crossfade.d.ts.map +1 -0
  6. package/dist/animate/crossfade.js +10 -0
  7. package/dist/animate/crossfade.js.map +1 -0
  8. package/dist/animate/keyframes.d.ts +42 -0
  9. package/dist/animate/keyframes.d.ts.map +1 -0
  10. package/dist/animate/keyframes.js +94 -0
  11. package/dist/animate/keyframes.js.map +1 -0
  12. package/dist/animate/transitions.d.ts +38 -0
  13. package/dist/animate/transitions.d.ts.map +1 -0
  14. package/dist/animate/transitions.js +81 -0
  15. package/dist/animate/transitions.js.map +1 -0
  16. package/dist/app.d.ts +16 -0
  17. package/dist/app.d.ts.map +1 -0
  18. package/dist/app.js +35 -0
  19. package/dist/app.js.map +1 -0
  20. package/dist/broadcast-BqOhSNsY.js +11 -0
  21. package/dist/broadcast-BqOhSNsY.js.map +1 -0
  22. package/dist/control-CRFn328D.js +16 -0
  23. package/dist/control-CRFn328D.js.map +1 -0
  24. package/dist/dev-entry.d.ts +2 -0
  25. package/dist/dev-entry.d.ts.map +1 -0
  26. package/dist/dev-entry.js +31 -0
  27. package/dist/dev-entry.js.map +1 -0
  28. package/dist/index-DUhPPRvw.js +583 -0
  29. package/dist/index-DUhPPRvw.js.map +1 -0
  30. package/dist/index.d.ts +4 -0
  31. package/dist/index.d.ts.map +1 -0
  32. package/dist/index.html +46 -0
  33. package/dist/index.js +3 -0
  34. package/dist/index.js.map +1 -0
  35. package/dist/internal/validate-options.d.ts +5 -0
  36. package/dist/internal/validate-options.d.ts.map +1 -0
  37. package/dist/internal/validate-options.js +19 -0
  38. package/dist/internal/validate-options.js.map +1 -0
  39. package/dist/lumencast.js +5 -0
  40. package/dist/lumencast.js.map +1 -0
  41. package/dist/modes/broadcast.d.ts +3 -0
  42. package/dist/modes/broadcast.d.ts.map +1 -0
  43. package/dist/modes/broadcast.js +9 -0
  44. package/dist/modes/broadcast.js.map +1 -0
  45. package/dist/modes/control.d.ts +4 -0
  46. package/dist/modes/control.d.ts.map +1 -0
  47. package/dist/modes/control.js +12 -0
  48. package/dist/modes/control.js.map +1 -0
  49. package/dist/modes/test.d.ts +4 -0
  50. package/dist/modes/test.d.ts.map +1 -0
  51. package/dist/modes/test.js +13 -0
  52. package/dist/modes/test.js.map +1 -0
  53. package/dist/mount.d.ts +3 -0
  54. package/dist/mount.d.ts.map +1 -0
  55. package/dist/mount.js +144 -0
  56. package/dist/mount.js.map +1 -0
  57. package/dist/overlay/control.d.ts +2 -0
  58. package/dist/overlay/control.d.ts.map +1 -0
  59. package/dist/overlay/control.js +127 -0
  60. package/dist/overlay/control.js.map +1 -0
  61. package/dist/overlay/runtime-context.d.ts +20 -0
  62. package/dist/overlay/runtime-context.d.ts.map +1 -0
  63. package/dist/overlay/runtime-context.js +14 -0
  64. package/dist/overlay/runtime-context.js.map +1 -0
  65. package/dist/overlay/status-pill.d.ts +2 -0
  66. package/dist/overlay/status-pill.d.ts.map +1 -0
  67. package/dist/overlay/status-pill.js +29 -0
  68. package/dist/overlay/status-pill.js.map +1 -0
  69. package/dist/overlay/test.d.ts +5 -0
  70. package/dist/overlay/test.d.ts.map +1 -0
  71. package/dist/overlay/test.js +116 -0
  72. package/dist/overlay/test.js.map +1 -0
  73. package/dist/render/bundle.d.ts +102 -0
  74. package/dist/render/bundle.d.ts.map +1 -0
  75. package/dist/render/bundle.js +86 -0
  76. package/dist/render/bundle.js.map +1 -0
  77. package/dist/render/fill.d.ts +41 -0
  78. package/dist/render/fill.d.ts.map +1 -0
  79. package/dist/render/fill.js +95 -0
  80. package/dist/render/fill.js.map +1 -0
  81. package/dist/render/keyframe-player.d.ts +10 -0
  82. package/dist/render/keyframe-player.d.ts.map +1 -0
  83. package/dist/render/keyframe-player.js +65 -0
  84. package/dist/render/keyframe-player.js.map +1 -0
  85. package/dist/render/primitives/frame.d.ts +12 -0
  86. package/dist/render/primitives/frame.d.ts.map +1 -0
  87. package/dist/render/primitives/frame.js +65 -0
  88. package/dist/render/primitives/frame.js.map +1 -0
  89. package/dist/render/primitives/grid.d.ts +4 -0
  90. package/dist/render/primitives/grid.d.ts.map +1 -0
  91. package/dist/render/primitives/grid.js +14 -0
  92. package/dist/render/primitives/grid.js.map +1 -0
  93. package/dist/render/primitives/image.d.ts +5 -0
  94. package/dist/render/primitives/image.d.ts.map +1 -0
  95. package/dist/render/primitives/image.js +25 -0
  96. package/dist/render/primitives/image.js.map +1 -0
  97. package/dist/render/primitives/index.d.ts +10 -0
  98. package/dist/render/primitives/index.d.ts.map +1 -0
  99. package/dist/render/primitives/index.js +22 -0
  100. package/dist/render/primitives/index.js.map +1 -0
  101. package/dist/render/primitives/instance.d.ts +4 -0
  102. package/dist/render/primitives/instance.d.ts.map +1 -0
  103. package/dist/render/primitives/instance.js +35 -0
  104. package/dist/render/primitives/instance.js.map +1 -0
  105. package/dist/render/primitives/media.d.ts +6 -0
  106. package/dist/render/primitives/media.d.ts.map +1 -0
  107. package/dist/render/primitives/media.js +19 -0
  108. package/dist/render/primitives/media.js.map +1 -0
  109. package/dist/render/primitives/shape.d.ts +12 -0
  110. package/dist/render/primitives/shape.d.ts.map +1 -0
  111. package/dist/render/primitives/shape.js +66 -0
  112. package/dist/render/primitives/shape.js.map +1 -0
  113. package/dist/render/primitives/stack.d.ts +13 -0
  114. package/dist/render/primitives/stack.d.ts.map +1 -0
  115. package/dist/render/primitives/stack.js +45 -0
  116. package/dist/render/primitives/stack.js.map +1 -0
  117. package/dist/render/primitives/text.d.ts +6 -0
  118. package/dist/render/primitives/text.d.ts.map +1 -0
  119. package/dist/render/primitives/text.js +27 -0
  120. package/dist/render/primitives/text.js.map +1 -0
  121. package/dist/render/scope.d.ts +10 -0
  122. package/dist/render/scope.d.ts.map +1 -0
  123. package/dist/render/scope.js +27 -0
  124. package/dist/render/scope.js.map +1 -0
  125. package/dist/render/stagger-context.d.ts +9 -0
  126. package/dist/render/stagger-context.d.ts.map +1 -0
  127. package/dist/render/stagger-context.js +22 -0
  128. package/dist/render/stagger-context.js.map +1 -0
  129. package/dist/render/tree.d.ts +9 -0
  130. package/dist/render/tree.d.ts.map +1 -0
  131. package/dist/render/tree.js +139 -0
  132. package/dist/render/tree.js.map +1 -0
  133. package/dist/render/universal-wrapper.d.ts +16 -0
  134. package/dist/render/universal-wrapper.d.ts.map +1 -0
  135. package/dist/render/universal-wrapper.js +58 -0
  136. package/dist/render/universal-wrapper.js.map +1 -0
  137. package/dist/state/apply-delta.d.ts +11 -0
  138. package/dist/state/apply-delta.d.ts.map +1 -0
  139. package/dist/state/apply-delta.js +23 -0
  140. package/dist/state/apply-delta.js.map +1 -0
  141. package/dist/state/apply-snapshot.d.ts +6 -0
  142. package/dist/state/apply-snapshot.d.ts.map +1 -0
  143. package/dist/state/apply-snapshot.js +6 -0
  144. package/dist/state/apply-snapshot.js.map +1 -0
  145. package/dist/state/store.d.ts +28 -0
  146. package/dist/state/store.d.ts.map +1 -0
  147. package/dist/state/store.js +119 -0
  148. package/dist/state/store.js.map +1 -0
  149. package/dist/status-pill-DCHvrd_y.js +241 -0
  150. package/dist/status-pill-DCHvrd_y.js.map +1 -0
  151. package/dist/test-DBCtwx_I.js +210 -0
  152. package/dist/test-DBCtwx_I.js.map +1 -0
  153. package/dist/transport/reconnect.d.ts +22 -0
  154. package/dist/transport/reconnect.d.ts.map +1 -0
  155. package/dist/transport/reconnect.js +60 -0
  156. package/dist/transport/reconnect.js.map +1 -0
  157. package/dist/transport/ws.d.ts +66 -0
  158. package/dist/transport/ws.d.ts.map +1 -0
  159. package/dist/transport/ws.js +270 -0
  160. package/dist/transport/ws.js.map +1 -0
  161. package/dist/tree-CnhX02kd.js +494 -0
  162. package/dist/tree-CnhX02kd.js.map +1 -0
  163. package/dist/types.d.ts +38 -0
  164. package/dist/types.d.ts.map +1 -0
  165. package/dist/types.js +3 -0
  166. package/dist/types.js.map +1 -0
  167. package/package.json +64 -0
  168. package/src/animate/crossfade.tsx +31 -0
  169. package/src/animate/keyframes.ts +142 -0
  170. package/src/animate/transitions.ts +116 -0
  171. package/src/app.tsx +84 -0
  172. package/src/dev-entry.tsx +38 -0
  173. package/src/index.ts +24 -0
  174. package/src/internal/validate-options.ts +20 -0
  175. package/src/modes/broadcast.tsx +8 -0
  176. package/src/modes/control.tsx +17 -0
  177. package/src/modes/test.tsx +19 -0
  178. package/src/mount.ts +169 -0
  179. package/src/overlay/control.tsx +239 -0
  180. package/src/overlay/runtime-context.tsx +37 -0
  181. package/src/overlay/status-pill.tsx +37 -0
  182. package/src/overlay/test.tsx +213 -0
  183. package/src/render/bundle.ts +208 -0
  184. package/src/render/fill.tsx +163 -0
  185. package/src/render/keyframe-player.tsx +89 -0
  186. package/src/render/primitives/frame.tsx +78 -0
  187. package/src/render/primitives/grid.tsx +20 -0
  188. package/src/render/primitives/image.tsx +35 -0
  189. package/src/render/primitives/index.ts +35 -0
  190. package/src/render/primitives/instance.tsx +70 -0
  191. package/src/render/primitives/media.tsx +28 -0
  192. package/src/render/primitives/shape.tsx +135 -0
  193. package/src/render/primitives/stack.tsx +48 -0
  194. package/src/render/primitives/text.tsx +38 -0
  195. package/src/render/scope.tsx +27 -0
  196. package/src/render/stagger-context.tsx +24 -0
  197. package/src/render/tree.tsx +182 -0
  198. package/src/render/universal-wrapper.tsx +95 -0
  199. package/src/state/apply-delta.ts +24 -0
  200. package/src/state/apply-snapshot.ts +8 -0
  201. package/src/state/store.ts +141 -0
  202. package/src/transport/reconnect.ts +83 -0
  203. package/src/transport/ws.ts +359 -0
  204. package/src/types.ts +54 -0
@@ -0,0 +1,45 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ /** Vertical or horizontal flex container. Layout-only — bindings
3
+ * here are unusual but tolerated.
4
+ *
5
+ * LSML 1.1 §4.1 adds `wrap` (boolean) and `crossGap` (number) :
6
+ * - wrap: true sets `flex-wrap: wrap` so children flow onto the
7
+ * next row / column when they overflow the main axis.
8
+ * - crossGap is the spacing between rows / columns when wrapping.
9
+ * Mapped to CSS `row-gap` (horizontal stack) or `column-gap`
10
+ * (vertical stack). Ignored when `wrap` is false.
11
+ */
12
+ export function Stack({ resolved, children }) {
13
+ const direction = resolved.direction ?? "vertical";
14
+ const gap = numberOr(resolved.gap, 0);
15
+ const wrap = resolved.wrap === true;
16
+ const crossGap = numberOr(resolved.crossGap, 0);
17
+ const align = resolved.align ?? "stretch";
18
+ const justify = resolved.justify ?? "flex-start";
19
+ const isHorizontal = direction === "horizontal";
20
+ const style = {
21
+ display: "flex",
22
+ flexDirection: isHorizontal ? "row" : "column",
23
+ alignItems: align,
24
+ justifyContent: justify,
25
+ };
26
+ if (wrap) {
27
+ style.flexWrap = "wrap";
28
+ if (isHorizontal) {
29
+ style.columnGap = gap;
30
+ style.rowGap = crossGap;
31
+ }
32
+ else {
33
+ style.rowGap = gap;
34
+ style.columnGap = crossGap;
35
+ }
36
+ }
37
+ else {
38
+ style.gap = gap;
39
+ }
40
+ return _jsx("div", { style: style, children: children });
41
+ }
42
+ function numberOr(v, fallback) {
43
+ return typeof v === "number" && Number.isFinite(v) ? v : fallback;
44
+ }
45
+ //# sourceMappingURL=stack.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stack.js","sourceRoot":"","sources":["../../../src/render/primitives/stack.tsx"],"names":[],"mappings":";AAGA;;;;;;;;;GASG;AACH,MAAM,UAAU,KAAK,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAkB;IAC1D,MAAM,SAAS,GAAI,QAAQ,CAAC,SAAoB,IAAI,UAAU,CAAC;IAC/D,MAAM,GAAG,GAAG,QAAQ,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;IACtC,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,KAAK,IAAI,CAAC;IACpC,MAAM,QAAQ,GAAG,QAAQ,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;IAChD,MAAM,KAAK,GAAI,QAAQ,CAAC,KAAgB,IAAI,SAAS,CAAC;IACtD,MAAM,OAAO,GAAI,QAAQ,CAAC,OAAkB,IAAI,YAAY,CAAC;IAC7D,MAAM,YAAY,GAAG,SAAS,KAAK,YAAY,CAAC;IAEhD,MAAM,KAAK,GAAkB;QAC3B,OAAO,EAAE,MAAM;QACf,aAAa,EAAE,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ;QAC9C,UAAU,EAAE,KAAK;QACjB,cAAc,EAAE,OAAO;KACxB,CAAC;IAEF,IAAI,IAAI,EAAE,CAAC;QACT,KAAK,CAAC,QAAQ,GAAG,MAAM,CAAC;QACxB,IAAI,YAAY,EAAE,CAAC;YACjB,KAAK,CAAC,SAAS,GAAG,GAAG,CAAC;YACtB,KAAK,CAAC,MAAM,GAAG,QAAQ,CAAC;QAC1B,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,MAAM,GAAG,GAAG,CAAC;YACnB,KAAK,CAAC,SAAS,GAAG,QAAQ,CAAC;QAC7B,CAAC;IACH,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC;IAClB,CAAC;IAED,OAAO,cAAK,KAAK,EAAE,KAAK,YAAG,QAAQ,GAAO,CAAC;AAC7C,CAAC;AAED,SAAS,QAAQ,CAAC,CAAU,EAAE,QAAgB;IAC5C,OAAO,OAAO,CAAC,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;AACpE,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { PrimitiveProps } from "./index";
2
+ /** Text leaf. Value renders as the displayed string ; style props
3
+ * cover size / weight / colour / alignment. Opacity is animated when
4
+ * a transition is declared on `opacity` or `value`. */
5
+ export declare function Text({ resolved, transitionFor }: PrimitiveProps): import("react/jsx-runtime").JSX.Element;
6
+ //# sourceMappingURL=text.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../../src/render/primitives/text.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAG9C;;wDAEwD;AACxD,wBAAgB,IAAI,CAAC,EAAE,QAAQ,EAAE,aAAa,EAAE,EAAE,cAAc,2CA0B/D"}
@@ -0,0 +1,27 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { motion } from "framer-motion";
3
+ import { toFramer } from "../../animate/transitions";
4
+ /** Text leaf. Value renders as the displayed string ; style props
5
+ * cover size / weight / colour / alignment. Opacity is animated when
6
+ * a transition is declared on `opacity` or `value`. */
7
+ export function Text({ resolved, transitionFor }) {
8
+ const value = resolved.value === undefined ? "" : String(resolved.value);
9
+ const size = resolved.size ?? "1rem";
10
+ const weight = resolved.weight ?? 400;
11
+ const colour = resolved.colour ?? "currentColor";
12
+ const align = resolved.align ?? "start";
13
+ const opacity = numberOr(resolved.opacity, 1);
14
+ const tx = transitionFor("opacity") ?? transitionFor("value");
15
+ return (_jsx(motion.span, { style: {
16
+ display: "inline-block",
17
+ fontSize: size,
18
+ fontWeight: weight,
19
+ color: colour,
20
+ textAlign: align,
21
+ willChange: "opacity",
22
+ }, animate: { opacity }, transition: toFramer(tx), children: value }));
23
+ }
24
+ function numberOr(v, fallback) {
25
+ return typeof v === "number" && Number.isFinite(v) ? v : fallback;
26
+ }
27
+ //# sourceMappingURL=text.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text.js","sourceRoot":"","sources":["../../../src/render/primitives/text.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAEvC,OAAO,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAErD;;wDAEwD;AACxD,MAAM,UAAU,IAAI,CAAC,EAAE,QAAQ,EAAE,aAAa,EAAkB;IAC9D,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IACzE,MAAM,IAAI,GAAI,QAAQ,CAAC,IAAoC,IAAI,MAAM,CAAC;IACtE,MAAM,MAAM,GAAI,QAAQ,CAAC,MAA6B,IAAI,GAAG,CAAC;IAC9D,MAAM,MAAM,GAAI,QAAQ,CAAC,MAA6B,IAAI,cAAc,CAAC;IACzE,MAAM,KAAK,GAAI,QAAQ,CAAC,KAA4B,IAAI,OAAO,CAAC;IAChE,MAAM,OAAO,GAAG,QAAQ,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IAE9C,MAAM,EAAE,GAAG,aAAa,CAAC,SAAS,CAAC,IAAI,aAAa,CAAC,OAAO,CAAC,CAAC;IAE9D,OAAO,CACL,KAAC,MAAM,CAAC,IAAI,IACV,KAAK,EAAE;YACL,OAAO,EAAE,cAAc;YACvB,QAAQ,EAAE,IAAI;YACd,UAAU,EAAE,MAAM;YAClB,KAAK,EAAE,MAAM;YACb,SAAS,EAAE,KAAyC;YACpD,UAAU,EAAE,SAAS;SACtB,EACD,OAAO,EAAE,EAAE,OAAO,EAAE,EACpB,UAAU,EAAE,QAAQ,CAAC,EAAE,CAAC,YAEvB,KAAK,GACM,CACf,CAAC;AACJ,CAAC;AAED,SAAS,QAAQ,CAAC,CAAU,EAAE,QAAgB;IAC5C,OAAO,OAAO,CAAC,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;AACpE,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { type ReactNode } from "react";
2
+ export declare function PathScopeProvider({ prefix, children }: {
3
+ prefix: string;
4
+ children: ReactNode;
5
+ }): import("react/jsx-runtime").JSX.Element;
6
+ /** Returns the current path prefix, or "" if there is no scope. */
7
+ export declare function usePathScope(): string;
8
+ /** Resolve a binding path under the current scope. */
9
+ export declare function scopedPath(prefix: string, path: string): string;
10
+ //# sourceMappingURL=scope.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scope.d.ts","sourceRoot":"","sources":["../../src/render/scope.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA6B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAOlE,wBAAgB,iBAAiB,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,SAAS,CAAA;CAAE,2CAI9F;AAED,mEAAmE;AACnE,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED,sDAAsD;AACtD,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAO/D"}
@@ -0,0 +1,27 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { createContext, useContext } from "react";
3
+ /** Path-scope context. Children inside a `repeat` get a `prefix` that
4
+ * is prepended to their declared bindings, so a single template can
5
+ * bind to per-item paths like `items.{i}.score`. */
6
+ const PathScopeContext = createContext("");
7
+ export function PathScopeProvider({ prefix, children }) {
8
+ const parent = useContext(PathScopeContext);
9
+ const next = parent ? `${parent}.${prefix}` : prefix;
10
+ return _jsx(PathScopeContext.Provider, { value: next, children: children });
11
+ }
12
+ /** Returns the current path prefix, or "" if there is no scope. */
13
+ export function usePathScope() {
14
+ return useContext(PathScopeContext);
15
+ }
16
+ /** Resolve a binding path under the current scope. */
17
+ export function scopedPath(prefix, path) {
18
+ if (!prefix)
19
+ return path;
20
+ // Path may itself start with a literal prefix (e.g. `__system.*`),
21
+ // which should NOT be scoped — only paths that are clearly relative
22
+ // get prefixed.
23
+ if (path.startsWith("__"))
24
+ return path;
25
+ return `${prefix}.${path}`;
26
+ }
27
+ //# sourceMappingURL=scope.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scope.js","sourceRoot":"","sources":["../../src/render/scope.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAkB,MAAM,OAAO,CAAC;AAElE;;qDAEqD;AACrD,MAAM,gBAAgB,GAAG,aAAa,CAAS,EAAE,CAAC,CAAC;AAEnD,MAAM,UAAU,iBAAiB,CAAC,EAAE,MAAM,EAAE,QAAQ,EAA2C;IAC7F,MAAM,MAAM,GAAG,UAAU,CAAC,gBAAgB,CAAC,CAAC;IAC5C,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,MAAM,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;IACrD,OAAO,KAAC,gBAAgB,CAAC,QAAQ,IAAC,KAAK,EAAE,IAAI,YAAG,QAAQ,GAA6B,CAAC;AACxF,CAAC;AAED,mEAAmE;AACnE,MAAM,UAAU,YAAY;IAC1B,OAAO,UAAU,CAAC,gBAAgB,CAAC,CAAC;AACtC,CAAC;AAED,sDAAsD;AACtD,MAAM,UAAU,UAAU,CAAC,MAAc,EAAE,IAAY;IACrD,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IACzB,mEAAmE;IACnE,oEAAoE;IACpE,gBAAgB;IAChB,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACvC,OAAO,GAAG,MAAM,IAAI,IAAI,EAAE,CAAC;AAC7B,CAAC"}
@@ -0,0 +1,9 @@
1
+ /** Per-iteration stagger delay in milliseconds. `0` means no offset
2
+ * (the implicit default outside a staggered repeat). */
3
+ export declare const StaggerContext: import("react").Context<number>;
4
+ /** Spec hint : runtimes MAY cap effective stagger to avoid pathological
5
+ * wait times on large lists. We cap at 2 s. */
6
+ export declare const STAGGER_CAP_MS = 2000;
7
+ /** Compute the effective per-iteration delay, applying the runtime cap. */
8
+ export declare function computeStaggerDelayMs(index: number, staggerMs: number): number;
9
+ //# sourceMappingURL=stagger-context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stagger-context.d.ts","sourceRoot":"","sources":["../../src/render/stagger-context.tsx"],"names":[],"mappings":"AAUA;yDACyD;AACzD,eAAO,MAAM,cAAc,iCAA2B,CAAC;AAEvD;gDACgD;AAChD,eAAO,MAAM,cAAc,OAAO,CAAC;AAEnC,2EAA2E;AAC3E,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAI9E"}
@@ -0,0 +1,22 @@
1
+ // LSML 1.1 §6.7 — stagger context.
2
+ //
3
+ // `repeat.stagger_ms` produces wave-like reveals : iteration N's
4
+ // animations start `N * stagger_ms` after iteration 0. The Repeat
5
+ // renderer computes the per-iteration delay and threads it through
6
+ // React context so KeyframePlayer (and future animate-aware primitives)
7
+ // can pick it up without per-primitive wiring.
8
+ import { createContext } from "react";
9
+ /** Per-iteration stagger delay in milliseconds. `0` means no offset
10
+ * (the implicit default outside a staggered repeat). */
11
+ export const StaggerContext = createContext(0);
12
+ /** Spec hint : runtimes MAY cap effective stagger to avoid pathological
13
+ * wait times on large lists. We cap at 2 s. */
14
+ export const STAGGER_CAP_MS = 2000;
15
+ /** Compute the effective per-iteration delay, applying the runtime cap. */
16
+ export function computeStaggerDelayMs(index, staggerMs) {
17
+ if (staggerMs <= 0)
18
+ return 0;
19
+ const raw = index * staggerMs;
20
+ return raw > STAGGER_CAP_MS ? STAGGER_CAP_MS : raw;
21
+ }
22
+ //# sourceMappingURL=stagger-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stagger-context.js","sourceRoot":"","sources":["../../src/render/stagger-context.tsx"],"names":[],"mappings":"AAAA,mCAAmC;AACnC,EAAE;AACF,iEAAiE;AACjE,kEAAkE;AAClE,mEAAmE;AACnE,wEAAwE;AACxE,+CAA+C;AAE/C,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAEtC;yDACyD;AACzD,MAAM,CAAC,MAAM,cAAc,GAAG,aAAa,CAAS,CAAC,CAAC,CAAC;AAEvD;gDACgD;AAChD,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,CAAC;AAEnC,2EAA2E;AAC3E,MAAM,UAAU,qBAAqB,CAAC,KAAa,EAAE,SAAiB;IACpE,IAAI,SAAS,IAAI,CAAC;QAAE,OAAO,CAAC,CAAC;IAC7B,MAAM,GAAG,GAAG,KAAK,GAAG,SAAS,CAAC;IAC9B,OAAO,GAAG,GAAG,cAAc,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,GAAG,CAAC;AACrD,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { type ReactNode } from "react";
2
+ import type { Store } from "../state/store";
3
+ import type { RenderNode } from "./bundle";
4
+ export interface TreeProps {
5
+ node: RenderNode;
6
+ store: Store;
7
+ }
8
+ export declare function Tree({ node, store }: TreeProps): ReactNode;
9
+ //# sourceMappingURL=tree.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tree.d.ts","sourceRoot":"","sources":["../../src/render/tree.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAW,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAChD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAI5C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAK3C,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,UAAU,CAAC;IACjB,KAAK,EAAE,KAAK,CAAC;CACd;AAED,wBAAgB,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,SAAS,GAAG,SAAS,CAK1D"}
@@ -0,0 +1,139 @@
1
+ import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
2
+ // Recursive tree renderer — resolves bindings, dispatches to
3
+ // primitives, handles `repeat` specially.
4
+ import { useSignals } from "@preact/signals-react/runtime";
5
+ import { useMemo } from "react";
6
+ import { PRIMITIVES } from "./primitives";
7
+ import { PathScopeProvider, scopedPath, usePathScope } from "./scope";
8
+ import { UniversalWrapper } from "./universal-wrapper";
9
+ import { KeyframePlayer } from "./keyframe-player";
10
+ import { StaggerContext, computeStaggerDelayMs } from "./stagger-context";
11
+ export function Tree({ node, store }) {
12
+ if (node.kind === "repeat") {
13
+ return _jsx(Repeat, { node: node, store: store });
14
+ }
15
+ return _jsx(Node, { node: node, store: store });
16
+ }
17
+ function Node({ node, store }) {
18
+ // useSignals() lets the surrounding component subscribe to any
19
+ // signal read during render. Each leaf path has its own signal so
20
+ // re-renders only fire on touched paths.
21
+ useSignals();
22
+ const scope = usePathScope();
23
+ // Hooks must run unconditionally — the early-return for unknown
24
+ // kinds happens *after* every hook has fired.
25
+ const resolved = useMemo(() => resolveProps(node, store, scope),
26
+ // We re-build per render — signals re-render cheaply, and the
27
+ // resolution itself is O(bindings) which is small. The memo is a
28
+ // micro-optimisation to keep object identity stable across renders
29
+ // when the inputs haven't changed.
30
+ [node, store, scope, ...readBindingValues(node, store, scope)]);
31
+ const Primitive = PRIMITIVES[node.kind];
32
+ if (!Primitive) {
33
+ if (import.meta.env.DEV) {
34
+ console.warn(`[lumencast] unknown render kind : ${node.kind}`);
35
+ }
36
+ return null;
37
+ }
38
+ // LSDP/1.1 §3.2.2 — a per-leaf transition on the most recent delta
39
+ // takes precedence over the bundle-level default. Only bound props
40
+ // can carry a wire transition (a static prop never moves). Snapshots
41
+ // clear the directive, so the bundle default reapplies after a reset.
42
+ //
43
+ // We resolve here in the parent's render (useSignals() above tracks
44
+ // these reads) rather than inside the primitive's callback — that way
45
+ // a transition signal change re-renders this Node, which in turn re-
46
+ // renders the primitive with the new transition prop.
47
+ const liveTransitions = {};
48
+ if (node.bindings) {
49
+ for (const [key, path] of Object.entries(node.bindings)) {
50
+ const ts = store.transitionSignal(scopedPath(scope, path)).value;
51
+ if (ts !== undefined)
52
+ liveTransitions[key] = ts;
53
+ }
54
+ }
55
+ const transitionFor = (key) => {
56
+ if (key in liveTransitions)
57
+ return liveTransitions[key];
58
+ return node.transitions?.[key];
59
+ };
60
+ const children = node.children?.map((child, idx) => (_jsx(Tree, { node: child, store: store }, child.id ?? idx)));
61
+ // LSML 1.1 §5.4 — universal props applied uniformly across all
62
+ // primitives. Pulled out of `resolved` so primitives can ignore
63
+ // them ; the wrapper composes with whatever transform/opacity the
64
+ // primitive's own framer-motion may apply.
65
+ const universal = {
66
+ visible: typeof resolved.visible === "boolean" ? resolved.visible : undefined,
67
+ opacity: typeof resolved.universal_opacity === "number" ? resolved.universal_opacity : undefined,
68
+ rotation: typeof resolved.rotation === "number" ? resolved.rotation : undefined,
69
+ sizing: extractSizing(resolved.sizing),
70
+ };
71
+ const body = (_jsx(UniversalWrapper, { ...universal, children: _jsx(Primitive, { resolved: resolved, transitionFor: transitionFor, children: children }) }));
72
+ // LSML 1.1 §6.6 — when a primitive declares keyframes, wrap the
73
+ // rendered subtree in a player that drives framer-motion through the
74
+ // step path. The player handles replay-on-key-change and reads any
75
+ // ambient stagger delay from StaggerContext (§6.7).
76
+ if (node.keyframes) {
77
+ return (_jsx(KeyframePlayer, { keyframes: node.keyframes, store: store, children: body }));
78
+ }
79
+ return body;
80
+ }
81
+ function extractSizing(value) {
82
+ if (typeof value !== "object" || value === null)
83
+ return undefined;
84
+ const obj = value;
85
+ const out = {};
86
+ if (obj.x === "fixed" || obj.x === "hug" || obj.x === "fill")
87
+ out.x = obj.x;
88
+ if (obj.y === "fixed" || obj.y === "hug" || obj.y === "fill")
89
+ out.y = obj.y;
90
+ return out.x !== undefined || out.y !== undefined ? out : undefined;
91
+ }
92
+ function Repeat({ node, store }) {
93
+ useSignals();
94
+ const scope = usePathScope();
95
+ const itemsBinding = node.bindings?.items;
96
+ const items = itemsBinding === undefined
97
+ ? []
98
+ : (store.signal(scopedPath(scope, itemsBinding)).value ?? []);
99
+ if (!Array.isArray(items))
100
+ return null;
101
+ const template = node.children?.[0];
102
+ if (!template)
103
+ return null;
104
+ // LSML 1.1 §6.7 — `stagger_ms` produces wave-like reveals across
105
+ // iterations. We compute the per-iteration delay (capped) and feed
106
+ // it to descendants via StaggerContext so the KeyframePlayer (and
107
+ // future animate-aware primitives) can pick it up without per-
108
+ // iteration scripting. `stagger_ms: 0` (or unset) is a no-op.
109
+ const staggerMs = typeof node.stagger_ms === "number" ? node.stagger_ms : 0;
110
+ return (_jsx(_Fragment, { children: items.map((_item, idx) => {
111
+ const delayMs = computeStaggerDelayMs(idx, staggerMs);
112
+ const tree = (_jsx(PathScopeProvider, { prefix: `${itemsBinding ?? ""}.${idx}`, children: _jsx(Tree, { node: template, store: store }) }, idx));
113
+ if (delayMs <= 0)
114
+ return tree;
115
+ return (_jsx(StaggerContext.Provider, { value: delayMs, children: tree }, idx));
116
+ }) }));
117
+ }
118
+ function resolveProps(node, store, scope) {
119
+ const out = { ...(node.props ?? {}) };
120
+ if (node.bindings) {
121
+ for (const [propKey, path] of Object.entries(node.bindings)) {
122
+ const fullPath = scopedPath(scope, path);
123
+ out[propKey] = store.signal(fullPath).value;
124
+ }
125
+ }
126
+ return out;
127
+ }
128
+ /** Helper for the useMemo deps array — read each bound signal so the
129
+ * memo invalidates when any binding moves. */
130
+ function readBindingValues(node, store, scope) {
131
+ if (!node.bindings)
132
+ return [];
133
+ const values = [];
134
+ for (const path of Object.values(node.bindings)) {
135
+ values.push(store.signal(scopedPath(scope, path)).value);
136
+ }
137
+ return values;
138
+ }
139
+ //# sourceMappingURL=tree.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tree.js","sourceRoot":"","sources":["../../src/render/tree.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import type { ReactNode } from "react";
2
+ export type SizingMode = "fixed" | "hug" | "fill";
3
+ export interface UniversalProps {
4
+ visible?: boolean;
5
+ opacity?: number;
6
+ rotation?: number;
7
+ sizing?: {
8
+ x?: SizingMode;
9
+ y?: SizingMode;
10
+ };
11
+ }
12
+ export interface UniversalWrapperProps extends UniversalProps {
13
+ children: ReactNode;
14
+ }
15
+ export declare function UniversalWrapper({ visible, opacity, rotation, sizing, children, }: UniversalWrapperProps): import("react/jsx-runtime").JSX.Element | null;
16
+ //# sourceMappingURL=universal-wrapper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"universal-wrapper.d.ts","sourceRoot":"","sources":["../../src/render/universal-wrapper.tsx"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,SAAS,EAAiB,MAAM,OAAO,CAAC;AAEtD,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,KAAK,GAAG,MAAM,CAAC;AAElD,MAAM,WAAW,cAAc;IAC7B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE;QAAE,CAAC,CAAC,EAAE,UAAU,CAAC;QAAC,CAAC,CAAC,EAAE,UAAU,CAAA;KAAE,CAAC;CAC7C;AAED,MAAM,WAAW,qBAAsB,SAAQ,cAAc;IAC3D,QAAQ,EAAE,SAAS,CAAC;CACrB;AAqBD,wBAAgB,gBAAgB,CAAC,EAC/B,OAAO,EACP,OAAO,EACP,QAAQ,EACR,MAAM,EACN,QAAQ,GACT,EAAE,qBAAqB,kDAsCvB"}
@@ -0,0 +1,58 @@
1
+ import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
2
+ /**
3
+ * Maps a SizingMode onto a flex shorthand. Per LSML 1.1 §5.4.1 :
4
+ * - fixed : the primitive honours its declared size verbatim
5
+ * - hug : the primitive shrinks to its intrinsic content size
6
+ * - fill : the primitive grows to fill available space
7
+ */
8
+ function flexFor(mode) {
9
+ switch (mode) {
10
+ case "fixed":
11
+ return "0 0 auto";
12
+ case "hug":
13
+ return "0 1 auto";
14
+ case "fill":
15
+ return "1 1 auto";
16
+ default:
17
+ return undefined;
18
+ }
19
+ }
20
+ export function UniversalWrapper({ visible, opacity, rotation, sizing, children, }) {
21
+ if (visible === false) {
22
+ return null; // slot collapses in flex/grid layouts (§5.4)
23
+ }
24
+ // No-op fast path — when no universal props are set, render children
25
+ // directly. Lets simple bundles avoid an extra DOM node per primitive.
26
+ const hasOpacity = typeof opacity === "number" && opacity !== 1;
27
+ const hasRotation = typeof rotation === "number" && rotation !== 0;
28
+ const hasSizing = sizing?.x !== undefined || sizing?.y !== undefined;
29
+ if (!hasOpacity && !hasRotation && !hasSizing) {
30
+ return _jsx(_Fragment, { children: children });
31
+ }
32
+ const style = {};
33
+ if (hasOpacity)
34
+ style.opacity = opacity;
35
+ if (hasRotation)
36
+ style.transform = `rotate(${rotation}deg)`;
37
+ // sizing.x / sizing.y map to flex / row-flex behaviour. The
38
+ // x-axis applies along the main axis of a horizontal stack ; the
39
+ // y-axis along a vertical stack. We emit `flex` (covers both via
40
+ // CSS's flex-direction) and rely on the parent stack for orientation.
41
+ if (hasSizing) {
42
+ const x = flexFor(sizing?.x);
43
+ const y = flexFor(sizing?.y);
44
+ // Emit a single flex declaration when both axes agree, otherwise
45
+ // ship explicit grow/shrink/basis based on the dominant intent.
46
+ if (x === y && x !== undefined) {
47
+ style.flex = x;
48
+ }
49
+ else {
50
+ // Heuristic : honour x for horizontal stacks (most common in
51
+ // broadcast UIs). Renderer doesn't know the parent's axis here ;
52
+ // a future iteration could thread that through context.
53
+ style.flex = x ?? y;
54
+ }
55
+ }
56
+ return _jsx("div", { style: style, children: children });
57
+ }
58
+ //# sourceMappingURL=universal-wrapper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"universal-wrapper.js","sourceRoot":"","sources":["../../src/render/universal-wrapper.tsx"],"names":[],"mappings":";AA+BA;;;;;GAKG;AACH,SAAS,OAAO,CAAC,IAA4B;IAC3C,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,OAAO;YACV,OAAO,UAAU,CAAC;QACpB,KAAK,KAAK;YACR,OAAO,UAAU,CAAC;QACpB,KAAK,MAAM;YACT,OAAO,UAAU,CAAC;QACpB;YACE,OAAO,SAAS,CAAC;IACrB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,EAC/B,OAAO,EACP,OAAO,EACP,QAAQ,EACR,MAAM,EACN,QAAQ,GACc;IACtB,IAAI,OAAO,KAAK,KAAK,EAAE,CAAC;QACtB,OAAO,IAAI,CAAC,CAAC,6CAA6C;IAC5D,CAAC;IAED,qEAAqE;IACrE,uEAAuE;IACvE,MAAM,UAAU,GAAG,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,CAAC,CAAC;IAChE,MAAM,WAAW,GAAG,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,KAAK,CAAC,CAAC;IACnE,MAAM,SAAS,GAAG,MAAM,EAAE,CAAC,KAAK,SAAS,IAAI,MAAM,EAAE,CAAC,KAAK,SAAS,CAAC;IACrE,IAAI,CAAC,UAAU,IAAI,CAAC,WAAW,IAAI,CAAC,SAAS,EAAE,CAAC;QAC9C,OAAO,4BAAG,QAAQ,GAAI,CAAC;IACzB,CAAC;IAED,MAAM,KAAK,GAAkB,EAAE,CAAC;IAChC,IAAI,UAAU;QAAE,KAAK,CAAC,OAAO,GAAG,OAAO,CAAC;IACxC,IAAI,WAAW;QAAE,KAAK,CAAC,SAAS,GAAG,UAAU,QAAQ,MAAM,CAAC;IAE5D,4DAA4D;IAC5D,iEAAiE;IACjE,iEAAiE;IACjE,sEAAsE;IACtE,IAAI,SAAS,EAAE,CAAC;QACd,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QAC7B,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QAC7B,iEAAiE;QACjE,gEAAgE;QAChE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,SAAS,EAAE,CAAC;YAC/B,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC;QACjB,CAAC;aAAM,CAAC;YACN,6DAA6D;YAC7D,iEAAiE;YACjE,wDAAwD;YACxD,KAAK,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC;QACtB,CAAC;IACH,CAAC;IAED,OAAO,cAAK,KAAK,EAAE,KAAK,YAAG,QAAQ,GAAO,CAAC;AAC7C,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { DeltaFrame } from "@lumencast/protocol";
2
+ import type { Store } from "./store.js";
3
+ /** Apply an LSDP/1 delta. All patches in the frame land in a single signals
4
+ * batch — components reading multiple paths see them flip in one render pass.
5
+ *
6
+ * LSDP/1.1 §3.2.2 — a patch may carry a `transition` directive overriding
7
+ * the bundle-level default for the next animation cycle on that leaf. We
8
+ * thread it through the store so the renderer reads the correct directive
9
+ * alongside the new value. */
10
+ export declare function applyDelta(store: Store, frame: DeltaFrame): void;
11
+ //# sourceMappingURL=apply-delta.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apply-delta.d.ts","sourceRoot":"","sources":["../../src/state/apply-delta.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAGxC;;;;;;+BAM+B;AAC/B,wBAAgB,UAAU,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,GAAG,IAAI,CAWhE"}
@@ -0,0 +1,23 @@
1
+ import { batch } from "@preact/signals-react";
2
+ import { parseWireTransition } from "../animate/transitions";
3
+ /** Apply an LSDP/1 delta. All patches in the frame land in a single signals
4
+ * batch — components reading multiple paths see them flip in one render pass.
5
+ *
6
+ * LSDP/1.1 §3.2.2 — a patch may carry a `transition` directive overriding
7
+ * the bundle-level default for the next animation cycle on that leaf. We
8
+ * thread it through the store so the renderer reads the correct directive
9
+ * alongside the new value. */
10
+ export function applyDelta(store, frame) {
11
+ batch(() => {
12
+ for (const patch of frame.patches) {
13
+ const transition = parseWireTransition(patch.transition);
14
+ if (transition !== undefined) {
15
+ store.setWithTransition(patch.path, patch.value, transition);
16
+ }
17
+ else {
18
+ store.set(patch.path, patch.value);
19
+ }
20
+ }
21
+ });
22
+ }
23
+ //# sourceMappingURL=apply-delta.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apply-delta.js","sourceRoot":"","sources":["../../src/state/apply-delta.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAG9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAE7D;;;;;;+BAM+B;AAC/B,MAAM,UAAU,UAAU,CAAC,KAAY,EAAE,KAAiB;IACxD,KAAK,CAAC,GAAG,EAAE;QACT,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;YAClC,MAAM,UAAU,GAAG,mBAAmB,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;YACzD,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;gBAC7B,KAAK,CAAC,iBAAiB,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;YAC/D,CAAC;iBAAM,CAAC;gBACN,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;YACrC,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { SnapshotFrame } from "@lumencast/protocol";
2
+ import type { Store } from "./store.js";
3
+ /** Apply an LSDP/1 snapshot to the store. Replaces the entire state — paths
4
+ * not present in the snapshot are reset to `undefined`. */
5
+ export declare function applySnapshot(store: Store, frame: SnapshotFrame): void;
6
+ //# sourceMappingURL=apply-snapshot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apply-snapshot.d.ts","sourceRoot":"","sources":["../../src/state/apply-snapshot.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC;4DAC4D;AAC5D,wBAAgB,aAAa,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,aAAa,GAAG,IAAI,CAEtE"}
@@ -0,0 +1,6 @@
1
+ /** Apply an LSDP/1 snapshot to the store. Replaces the entire state — paths
2
+ * not present in the snapshot are reset to `undefined`. */
3
+ export function applySnapshot(store, frame) {
4
+ store.reset(frame.state);
5
+ }
6
+ //# sourceMappingURL=apply-snapshot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apply-snapshot.js","sourceRoot":"","sources":["../../src/state/apply-snapshot.ts"],"names":[],"mappings":"AAGA;4DAC4D;AAC5D,MAAM,UAAU,aAAa,CAAC,KAAY,EAAE,KAAoB;IAC9D,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;AAC3B,CAAC"}
@@ -0,0 +1,28 @@
1
+ import { type Signal } from "@preact/signals-react";
2
+ import type { Transition } from "../animate/transitions";
3
+ export interface Store {
4
+ /** Get-or-create the signal for a path. New paths start as `undefined`. */
5
+ signal(path: string): Signal<unknown>;
6
+ /** Apply a single leaf write. */
7
+ set(path: string, value: unknown): void;
8
+ /** Apply a single leaf write with an LSDP/1.1 §3.2.2 transition directive.
9
+ * The directive lives in a separate signal so the renderer can subscribe
10
+ * to it independently. Passing `undefined` clears any pending directive. */
11
+ setWithTransition(path: string, value: unknown, transition: Transition | undefined): void;
12
+ /** Read the most-recent transition directive for a path (or undefined
13
+ * when no directive has been applied since the last snapshot). The
14
+ * returned signal is reactive — components reading via `useSignals()`
15
+ * re-render when the directive changes. */
16
+ transitionSignal(path: string): Signal<Transition | undefined>;
17
+ /**
18
+ * Replace the whole state — used by `apply-snapshot`. Existing signals are
19
+ * reused (subscribers stay attached); paths missing from the snapshot reset
20
+ * to `undefined`. Pending per-path transitions are cleared (a snapshot is
21
+ * a state restore, not an animated change).
22
+ */
23
+ reset(state: Record<string, unknown>): void;
24
+ /** Snapshot of every known path → current value. For debug / state inspector. */
25
+ toRecord(): Record<string, unknown>;
26
+ }
27
+ export declare function createStore(): Store;
28
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/state/store.ts"],"names":[],"mappings":"AAaA,OAAO,EAAU,KAAK,MAAM,EAAS,MAAM,uBAAuB,CAAC;AACnE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEzD,MAAM,WAAW,KAAK;IACpB,2EAA2E;IAC3E,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;IACtC,iCAAiC;IACjC,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;IACxC;;gFAE4E;IAC5E,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,GAAG,SAAS,GAAG,IAAI,CAAC;IAC1F;;;+CAG2C;IAC3C,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,UAAU,GAAG,SAAS,CAAC,CAAC;IAC/D;;;;;OAKG;IACH,KAAK,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC5C,iFAAiF;IACjF,QAAQ,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACrC;AA2ED,wBAAgB,WAAW,IAAI,KAAK,CAEnC"}