@lumencast/runtime 0.4.0 → 0.6.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 (135) hide show
  1. package/README.md +57 -0
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/animate/frame-coalescer.d.ts +13 -0
  4. package/dist/animate/frame-coalescer.d.ts.map +1 -0
  5. package/dist/animate/frame-coalescer.js +46 -0
  6. package/dist/animate/frame-coalescer.js.map +1 -0
  7. package/dist/animate/keyframes.d.ts +1 -1
  8. package/dist/animate/keyframes.d.ts.map +1 -1
  9. package/dist/animate/keyframes.js +20 -6
  10. package/dist/animate/keyframes.js.map +1 -1
  11. package/dist/animate/transitions.d.ts +4 -1
  12. package/dist/animate/transitions.d.ts.map +1 -1
  13. package/dist/animate/transitions.js +30 -3
  14. package/dist/animate/transitions.js.map +1 -1
  15. package/dist/{broadcast-DzZ8TVGZ.js → broadcast-DO7jEkix.js} +3 -3
  16. package/dist/{broadcast-DzZ8TVGZ.js.map → broadcast-DO7jEkix.js.map} +1 -1
  17. package/dist/{control-gbDGvdR0.js → control-BSfl4_cO.js} +4 -4
  18. package/dist/{control-gbDGvdR0.js.map → control-BSfl4_cO.js.map} +1 -1
  19. package/dist/{index-oteiocFe.js → index-Crkij3C4.js} +352 -179
  20. package/dist/index-Crkij3C4.js.map +1 -0
  21. package/dist/index.d.ts +5 -2
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.html +1 -1
  24. package/dist/index.js +10 -0
  25. package/dist/index.js.map +1 -1
  26. package/dist/lumencast.js +9 -2
  27. package/dist/mount.d.ts.map +1 -1
  28. package/dist/mount.js +16 -1
  29. package/dist/mount.js.map +1 -1
  30. package/dist/render/bind-animate.d.ts +40 -0
  31. package/dist/render/bind-animate.d.ts.map +1 -0
  32. package/dist/render/bind-animate.js +329 -0
  33. package/dist/render/bind-animate.js.map +1 -0
  34. package/dist/render/bundle.d.ts +56 -6
  35. package/dist/render/bundle.d.ts.map +1 -1
  36. package/dist/render/bundle.js +86 -5
  37. package/dist/render/bundle.js.map +1 -1
  38. package/dist/render/color-interp.d.ts +18 -0
  39. package/dist/render/color-interp.d.ts.map +1 -0
  40. package/dist/render/color-interp.js +303 -0
  41. package/dist/render/color-interp.js.map +1 -0
  42. package/dist/render/css-color.d.ts +16 -0
  43. package/dist/render/css-color.d.ts.map +1 -0
  44. package/dist/render/css-color.js +130 -0
  45. package/dist/render/css-color.js.map +1 -0
  46. package/dist/render/diagnostics.d.ts +26 -0
  47. package/dist/render/diagnostics.d.ts.map +1 -0
  48. package/dist/render/diagnostics.js +58 -0
  49. package/dist/render/diagnostics.js.map +1 -0
  50. package/dist/render/fill.d.ts +15 -3
  51. package/dist/render/fill.d.ts.map +1 -1
  52. package/dist/render/fill.js +81 -14
  53. package/dist/render/fill.js.map +1 -1
  54. package/dist/render/filter-clamp.d.ts +35 -0
  55. package/dist/render/filter-clamp.d.ts.map +1 -0
  56. package/dist/render/filter-clamp.js +90 -0
  57. package/dist/render/filter-clamp.js.map +1 -0
  58. package/dist/render/keyframe-player.d.ts +4 -1
  59. package/dist/render/keyframe-player.d.ts.map +1 -1
  60. package/dist/render/keyframe-player.js +2 -2
  61. package/dist/render/keyframe-player.js.map +1 -1
  62. package/dist/render/primitives/frame.d.ts +16 -1
  63. package/dist/render/primitives/frame.d.ts.map +1 -1
  64. package/dist/render/primitives/frame.js +42 -7
  65. package/dist/render/primitives/frame.js.map +1 -1
  66. package/dist/render/primitives/image.d.ts +1 -1
  67. package/dist/render/primitives/image.d.ts.map +1 -1
  68. package/dist/render/primitives/image.js +6 -3
  69. package/dist/render/primitives/image.js.map +1 -1
  70. package/dist/render/primitives/index.d.ts +3 -0
  71. package/dist/render/primitives/index.d.ts.map +1 -1
  72. package/dist/render/primitives/index.js.map +1 -1
  73. package/dist/render/primitives/instance.d.ts +1 -1
  74. package/dist/render/primitives/instance.d.ts.map +1 -1
  75. package/dist/render/primitives/instance.js +10 -13
  76. package/dist/render/primitives/instance.js.map +1 -1
  77. package/dist/render/primitives/shape.d.ts +9 -3
  78. package/dist/render/primitives/shape.d.ts.map +1 -1
  79. package/dist/render/primitives/shape.js +56 -12
  80. package/dist/render/primitives/shape.js.map +1 -1
  81. package/dist/render/primitives/text.d.ts +35 -4
  82. package/dist/render/primitives/text.d.ts.map +1 -1
  83. package/dist/render/primitives/text.js +179 -7
  84. package/dist/render/primitives/text.js.map +1 -1
  85. package/dist/render/prop-allowlist.d.ts +10 -0
  86. package/dist/render/prop-allowlist.d.ts.map +1 -0
  87. package/dist/render/prop-allowlist.js +112 -0
  88. package/dist/render/prop-allowlist.js.map +1 -0
  89. package/dist/render/svg-path.d.ts +35 -0
  90. package/dist/render/svg-path.d.ts.map +1 -0
  91. package/dist/render/svg-path.js +211 -0
  92. package/dist/render/svg-path.js.map +1 -0
  93. package/dist/render/tree.d.ts.map +1 -1
  94. package/dist/render/tree.js +30 -5
  95. package/dist/render/tree.js.map +1 -1
  96. package/dist/{status-pill-Cgdl9FtP.js → status-pill-BT5b-yET.js} +2 -2
  97. package/dist/{status-pill-Cgdl9FtP.js.map → status-pill-BT5b-yET.js.map} +1 -1
  98. package/dist/{test-CAnkHA0n.js → test-_hh1JvAd.js} +4 -4
  99. package/dist/{test-CAnkHA0n.js.map → test-_hh1JvAd.js.map} +1 -1
  100. package/dist/transport/ws.d.ts +5 -0
  101. package/dist/transport/ws.d.ts.map +1 -1
  102. package/dist/transport/ws.js +7 -0
  103. package/dist/transport/ws.js.map +1 -1
  104. package/dist/tree-DBj9SJgs.js +1230 -0
  105. package/dist/tree-DBj9SJgs.js.map +1 -0
  106. package/dist/types.d.ts +26 -0
  107. package/dist/types.d.ts.map +1 -1
  108. package/package.json +5 -4
  109. package/src/animate/frame-coalescer.ts +63 -0
  110. package/src/animate/keyframes.ts +24 -5
  111. package/src/animate/transitions.ts +33 -3
  112. package/src/index.ts +24 -0
  113. package/src/mount.ts +17 -1
  114. package/src/render/bind-animate.tsx +370 -0
  115. package/src/render/bundle.ts +124 -11
  116. package/src/render/color-interp.ts +303 -0
  117. package/src/render/css-color.ts +145 -0
  118. package/src/render/diagnostics.ts +75 -0
  119. package/src/render/fill.tsx +85 -14
  120. package/src/render/filter-clamp.ts +99 -0
  121. package/src/render/keyframe-player.tsx +10 -2
  122. package/src/render/primitives/frame.tsx +47 -7
  123. package/src/render/primitives/image.tsx +6 -2
  124. package/src/render/primitives/index.ts +3 -0
  125. package/src/render/primitives/instance.tsx +14 -15
  126. package/src/render/primitives/shape.tsx +76 -12
  127. package/src/render/primitives/text.tsx +224 -7
  128. package/src/render/prop-allowlist.ts +119 -0
  129. package/src/render/svg-path.ts +215 -0
  130. package/src/render/tree.tsx +41 -6
  131. package/src/transport/ws.ts +8 -0
  132. package/src/types.ts +27 -0
  133. package/dist/index-oteiocFe.js.map +0 -1
  134. package/dist/tree-DVYXwItH.js +0 -512
  135. package/dist/tree-DVYXwItH.js.map +0 -1
@@ -1,100 +1,148 @@
1
- import { batch as k, signal as d } from "@preact/signals-react";
2
- import { createRoot as U } from "react-dom/client";
3
- import { createContext as P, useContext as $, lazy as b, Suspense as j, createElement as x } from "react";
4
- import { jsx as l } from "react/jsx-runtime";
5
- import { useSignals as C } from "@preact/signals-react/runtime";
6
- import { AnimatePresence as q, motion as D } from "framer-motion";
7
- import { SequenceTracker as W, encodeFrame as _, input as B, WS_SUBPROTOCOLS as F, WS_SUBPROTOCOL_V1_1 as H, subscribe as z, decodeServerFrame as G, LumencastError as I } from "@lumencast/protocol";
8
- const O = P(null);
9
- function K({
1
+ import { batch as T, signal as p } from "@preact/signals-react";
2
+ import { createRoot as B } from "react-dom/client";
3
+ import { createContext as W, useContext as z, lazy as y, Suspense as H, createElement as G } from "react";
4
+ import { jsx as f } from "react/jsx-runtime";
5
+ import { useSignals as X } from "@preact/signals-react/runtime";
6
+ import { AnimatePresence as Y, motion as K } from "framer-motion";
7
+ import { SequenceTracker as J, encodeFrame as R, input as Q, WS_SUBPROTOCOLS as Z, WS_SUBPROTOCOL_V1_1 as V, subscribe as ee, decodeServerFrame as te, LumencastError as A } from "@lumencast/protocol";
8
+ const P = W(null);
9
+ function se({
10
10
  value: t,
11
11
  children: e
12
12
  }) {
13
- return /* @__PURE__ */ l(O.Provider, { value: t, children: e });
13
+ return /* @__PURE__ */ f(P.Provider, { value: t, children: e });
14
14
  }
15
- function Ie() {
16
- const t = $(O);
15
+ function Ye() {
16
+ const t = z(P);
17
17
  if (!t)
18
18
  throw new Error(
19
19
  "Lumencast overlay components must be rendered inside LumencastRuntimeProvider"
20
20
  );
21
21
  return t;
22
22
  }
23
- const Y = b(
24
- () => import("./broadcast-DzZ8TVGZ.js").then((t) => ({ default: t.BroadcastMode }))
25
- ), J = b(
26
- () => import("./control-gbDGvdR0.js").then((t) => ({ default: t.ControlMode }))
27
- ), Q = b(() => import("./test-CAnkHA0n.js").then((t) => ({ default: t.TestMode })));
28
- function X({
23
+ const ne = y(
24
+ () => import("./broadcast-DO7jEkix.js").then((t) => ({ default: t.BroadcastMode }))
25
+ ), re = y(
26
+ () => import("./control-BSfl4_cO.js").then((t) => ({ default: t.ControlMode }))
27
+ ), ie = y(() => import("./test-_hh1JvAd.js").then((t) => ({ default: t.TestMode })));
28
+ function oe({
29
29
  mode: t,
30
30
  store: e,
31
31
  bundleSignal: s,
32
32
  statusSignal: n,
33
33
  crossfadeKeySignal: r,
34
- sendInput: c
34
+ sendInput: o
35
35
  }) {
36
- C();
37
- const i = s.value, m = n.value, h = r.value;
38
- if (!i) return null;
39
- const a = t === "broadcast" ? Y : t === "control" ? J : Q;
40
- return /* @__PURE__ */ l(q, { mode: "sync", children: /* @__PURE__ */ l(
41
- D.div,
36
+ X();
37
+ const c = s.value, a = n.value, d = r.value;
38
+ if (!c) return null;
39
+ const l = t === "broadcast" ? ne : t === "control" ? re : ie;
40
+ return /* @__PURE__ */ f(Y, { mode: "sync", children: /* @__PURE__ */ f(
41
+ K.div,
42
42
  {
43
43
  initial: { opacity: 0 },
44
44
  animate: { opacity: 1 },
45
45
  exit: { opacity: 0 },
46
46
  transition: { duration: 0.4, ease: "easeInOut" },
47
47
  style: { position: "absolute", inset: 0 },
48
- children: /* @__PURE__ */ l(
49
- K,
48
+ children: /* @__PURE__ */ f(
49
+ se,
50
50
  {
51
51
  value: {
52
52
  mode: t,
53
53
  store: e,
54
- bundle: i,
55
- status: m,
56
- sendInput: c
54
+ bundle: c,
55
+ status: a,
56
+ sendInput: o
57
57
  },
58
- children: /* @__PURE__ */ l(j, { fallback: null, children: /* @__PURE__ */ l(a, {}) })
58
+ children: /* @__PURE__ */ f(H, { fallback: null, children: /* @__PURE__ */ f(l, {}) })
59
59
  }
60
60
  )
61
61
  },
62
- h
62
+ d
63
63
  ) });
64
64
  }
65
- const Z = { duration: 0 }, V = {
65
+ const ce = "<anon>", b = /* @__PURE__ */ new Set();
66
+ function ae(t) {
67
+ return b.add(t), () => {
68
+ b.delete(t);
69
+ };
70
+ }
71
+ function $(t, e, s) {
72
+ const n = { nodeId: t ?? ce, field: e, reason: s };
73
+ if (b.size > 0) {
74
+ for (const r of b)
75
+ try {
76
+ r(n);
77
+ } catch {
78
+ }
79
+ return;
80
+ }
81
+ }
82
+ const le = 100, ue = 4, he = 64, fe = {
83
+ blur: le,
84
+ brightness: ue
85
+ };
86
+ function O(t, e) {
87
+ if (typeof e != "number" || !Number.isFinite(e) || e < 0 || Object.is(e, -0)) return null;
88
+ const s = fe[t];
89
+ return e > s ? s : e;
90
+ }
91
+ const de = /^blur\((\d{1,7}(?:\.\d{1,4})?)px\) brightness\((\d{1,7}(?:\.\d{1,4})?)\)$/, Ke = "blur(0px) brightness(1)";
92
+ function me(t) {
93
+ if (typeof t != "string" || t.length === 0 || t.length > he) return null;
94
+ const e = de.exec(t);
95
+ if (!e) return null;
96
+ const s = O("blur", Number(e[1])), n = O("brightness", Number(e[2]));
97
+ return s === null || n === null ? null : `blur(${s}px) brightness(${n})`;
98
+ }
99
+ function pe(t, e) {
100
+ $(
101
+ e,
102
+ t,
103
+ "rejected unsafe filter value : outside the R8 caps or not a finite number >= 0"
104
+ );
105
+ }
106
+ const ge = { duration: 0 }, be = {
66
107
  linear: "linear",
67
108
  "cubic-in": "easeIn",
68
109
  "cubic-out": "easeOut",
69
110
  "cubic-in-out": "easeInOut"
70
111
  };
71
- function Re(t) {
72
- return !t || t.kind === "none" ? Z : t.kind === "tween" ? {
112
+ function Je(t) {
113
+ return !t || t.kind === "none" ? ge : t.kind === "tween" ? {
73
114
  type: "tween",
74
115
  duration: (t.duration_ms ?? 0) / 1e3,
75
- ease: t.ease ? V[t.ease] ?? "easeOut" : "easeOut"
116
+ ease: t.ease ? be[t.ease] ?? "easeOut" : "easeOut"
76
117
  } : t.kind === "spring" ? {
77
118
  type: "spring",
78
119
  ...t.stiffness !== void 0 ? { stiffness: t.stiffness } : {},
79
- ...t.damping !== void 0 ? { damping: t.damping } : {}
120
+ ...t.damping !== void 0 ? { damping: t.damping } : {},
121
+ ...t.mass !== void 0 ? { mass: t.mass } : {}
80
122
  } : {
81
123
  type: "tween",
82
124
  duration: (t.duration_ms ?? 400) / 1e3,
83
125
  ease: "easeInOut"
84
126
  };
85
127
  }
86
- const ee = {
128
+ const ve = {
87
129
  opacity: 1,
88
130
  scale: 1,
131
+ scaleX: 1,
132
+ scaleY: 1,
89
133
  rotate: 0,
90
134
  x: 0,
91
- y: 0
92
- }, te = {
135
+ y: 0,
136
+ // LSML §6.1 filter identity — both functions are always present so
137
+ // framer interpolates between structurally-identical filter lists
138
+ // (the compiler emits the same two-function form, clamped per R8).
139
+ filter: "blur(0px) brightness(1)"
140
+ }, ke = {
93
141
  kind: "tween",
94
142
  duration_ms: 400,
95
143
  ease: "cubic-out"
96
144
  };
97
- function Oe(t, e, s) {
145
+ function Qe(t, e, s) {
98
146
  for (const n of e) {
99
147
  const r = t(n);
100
148
  if (r !== void 0) return r;
@@ -104,80 +152,85 @@ function Oe(t, e, s) {
104
152
  const r = t(n);
105
153
  if (r !== void 0) return r;
106
154
  }
107
- return te;
155
+ return ke;
108
156
  }
109
157
  }
110
- function Ae(t, e) {
158
+ function Ze(t, e, s) {
111
159
  if (!e || Object.keys(e).length === 0)
112
160
  return { initial: t, animate: t };
113
- const s = { ...t };
114
- for (const n of Object.keys(e))
115
- n in s || (s[n] = ee[n] ?? 0);
116
- return { initial: e, animate: s };
161
+ let n = e;
162
+ if (e.filter !== void 0) {
163
+ const o = me(e.filter);
164
+ n = { ...e }, o === null ? (pe("animate_initial.filter", s), delete n.filter) : n.filter = o;
165
+ }
166
+ const r = { ...t };
167
+ for (const o of Object.keys(n))
168
+ o in r || (r[o] = ve[o] ?? 0);
169
+ return { initial: n, animate: r };
117
170
  }
118
- function se(t) {
171
+ function Te(t) {
119
172
  if (typeof t != "object" || t === null) return;
120
173
  const e = t, s = e.kind;
121
174
  if (s === "snap")
122
175
  return { kind: "none" };
123
176
  if (s === "tween") {
124
- const n = typeof e.duration_ms == "number" ? e.duration_ms : 0, r = ne[e.easing] ?? "cubic-out";
177
+ const n = typeof e.duration_ms == "number" ? e.duration_ms : 0, r = ye[e.easing] ?? "cubic-out";
125
178
  return { kind: "tween", duration_ms: n, ease: r };
126
179
  }
127
180
  if (s === "spring") {
128
181
  const n = { kind: "spring" };
129
- return typeof e.stiffness == "number" && (n.stiffness = e.stiffness), typeof e.damping == "number" && (n.damping = e.damping), n;
182
+ return typeof e.stiffness == "number" && (n.stiffness = e.stiffness), typeof e.damping == "number" && (n.damping = e.damping), typeof e.mass == "number" && (n.mass = e.mass), n;
130
183
  }
131
184
  }
132
- const ne = {
185
+ const ye = {
133
186
  linear: "linear",
134
187
  "ease-in": "cubic-in",
135
188
  "ease-out": "cubic-out",
136
189
  "ease-in-out": "cubic-in-out"
137
190
  };
138
- function re(t, e) {
139
- k(() => {
191
+ function Se(t, e) {
192
+ T(() => {
140
193
  for (const s of e.patches) {
141
- const n = se(s.transition);
194
+ const n = Te(s.transition);
142
195
  n !== void 0 ? t.setWithTransition(s.path, s.value, n) : t.set(s.path, s.value);
143
196
  }
144
197
  });
145
198
  }
146
- function oe(t, e) {
199
+ function we(t, e) {
147
200
  t.reset(e.state);
148
201
  }
149
- class ie {
202
+ class _e {
150
203
  signals = /* @__PURE__ */ new Map();
151
204
  transitions = /* @__PURE__ */ new Map();
152
205
  signal(e) {
153
206
  let s = this.signals.get(e);
154
- return s || (s = d(void 0), this.signals.set(e, s)), s;
207
+ return s || (s = p(void 0), this.signals.set(e, s)), s;
155
208
  }
156
209
  transitionSignal(e) {
157
210
  let s = this.transitions.get(e);
158
- return s || (s = d(void 0), this.transitions.set(e, s)), s;
211
+ return s || (s = p(void 0), this.transitions.set(e, s)), s;
159
212
  }
160
213
  set(e, s) {
161
214
  const n = this.signal(e);
162
- v(n.peek(), s) || (n.value = s);
215
+ k(n.peek(), s) || (n.value = s);
163
216
  }
164
217
  setWithTransition(e, s, n) {
165
- k(() => {
218
+ T(() => {
166
219
  const r = this.transitionSignal(e);
167
220
  r.peek() !== n && (r.value = n);
168
- const c = this.signal(e);
169
- v(c.peek(), s) || (c.value = s);
221
+ const o = this.signal(e);
222
+ k(o.peek(), s) || (o.value = s);
170
223
  });
171
224
  }
172
225
  reset(e) {
173
- k(() => {
226
+ T(() => {
174
227
  const s = /* @__PURE__ */ new Set();
175
228
  for (const [n, r] of Object.entries(e)) {
176
229
  s.add(n);
177
- const c = this.signal(n);
178
- v(c.peek(), r) || (c.value = r);
179
- const i = this.transitions.get(n);
180
- i && i.peek() !== void 0 && (i.value = void 0);
230
+ const o = this.signal(n);
231
+ k(o.peek(), r) || (o.value = r);
232
+ const c = this.transitions.get(n);
233
+ c && c.peek() !== void 0 && (c.value = void 0);
181
234
  }
182
235
  for (const n of this.signals.keys())
183
236
  if (!s.has(n)) {
@@ -193,28 +246,34 @@ class ie {
193
246
  return e;
194
247
  }
195
248
  }
196
- function ce() {
197
- return new ie();
249
+ function Ee() {
250
+ return new _e();
198
251
  }
199
- function v(t, e) {
252
+ function k(t, e) {
200
253
  if (t === e) return !0;
201
254
  if (t === null || e === null || typeof t != typeof e || typeof t != "object" || Array.isArray(t) !== Array.isArray(e)) return !1;
202
255
  if (Array.isArray(t) && Array.isArray(e)) {
203
256
  if (t.length !== e.length) return !1;
204
- for (let i = 0; i < t.length; i++)
205
- if (t[i] !== e[i]) return !1;
257
+ for (let c = 0; c < t.length; c++)
258
+ if (t[c] !== e[c]) return !1;
206
259
  return !0;
207
260
  }
208
- const s = t, n = e, r = Object.keys(s), c = Object.keys(n);
209
- if (r.length !== c.length) return !1;
210
- for (const i of r)
211
- if (s[i] !== n[i]) return !1;
261
+ const s = t, n = e, r = Object.keys(s), o = Object.keys(n);
262
+ if (r.length !== o.length) return !1;
263
+ for (const c of r)
264
+ if (s[c] !== n[c]) return !1;
212
265
  return !0;
213
266
  }
214
- const ae = /* @__PURE__ */ new Set([
267
+ const Ie = /* @__PURE__ */ new Set([
215
268
  "x-lumencast.color-srgb-1.0"
216
- ]);
217
- class ue extends Error {
269
+ ]), Re = /^x-[a-z0-9-]+(?:\.[a-z0-9-]+)*$/, Ae = /^(?:0|[1-9][0-9]*)$/, N = ".authoring";
270
+ function Oe(t) {
271
+ const e = t.indexOf("/");
272
+ if (e < 0) return !1;
273
+ const s = t.slice(0, e), n = t.slice(e + 1);
274
+ return !Ae.test(n) || !s.endsWith(N) ? !1 : Re.test(s.slice(0, -N.length));
275
+ }
276
+ class L extends Error {
218
277
  code = "BUNDLE_INCOMPATIBLE";
219
278
  unsupportedProfiles;
220
279
  constructor(e) {
@@ -225,48 +284,65 @@ class ue extends Error {
225
284
  ), this.name = "BundleIncompatibleError", this.unsupportedProfiles = e;
226
285
  }
227
286
  }
228
- function R(t, e = ae) {
287
+ function U(t, e = Ie) {
229
288
  const s = t.profiles;
230
- if (!s || s.length === 0) return;
231
- const n = s.filter((r) => !e.has(r));
289
+ if (!s) return;
290
+ if (!Array.isArray(s))
291
+ throw new L(["<malformed: profiles is not an array>"]);
292
+ if (s.length === 0) return;
293
+ const n = s.filter((r) => typeof r != "string" || !Oe(r) && !e.has(r)).map((r) => typeof r == "string" ? r : "<malformed: non-string profile entry>");
232
294
  if (n.length > 0)
233
- throw new ue(n);
295
+ throw new L(n);
234
296
  }
235
- class le {
297
+ class Ne {
236
298
  cache = /* @__PURE__ */ new Map();
237
299
  baseUrl;
238
300
  pathPrefix;
301
+ resolveUrl;
302
+ getAuthToken;
239
303
  fetchImpl;
240
304
  constructor(e) {
241
- this.baseUrl = e.baseUrl.replace(/\/$/, ""), this.pathPrefix = (e.pathPrefix ?? "/lsdp/v1/scenes").replace(/\/$/, ""), this.fetchImpl = e.fetchImpl ?? globalThis.fetch.bind(globalThis);
305
+ this.baseUrl = e.baseUrl.replace(/\/$/, ""), this.pathPrefix = (e.pathPrefix ?? "/lsdp/v1/scenes").replace(/\/$/, ""), this.resolveUrl = e.resolveUrl, this.getAuthToken = e.getAuthToken, this.fetchImpl = e.fetchImpl ?? globalThis.fetch.bind(globalThis);
306
+ }
307
+ /** Build the request init carrying the bearer token, if any. Returns
308
+ * `undefined` when no token is available — the fetch stays header-less,
309
+ * preserving v0.5.0 behaviour. */
310
+ async buildInit() {
311
+ if (!this.getAuthToken) return;
312
+ const e = await this.getAuthToken();
313
+ if (e)
314
+ return { headers: { Authorization: `Bearer ${e}` } };
315
+ }
316
+ buildUrl(e, s) {
317
+ return this.resolveUrl ? this.resolveUrl(e, s) : `${this.baseUrl}${this.pathPrefix}/${encodeURIComponent(e)}/bundle?v=${encodeURIComponent(s)}`;
242
318
  }
243
319
  preload(e) {
244
- R(e), this.cache.set(e.scene_version, e);
320
+ U(e), this.cache.set(e.scene_version, e);
245
321
  }
246
322
  async get(e, s) {
247
323
  const n = this.cache.get(s);
248
324
  if (n) return n;
249
- const r = `${this.baseUrl}${this.pathPrefix}/${encodeURIComponent(e)}/bundle?v=${encodeURIComponent(s)}`, c = await this.fetchImpl(r);
325
+ const r = this.buildUrl(e, s), o = await this.buildInit(), c = o ? await this.fetchImpl(r, o) : await this.fetchImpl(r);
250
326
  if (!c.ok)
251
327
  throw new Error(`bundle fetch failed: ${c.status} ${c.statusText}`);
252
- const i = await c.json();
253
- if (i.scene_version !== s)
328
+ const a = await c.json();
329
+ if (a.scene_version !== s)
254
330
  throw new Error(
255
- `bundle scene_version mismatch: expected ${s}, got ${i.scene_version}`
331
+ `bundle scene_version mismatch: expected ${s}, got ${a.scene_version}`
256
332
  );
257
- return R(i), this.cache.set(s, i), i;
333
+ return U(a), this.cache.set(s, a), a;
258
334
  }
259
335
  }
260
- function he(t) {
261
- return new le(t);
336
+ function Le(t) {
337
+ return new Ne(t);
262
338
  }
263
- const p = {
339
+ const g = {
264
340
  initial: 200,
265
341
  max: 5e3,
266
342
  factor: 2,
267
343
  jitter: 0.2
268
344
  };
269
- class de {
345
+ class Ue {
270
346
  constructor(e, s) {
271
347
  this.opts = e, this.random = s;
272
348
  }
@@ -290,20 +366,20 @@ class de {
290
366
  this._attempt = 0;
291
367
  }
292
368
  }
293
- function fe(t = {}) {
369
+ function xe(t = {}) {
294
370
  const e = {
295
- initial: t.initial ?? p.initial,
296
- max: t.max ?? p.max,
297
- factor: t.factor ?? p.factor,
298
- jitter: t.jitter ?? p.jitter
371
+ initial: t.initial ?? g.initial,
372
+ max: t.max ?? g.max,
373
+ factor: t.factor ?? g.factor,
374
+ jitter: t.jitter ?? g.jitter
299
375
  };
300
376
  if (e.initial <= 0) throw new RangeError("initial must be > 0");
301
377
  if (e.max < e.initial) throw new RangeError("max must be >= initial");
302
378
  if (e.factor < 1) throw new RangeError("factor must be >= 1");
303
379
  if (e.jitter < 0 || e.jitter > 1) throw new RangeError("jitter must be within [0, 1]");
304
- return new de(e, t.random ?? Math.random);
380
+ return new Ue(e, t.random ?? Math.random);
305
381
  }
306
- class u extends Error {
382
+ class h extends Error {
307
383
  recoverable;
308
384
  code;
309
385
  cause;
@@ -311,14 +387,14 @@ class u extends Error {
311
387
  super(e), this.name = "TransportError", this.recoverable = s, this.code = n, this.cause = r;
312
388
  }
313
389
  }
314
- class pe {
390
+ class Me {
315
391
  status = "disconnected";
316
392
  socket = null;
317
393
  token;
318
394
  url;
319
395
  WebSocketCtor;
320
396
  schedule;
321
- seq = new W();
397
+ seq = new J();
322
398
  opts;
323
399
  scheduler;
324
400
  reconnectTimer = null;
@@ -330,7 +406,7 @@ class pe {
330
406
  throw new TypeError(
331
407
  "Lumencast WsClient: no WebSocket implementation found in this environment"
332
408
  );
333
- this.WebSocketCtor = s, this.schedule = fe(e.reconnect), this.scheduler = e.scheduler ?? {
409
+ this.WebSocketCtor = s, this.schedule = xe(e.reconnect), this.scheduler = e.scheduler ?? {
334
410
  setTimeout: globalThis.setTimeout.bind(globalThis),
335
411
  clearTimeout: globalThis.clearTimeout.bind(globalThis)
336
412
  };
@@ -339,9 +415,16 @@ class pe {
339
415
  start() {
340
416
  this.active && (this.socket || this.status === "connecting" || this.openSocket());
341
417
  }
418
+ /** Resolve the current session token (the one used for the WS
419
+ * subscription). Mirrors `setToken` swaps. Used by the bundle fetcher to
420
+ * authenticate the render-bundle GET with the same credential. A
421
+ * `LumencastTokenProvider` is awaited. */
422
+ resolveCurrentToken() {
423
+ return x(this.token);
424
+ }
342
425
  /** Send `input` patches to the server. No-op if not connected. */
343
426
  sendInput(e) {
344
- !this.socket || this.socket.readyState !== this.WebSocketCtor.OPEN || e.length !== 0 && this.socket.send(_(B(e)));
427
+ !this.socket || this.socket.readyState !== this.WebSocketCtor.OPEN || e.length !== 0 && this.socket.send(R(Q(e)));
345
428
  }
346
429
  /** Replace the auth token. Closes and reopens with the new token. */
347
430
  setToken(e) {
@@ -357,10 +440,10 @@ class pe {
357
440
  this.setStatus("connecting");
358
441
  let e;
359
442
  try {
360
- e = await me(this.token);
443
+ e = await x(this.token);
361
444
  } catch (n) {
362
445
  this.opts.onTransportError?.(
363
- new u(
446
+ new h(
364
447
  `failed to resolve token: ${n.message}`,
365
448
  !0,
366
449
  "AUTH_DENIED",
@@ -372,10 +455,10 @@ class pe {
372
455
  if (!this.active) return;
373
456
  let s;
374
457
  try {
375
- s = new this.WebSocketCtor(this.url, [...F]);
458
+ s = new this.WebSocketCtor(this.url, [...Z]);
376
459
  } catch (n) {
377
460
  this.opts.onTransportError?.(
378
- new u(
461
+ new h(
379
462
  `failed to open WebSocket: ${n.message}`,
380
463
  !0,
381
464
  "INTERNAL",
@@ -388,25 +471,25 @@ class pe {
388
471
  }
389
472
  handleOpen(e) {
390
473
  if (!this.socket) return;
391
- const n = this.socket.protocol === H && this.seq.last > 0, r = n ? this.seq.last : void 0;
474
+ const n = this.socket.protocol === V && this.seq.last > 0, r = n ? this.seq.last : void 0;
392
475
  n || this.seq.reset();
393
- const c = z({
476
+ const o = ee({
394
477
  token: e,
395
478
  ...this.opts.scene !== void 0 ? { scene: this.opts.scene } : {},
396
479
  ...this.opts.session !== void 0 ? { session: this.opts.session } : {},
397
480
  ...r !== void 0 ? { since_sequence: r } : {}
398
481
  });
399
- this.socket.send(_(c));
482
+ this.socket.send(R(o));
400
483
  }
401
484
  handleMessage(e) {
402
485
  const s = typeof e.data == "string" ? e.data : "";
403
486
  if (!s) return;
404
487
  let n;
405
488
  try {
406
- n = G(s);
489
+ n = te(s);
407
490
  } catch (r) {
408
- const c = (r instanceof I, r.message), i = r instanceof I ? r.code : "INTERNAL";
409
- this.opts.onTransportError?.(new u(`codec: ${c}`, !0, i, r)), this.closeSocket(), this.scheduleReconnect();
491
+ const o = (r instanceof A, r.message), c = r instanceof A ? r.code : "INTERNAL";
492
+ this.opts.onTransportError?.(new h(`codec: ${o}`, !0, c, r)), this.closeSocket(), this.scheduleReconnect();
410
493
  return;
411
494
  }
412
495
  if (n !== null)
@@ -414,7 +497,7 @@ class pe {
414
497
  case "snapshot": {
415
498
  if (n.seq < 1) {
416
499
  this.opts.onTransportError?.(
417
- new u(`snapshot seq must be >= 1, got ${n.seq}`, !0, "VERSION_GAP")
500
+ new h(`snapshot seq must be >= 1, got ${n.seq}`, !0, "VERSION_GAP")
418
501
  ), this.closeSocket(), this.scheduleReconnect();
419
502
  return;
420
503
  }
@@ -425,7 +508,7 @@ class pe {
425
508
  const r = this.seq.observe(n.seq);
426
509
  if (r.kind === "gap") {
427
510
  this.opts.onTransportError?.(
428
- new u(
511
+ new h(
429
512
  `sequence gap: expected ${this.seq.last + 1}, got ${n.seq}`,
430
513
  !0,
431
514
  "VERSION_GAP"
@@ -458,7 +541,7 @@ class pe {
458
541
  }
459
542
  if (e.code === 4401 || e.code === 4403 || e.code === 1008) {
460
543
  this.opts.onTransportError?.(
461
- new u(`server closed: ${e.code} ${e.reason}`, !1, "AUTH_DENIED")
544
+ new h(`server closed: ${e.code} ${e.reason}`, !1, "AUTH_DENIED")
462
545
  ), this.close();
463
546
  return;
464
547
  }
@@ -488,10 +571,10 @@ class pe {
488
571
  this.status !== e && (this.status = e, this.opts.onStatus?.(e));
489
572
  }
490
573
  }
491
- async function me(t) {
574
+ async function x(t) {
492
575
  return typeof t == "string" ? t : await t.fetch();
493
576
  }
494
- function ge(t) {
577
+ function Pe(t) {
495
578
  if (!(t.target instanceof HTMLElement))
496
579
  throw new TypeError("mount: `target` must be an HTMLElement");
497
580
  if (typeof t.serverUrl != "string" || t.serverUrl.length === 0)
@@ -503,103 +586,107 @@ function ge(t) {
503
586
  throw new TypeError("mount: `scene` is required when mode === 'test'");
504
587
  }
505
588
  }
506
- function Le(t) {
507
- ge(t), t.onStatus?.("disconnected");
508
- const e = ce(), s = ke(t.serverUrl), n = he({ baseUrl: s }), r = d(null), c = d("disconnected"), i = d("__initial__"), m = (o) => {
509
- c.value = o, t.onStatus?.(o);
510
- }, h = (o) => {
511
- t.onError?.(o);
589
+ function Ve(t) {
590
+ Pe(t), t.onStatus?.("disconnected");
591
+ const e = Ee(), s = je(t.serverUrl), n = Le({
592
+ baseUrl: s,
593
+ ...t.resolveBundleUrl !== void 0 ? { resolveUrl: t.resolveBundleUrl } : {},
594
+ getAuthToken: () => m.resolveCurrentToken()
595
+ }), r = p(null), o = p("disconnected"), c = p("__initial__"), a = (i) => {
596
+ o.value = i, t.onStatus?.(i);
597
+ }, d = (i) => {
598
+ t.onError?.(i);
512
599
  };
513
- let a = !0;
514
- const f = new pe({
600
+ let l = !0;
601
+ const j = t.onDiagnostic ? ae(t.onDiagnostic) : void 0, m = new Me({
515
602
  url: t.serverUrl,
516
603
  token: t.token,
517
604
  ...t.scene !== void 0 ? { scene: t.scene } : {},
518
605
  ...t.testSession !== void 0 ? { session: t.testSession } : {},
519
- onStatus: m,
520
- onSnapshot: (o) => {
521
- a && (A(
606
+ onStatus: a,
607
+ onSnapshot: (i) => {
608
+ l && (C(
522
609
  n,
523
610
  r,
524
- i,
525
- o.scene_id,
526
- o.scene_version,
527
- () => oe(e, o),
528
- h
611
+ c,
612
+ i.scene_id,
613
+ i.scene_version,
614
+ () => we(e, i),
615
+ d
529
616
  ), t.onMetric?.({
530
617
  name: "snapshot_received",
531
- scene_id: o.scene_id,
532
- path_count: Object.keys(o.state).length
618
+ scene_id: i.scene_id,
619
+ path_count: Object.keys(i.state).length
533
620
  }));
534
621
  },
535
- onDelta: (o) => {
536
- if (!a) return;
537
- const g = performance.now();
538
- re(e, o), t.onMetric?.({
622
+ onDelta: (i) => {
623
+ if (!l) return;
624
+ const v = performance.now();
625
+ Se(e, i), t.onMetric?.({
539
626
  name: "delta_applied",
540
- duration_ms: performance.now() - g
541
- }), t.onMetric?.({ name: "delta_received", count: 1, path_count: o.patches.length });
627
+ duration_ms: performance.now() - v
628
+ }), t.onMetric?.({ name: "delta_received", count: 1, path_count: i.patches.length });
542
629
  },
543
- onSceneChanged: (o) => {
544
- a && t.onMetric?.({
630
+ onSceneChanged: (i) => {
631
+ l && t.onMetric?.({
545
632
  name: "scene_changed",
546
633
  from: r.value?.scene_version ?? null,
547
- to: o.scene_version
634
+ to: i.scene_version
548
635
  });
549
636
  },
550
- onServerError: (o) => {
551
- h({
552
- code: o.code,
553
- message: o.message,
554
- recoverable: o.recoverable
637
+ onServerError: (i) => {
638
+ d({
639
+ code: i.code,
640
+ message: i.message,
641
+ recoverable: i.recoverable
555
642
  });
556
643
  },
557
- onTransportError: (o) => {
558
- h(ve(o));
644
+ onTransportError: (i) => {
645
+ d($e(i));
559
646
  }
560
647
  });
561
- f.start();
562
- const S = U(t.target);
648
+ m.start();
649
+ const S = B(t.target);
563
650
  return S.render(
564
- x(X, {
651
+ G(oe, {
565
652
  mode: t.mode,
566
653
  store: e,
567
654
  bundleSignal: r,
568
- statusSignal: c,
569
- crossfadeKeySignal: i,
570
- sendInput: (o) => f.sendInput(o)
655
+ statusSignal: o,
656
+ crossfadeKeySignal: c,
657
+ sendInput: (i) => m.sendInput(i)
571
658
  })
572
659
  ), {
573
660
  disconnect() {
574
- a && (a = !1, f.close(), S.unmount());
661
+ l && (l = !1, j?.(), m.close(), S.unmount());
575
662
  },
576
- setToken(o) {
577
- a && f.setToken(o);
663
+ setToken(i) {
664
+ l && m.setToken(i);
578
665
  }
579
666
  };
580
- async function A(o, g, L, y, T, M, N) {
581
- let w;
667
+ async function C(i, v, D, w, _, F, q) {
668
+ let E;
582
669
  try {
583
- w = await o.get(y, T);
584
- } catch (E) {
585
- N({
670
+ E = await i.get(w, _);
671
+ } catch (I) {
672
+ q({
586
673
  code: "BUNDLE_FETCH_FAILED",
587
- message: E instanceof Error ? E.message : "render bundle fetch failed",
674
+ message: I instanceof Error ? I.message : "render bundle fetch failed",
588
675
  recoverable: !0
589
676
  });
590
677
  return;
591
678
  }
592
- a && (M(), g.value = w, L.value = `${y}::${T}`);
679
+ l && (F(), v.value = E, D.value = `${w}::${_}`);
593
680
  }
594
681
  }
595
- function ve(t) {
682
+ function $e(t) {
596
683
  return {
597
684
  code: t.code,
598
685
  message: t.message,
599
686
  recoverable: t.recoverable
600
687
  };
601
688
  }
602
- function ke(t) {
689
+ function je(t) {
603
690
  try {
604
691
  const e = new URL(t);
605
692
  return `${e.protocol === "wss:" ? "https:" : "http:"}//${e.host}`;
@@ -607,11 +694,97 @@ function ke(t) {
607
694
  return "";
608
695
  }
609
696
  }
697
+ const Ce = ["visible", "opacity", "universal_opacity", "rotation", "sizing"];
698
+ function u(t) {
699
+ return /* @__PURE__ */ new Set([...Ce, ...t]);
700
+ }
701
+ const De = {
702
+ stack: u(["direction", "gap", "wrap", "crossGap", "align", "justify"]),
703
+ grid: u(["cols", "rows", "gap"]),
704
+ frame: u([
705
+ "x",
706
+ "y",
707
+ "width",
708
+ "height",
709
+ "scale",
710
+ "rotate",
711
+ "background",
712
+ "backgrounds",
713
+ "clipsContent"
714
+ ]),
715
+ text: u([
716
+ "value",
717
+ "size",
718
+ "font",
719
+ "weight",
720
+ "colour",
721
+ "align",
722
+ "lineHeight",
723
+ "letterSpacing",
724
+ "textTransform",
725
+ "textDecoration",
726
+ "fontStyle",
727
+ "maxLines"
728
+ ]),
729
+ image: u(["src", "alt", "fit", "position", "width", "height"]),
730
+ shape: u([
731
+ "geometry",
732
+ "kind",
733
+ "width",
734
+ "height",
735
+ "radius",
736
+ "fill",
737
+ "fills",
738
+ "stroke",
739
+ "stroke_width",
740
+ "strokes",
741
+ "pathData",
742
+ "paths",
743
+ "ariaLabel"
744
+ ]),
745
+ media: u(["src", "loop", "mute", "autoplay", "fit"]),
746
+ instance: u(["scene_id", "scene_version", "size", "position"]),
747
+ // `repeat` is dispatched specially by the tree ; its only consumed
748
+ // binding is `items`.
749
+ repeat: /* @__PURE__ */ new Set(["items"])
750
+ };
751
+ function Fe(t, e) {
752
+ const s = De[t];
753
+ return !!(s === void 0 || s.has(e) || t === "instance" && (e === "params" || e.startsWith("params.")));
754
+ }
755
+ const M = /* @__PURE__ */ new WeakSet();
756
+ function et(t) {
757
+ if (M.has(t)) return;
758
+ M.add(t);
759
+ const e = /* @__PURE__ */ new Set([
760
+ ...Object.keys(t.props ?? {}),
761
+ ...Object.keys(t.bindings ?? {})
762
+ ]);
763
+ for (const s of e)
764
+ Fe(t.kind, s) || $(
765
+ t.id,
766
+ `${t.kind}.${s}`,
767
+ "is not consumed by this primitive's renderer ; the prop is ignored (anti-silent-drop, ADR 001 §3.4)"
768
+ );
769
+ }
610
770
  export {
611
- Le as a,
612
- Ae as m,
613
- Oe as r,
614
- Re as t,
615
- Ie as u
771
+ ce as A,
772
+ L as B,
773
+ Ke as F,
774
+ De as P,
775
+ Ie as S,
776
+ et as a,
777
+ ae as b,
778
+ O as c,
779
+ Ve as d,
780
+ $ as e,
781
+ Oe as i,
782
+ Ze as m,
783
+ Qe as r,
784
+ me as s,
785
+ Je as t,
786
+ Ye as u,
787
+ U as v,
788
+ pe as w
616
789
  };
617
- //# sourceMappingURL=index-oteiocFe.js.map
790
+ //# sourceMappingURL=index-Crkij3C4.js.map