@lumencast/runtime 0.3.0 → 0.5.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 (130) 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 +33 -1
  12. package/dist/animate/transitions.d.ts.map +1 -1
  13. package/dist/animate/transitions.js +78 -3
  14. package/dist/animate/transitions.js.map +1 -1
  15. package/dist/{broadcast-B82fQPph.js → broadcast-3vYij4k-.js} +3 -3
  16. package/dist/{broadcast-B82fQPph.js.map → broadcast-3vYij4k-.js.map} +1 -1
  17. package/dist/{control-DIfwMYRb.js → control-BFNkY7-6.js} +4 -4
  18. package/dist/{control-DIfwMYRb.js.map → control-BFNkY7-6.js.map} +1 -1
  19. package/dist/{index-BFZXQAD7.js → index-CyOlpZAL.js} +318 -145
  20. package/dist/index-CyOlpZAL.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 +11 -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 +48 -6
  35. package/dist/render/bundle.d.ts.map +1 -1
  36. package/dist/render/bundle.js +71 -4
  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 +44 -13
  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 +8 -5
  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 +58 -14
  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 +181 -9
  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-DNHbHdag.js → status-pill-DIpXc5du.js} +2 -2
  97. package/dist/{status-pill-DNHbHdag.js.map → status-pill-DIpXc5du.js.map} +1 -1
  98. package/dist/{test-Dp0QrKYM.js → test-ByRec1kd.js} +4 -4
  99. package/dist/{test-Dp0QrKYM.js.map → test-ByRec1kd.js.map} +1 -1
  100. package/dist/tree-D5wYHpPu.js +1230 -0
  101. package/dist/tree-D5wYHpPu.js.map +1 -0
  102. package/dist/types.d.ts +26 -0
  103. package/dist/types.d.ts.map +1 -1
  104. package/package.json +5 -4
  105. package/src/animate/frame-coalescer.ts +63 -0
  106. package/src/animate/keyframes.ts +24 -5
  107. package/src/animate/transitions.ts +85 -3
  108. package/src/index.ts +24 -0
  109. package/src/mount.ts +12 -1
  110. package/src/render/bind-animate.tsx +370 -0
  111. package/src/render/bundle.ts +102 -10
  112. package/src/render/color-interp.ts +303 -0
  113. package/src/render/css-color.ts +145 -0
  114. package/src/render/diagnostics.ts +75 -0
  115. package/src/render/fill.tsx +85 -14
  116. package/src/render/filter-clamp.ts +99 -0
  117. package/src/render/keyframe-player.tsx +10 -2
  118. package/src/render/primitives/frame.tsx +53 -14
  119. package/src/render/primitives/image.tsx +8 -4
  120. package/src/render/primitives/index.ts +3 -0
  121. package/src/render/primitives/instance.tsx +14 -15
  122. package/src/render/primitives/shape.tsx +78 -14
  123. package/src/render/primitives/text.tsx +226 -9
  124. package/src/render/prop-allowlist.ts +119 -0
  125. package/src/render/svg-path.ts +215 -0
  126. package/src/render/tree.tsx +41 -6
  127. package/src/types.ts +27 -0
  128. package/dist/index-BFZXQAD7.js.map +0 -1
  129. package/dist/tree-x5Qd9Kq0.js +0 -508
  130. package/dist/tree-x5Qd9Kq0.js.map +0 -1
@@ -0,0 +1,329 @@
1
+ // LSML 1.1 §6.3 `bindAnimate` — continuous interpolation toward a live
2
+ // leaf value (ADR 001 §3.3, issue #33).
3
+ //
4
+ // Per binding, the hook subscribes the existing leaf-grain signal and
5
+ // retargets a Framer motion value on change — NO remount, the DOM node
6
+ // is identical before/after (RC#6). Scalar channels (§6.1) ride motion
7
+ // values attached to a wrapping `motion.div` ; colour channels (§6.5)
8
+ // are interpolated component-wise in sRGB through the strict shared
9
+ // parser and flow back into the primitive's resolved prop (which
10
+ // re-validates them — RC#11 belt and braces).
11
+ //
12
+ // Anti-DoS (Bastion RC#13) : deltas are coalesced per frame — one
13
+ // retarget max per rAF per binding, whatever the producer's rate
14
+ // (1 kHz tested in E2E). Retargets interrupt in-flight springs with
15
+ // velocity carry (§6.2/§6.4 — framer preserves a motion value's
16
+ // velocity when a spring animation is replaced ; no snap).
17
+ //
18
+ // R8 runtime half (issue #42) : `filter.blur` / `filter.brightness`
19
+ // values arriving live re-pass the same caps as the compiler before
20
+ // they may touch the composed CSS filter (see filter-clamp.ts).
21
+ //
22
+ // Stagger (§6.7) : inside a `repeat` iteration the FIRST animated
23
+ // retarget per binding is delayed by the ambient StaggerContext delay ;
24
+ // steady-state retargets are never delayed (a permanently-lagging gauge
25
+ // would defeat the purpose of a live binding). Documented hypothesis —
26
+ // the spec only constrains animation *starts*.
27
+ import { animate, useMotionValue, useTransform, } from "framer-motion";
28
+ import { effect } from "@preact/signals-react";
29
+ import { useContext, useEffect, useMemo, useRef, useState } from "react";
30
+ import { scopedPath } from "./scope";
31
+ import { StaggerContext } from "./stagger-context";
32
+ import { toFramer } from "../animate/transitions";
33
+ import { createFrameCoalescer } from "../animate/frame-coalescer";
34
+ import { clampFilterChannel, warnRejectedFilter } from "./filter-clamp";
35
+ import { warnRejectedColor } from "./css-color";
36
+ import { emitDiagnostic } from "./diagnostics";
37
+ import { cssColorToRgba, mixRgba, serializeRgba } from "./color-interp";
38
+ /** §6.5 colour-typed bindAnimate keys → the runtime prop name the
39
+ * primitive reads (and re-validates through `parseCssColor`). */
40
+ export const BIND_ANIMATE_COLOR_PROPS = {
41
+ "style.color": "colour",
42
+ fill: "fill",
43
+ background: "background",
44
+ };
45
+ /**
46
+ * Validate + normalise one live bindAnimate value into per-channel
47
+ * numeric targets. Returns `null` on rejection (wrong JSON shape per
48
+ * §6.3, non-finite numbers, filter values outside the R8 caps when the
49
+ * channel rejects rather than clamps). A `null` keeps the last
50
+ * known-good target — the raw input never reaches a style.
51
+ *
52
+ * Exported pure for the hostile-delta fixture suite (issue #42).
53
+ */
54
+ export function resolveScalarTargets(key, raw) {
55
+ switch (key) {
56
+ case "opacity": {
57
+ const v = toFiniteScalar(raw);
58
+ if (v === null)
59
+ return null;
60
+ return { opacity: v < 0 ? 0 : v > 1 ? 1 : v };
61
+ }
62
+ case "transform.translate": {
63
+ if (!Array.isArray(raw) || raw.length !== 2)
64
+ return null;
65
+ const tx = toFiniteScalar(raw[0]);
66
+ const ty = toFiniteScalar(raw[1]);
67
+ if (tx === null || ty === null)
68
+ return null;
69
+ return { x: tx, y: ty };
70
+ }
71
+ case "transform.scale": {
72
+ const s = toFiniteScalar(raw);
73
+ if (s !== null)
74
+ return { scaleX: s, scaleY: s };
75
+ if (Array.isArray(raw) && raw.length === 2) {
76
+ const sx = toFiniteScalar(raw[0]);
77
+ const sy = toFiniteScalar(raw[1]);
78
+ if (sx === null || sy === null)
79
+ return null;
80
+ return { scaleX: sx, scaleY: sy };
81
+ }
82
+ return null;
83
+ }
84
+ case "transform.rotate": {
85
+ const v = toFiniteScalar(raw);
86
+ if (v === null)
87
+ return null;
88
+ return { rotate: v };
89
+ }
90
+ case "filter.blur": {
91
+ const v = clampFilterChannel("blur", raw);
92
+ return v === null ? null : { blur: v };
93
+ }
94
+ case "filter.brightness": {
95
+ const v = clampFilterChannel("brightness", raw);
96
+ return v === null ? null : { brightness: v };
97
+ }
98
+ default:
99
+ return null;
100
+ }
101
+ }
102
+ // ── IEEE-754 `-0` policy (R8 / PR #39 coherence, issue #33) ───────────
103
+ // `-0 < 0` is FALSE, so a plain sign clamp lets -0 through. Uniform
104
+ // rule : no -0 ever reaches a motion value or a style. Per channel :
105
+ // · opacity — the negative case CLAMPS to 0 (`-5 → 0`), so -0 follows
106
+ // the same line and normalises to +0 (rejecting -0 while clamping
107
+ // -5 would be incoherent within the channel) ;
108
+ // · translate / scale / rotate — negatives are valid values and
109
+ // `-0 == 0` is mathematically neutral, so -0 normalises to +0 (a
110
+ // producer computing `-x` at x = 0 must not be rejected into a
111
+ // stale last-good) ;
112
+ // · filter.blur / filter.brightness — REJECTED (null → last-good) by
113
+ // `clampFilterChannel` : the R8 gate treats any negative sign,
114
+ // including -0, as hostile input (compiler mirror, issues #39/#41
115
+ // — do not relax here).
116
+ /** Finite-number gate + `-0 → +0` normalisation for the generic scalar
117
+ * channels (filter channels go through `clampFilterChannel` instead). */
118
+ function toFiniteScalar(v) {
119
+ if (typeof v !== "number" || !Number.isFinite(v))
120
+ return null;
121
+ return Object.is(v, -0) ? 0 : v;
122
+ }
123
+ /** Default retarget transition when neither a per-leaf wire directive
124
+ * nor a compiled `transitions` entry resolves : the §6.2 default
125
+ * spring (stiffness 170, damping 26, mass 1). A spring is the only
126
+ * curve with well-defined retarget semantics (velocity carry) — a
127
+ * documented hypothesis, see the PR for issue #33. */
128
+ export const DEFAULT_BIND_ANIMATE_TRANSITION = {
129
+ kind: "spring",
130
+ stiffness: 170,
131
+ damping: 26,
132
+ mass: 1,
133
+ };
134
+ /** node.transitions lookup key for each bindAnimate key (mirrors the
135
+ * compiler's `transitionKeysForBindAnimate`). */
136
+ function transitionLookupKey(key) {
137
+ switch (key) {
138
+ case "opacity":
139
+ return "opacity";
140
+ case "transform.translate":
141
+ return "x";
142
+ case "transform.scale":
143
+ return "scale";
144
+ case "transform.rotate":
145
+ return "rotate";
146
+ case "filter.blur":
147
+ case "filter.brightness":
148
+ return "filter";
149
+ default:
150
+ return BIND_ANIMATE_COLOR_PROPS[key] ?? key;
151
+ }
152
+ }
153
+ const NO_COLORS = {};
154
+ /**
155
+ * Drive a node's `animateBindings`. Must be called unconditionally
156
+ * (hook) ; cheap no-op when the node has no bindings.
157
+ */
158
+ export function useBindAnimate(node, store, scope) {
159
+ const bindings = node.animateBindings;
160
+ const staggerDelayMs = useContext(StaggerContext);
161
+ // Fixed channel set — created unconditionally so hook order is
162
+ // stable ; unbound channels stay at their identity value.
163
+ const opacity = useMotionValue(1);
164
+ const x = useMotionValue(0);
165
+ const y = useMotionValue(0);
166
+ const scaleX = useMotionValue(1);
167
+ const scaleY = useMotionValue(1);
168
+ const rotate = useMotionValue(0);
169
+ const blur = useMotionValue(0);
170
+ const brightness = useMotionValue(1);
171
+ // Composed CSS filter — both functions always present so framer
172
+ // interpolates structurally-identical lists (same form as the
173
+ // compiler emits, clamped per R8).
174
+ const filter = useTransform([blur, brightness], ([b, br]) => `blur(${b}px) brightness(${br})`);
175
+ const [colorProps, setColorProps] = useState(NO_COLORS);
176
+ const channels = useRef({
177
+ opacity,
178
+ x,
179
+ y,
180
+ scaleX,
181
+ scaleY,
182
+ rotate,
183
+ blur,
184
+ brightness,
185
+ });
186
+ useEffect(() => {
187
+ if (!bindings || Object.keys(bindings).length === 0)
188
+ return;
189
+ const mvs = channels.current;
190
+ const controls = new Map();
191
+ const colorState = new Map();
192
+ const animatedOnce = new Set();
193
+ let mounted = false;
194
+ const transitionFor = (key, fullPath) => {
195
+ const live = store.transitionSignal(fullPath).peek();
196
+ const declared = live ?? node.transitions?.[transitionLookupKey(key)];
197
+ const base = toFramer(declared ?? DEFAULT_BIND_ANIMATE_TRANSITION);
198
+ // §6.7 — stagger delays only the first animated retarget.
199
+ if (staggerDelayMs > 0 && !animatedOnce.has(key)) {
200
+ return { ...base, delay: staggerDelayMs / 1000 };
201
+ }
202
+ return base;
203
+ };
204
+ const dispatch = (key, value, instant) => {
205
+ const colorProp = BIND_ANIMATE_COLOR_PROPS[key];
206
+ const fullPath = scopedPath(scope, bindings[key]);
207
+ if (colorProp !== undefined) {
208
+ // §6.5 — canonicalise BOTH endpoints through the strict parser
209
+ // before interpolating ; never a raw string.
210
+ const end = cssColorToRgba(value);
211
+ if (end === null) {
212
+ warnRejectedColor(`bindAnimate.${key}`, node.id);
213
+ return;
214
+ }
215
+ const prev = colorState.get(key);
216
+ if (instant || prev === undefined) {
217
+ colorState.set(key, { current: end });
218
+ setColorProps((p) => ({ ...p, [colorProp]: serializeRgba(end) }));
219
+ return;
220
+ }
221
+ const start = prev.current;
222
+ const tx = transitionFor(key, fullPath);
223
+ animatedOnce.add(key);
224
+ controls.get(`color:${key}`)?.stop();
225
+ controls.set(`color:${key}`, animate(0, 1, {
226
+ ...tx,
227
+ onUpdate: (t) => {
228
+ const mixed = mixRgba(start, end, t);
229
+ prev.current = mixed;
230
+ setColorProps((p) => ({ ...p, [colorProp]: serializeRgba(mixed) }));
231
+ },
232
+ }));
233
+ return;
234
+ }
235
+ const targets = resolveScalarTargets(key, value);
236
+ if (targets === null) {
237
+ // R9 — the offending value is never logged.
238
+ if (key.startsWith("filter."))
239
+ warnRejectedFilter(`bindAnimate.${key}`, node.id);
240
+ else
241
+ warnRejectedBindValue(key, node.id);
242
+ return;
243
+ }
244
+ if (instant) {
245
+ // §6.3.1 — on mount the rendered state initialises from the
246
+ // bound value instantly (there is no previous state).
247
+ for (const [ch, v] of Object.entries(targets)) {
248
+ mvs[ch].jump(v);
249
+ }
250
+ return;
251
+ }
252
+ const tx = transitionFor(key, fullPath);
253
+ animatedOnce.add(key);
254
+ for (const [ch, v] of Object.entries(targets)) {
255
+ // framer's animate() replaces any in-flight animation on the
256
+ // motion value and seeds the new spring with the value's
257
+ // current velocity — §6.2 velocity carry, no snap.
258
+ controls.set(ch, animate(mvs[ch], v, tx));
259
+ }
260
+ };
261
+ // RC#13 — one retarget max per rAF per binding.
262
+ const coalescer = createFrameCoalescer((key, value) => dispatch(key, value, false));
263
+ const disposers = Object.entries(bindings).map(([key, path]) => effect(() => {
264
+ const v = store.signal(scopedPath(scope, path)).value;
265
+ if (v === undefined)
266
+ return;
267
+ if (!mounted)
268
+ dispatch(key, v, true);
269
+ else
270
+ coalescer.push(key, v);
271
+ }));
272
+ mounted = true;
273
+ return () => {
274
+ for (const d of disposers)
275
+ d();
276
+ coalescer.dispose();
277
+ for (const c of controls.values())
278
+ c.stop();
279
+ };
280
+ // node/store/scope identity changes re-wire every subscription ;
281
+ // staggerDelayMs is stable per repeat iteration.
282
+ }, [node, bindings, store, scope, staggerDelayMs]);
283
+ const motionStyle = useMemo(() => {
284
+ if (!bindings)
285
+ return null;
286
+ const style = {};
287
+ let any = false;
288
+ for (const key of Object.keys(bindings)) {
289
+ switch (key) {
290
+ case "opacity":
291
+ style.opacity = opacity;
292
+ any = true;
293
+ break;
294
+ case "transform.translate":
295
+ style.x = x;
296
+ style.y = y;
297
+ any = true;
298
+ break;
299
+ case "transform.scale":
300
+ style.scaleX = scaleX;
301
+ style.scaleY = scaleY;
302
+ any = true;
303
+ break;
304
+ case "transform.rotate":
305
+ style.rotate = rotate;
306
+ any = true;
307
+ break;
308
+ case "filter.blur":
309
+ case "filter.brightness":
310
+ style.filter = filter;
311
+ any = true;
312
+ break;
313
+ default:
314
+ break; // colour keys flow through colorProps, not the wrapper
315
+ }
316
+ }
317
+ if (!any)
318
+ return null;
319
+ style.willChange = "transform, opacity, filter";
320
+ return style;
321
+ }, [bindings, opacity, x, y, scaleX, scaleY, rotate, filter]);
322
+ return { motionStyle, colorProps };
323
+ }
324
+ /** R9 diagnostic — shape-invalid bindAnimate value (non-filter
325
+ * channels). Structured event, value withheld. */
326
+ function warnRejectedBindValue(key, nodeId) {
327
+ emitDiagnostic(nodeId, `bindAnimate.${key}`, "rejected bound value : JSON shape does not match the property type (LSML §6.3)");
328
+ }
329
+ //# sourceMappingURL=bind-animate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bind-animate.js","sourceRoot":"","sources":["../../src/render/bind-animate.tsx"],"names":[],"mappings":"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"}
@@ -22,6 +22,17 @@ export interface RenderNode {
22
22
  * the primitive applies no `initial` and the prior no-mount-play
23
23
  * behaviour holds (backward compatible). */
24
24
  animate_initial?: Record<string, number | string>;
25
+ /** LSML 1.1 §6.3 — animation targets bound to leaf paths
26
+ * (`bindAnimate`). Keys are the spec property names (`opacity`,
27
+ * `transform.translate`, `transform.scale`, `transform.rotate`,
28
+ * `filter.blur`, `filter.brightness`, plus the kind's colour-typed
29
+ * property per §6.5 : `style.color` / `fill` / `background`) ; values
30
+ * are LeafPaths. The runtime subscribes each path's leaf-grain signal
31
+ * and retargets a Framer motion value on change — continuous
32
+ * interpolation toward the live value, no remount. Deltas are
33
+ * coalesced per frame (one retarget max per rAF per binding,
34
+ * ADR 001 RC#13). */
35
+ animateBindings?: Record<string, string>;
25
36
  /** LSML 1.1 §6.6 — multi-step keyframe sequence played on mount or
26
37
  * whenever `keyframes.key` (LeafPath) changes. Coexists with
27
38
  * `transitions` ; the runtime applies whichever was last triggered
@@ -63,9 +74,11 @@ export interface RenderBundle {
63
74
  external_adapters?: ExternalAdapter[];
64
75
  assets?: Asset[];
65
76
  /** LSML 1.1 §17.3 — capability profiles required for correct rendering.
66
- * Each entry is a `<vendor>.<name>-<version>` string. The runtime
67
- * checks every entry against its supported list ; an unrecognised
68
- * profile raises BUNDLE_INCOMPATIBLE per §17.3.1. */
77
+ * Each entry is an `x-<vendor>.<name>/<version>` string. The runtime
78
+ * checks every behavioural entry against its supported list ; an
79
+ * unrecognised behavioural profile raises BUNDLE_INCOMPATIBLE per
80
+ * §17.3.1. Authoring profiles (`x-<vendor>.authoring/<major>`, §17.5.1)
81
+ * are advisory : ignored at render time, never a rejection cause. */
69
82
  profiles?: string[];
70
83
  }
71
84
  /**
@@ -80,6 +93,10 @@ export interface RenderBundle {
80
93
  * reject.
81
94
  */
82
95
  export declare const SUPPORTED_PROFILES: ReadonlySet<string>;
96
+ /** True when `id` has the complete authoring-profile form
97
+ * `x-<vendor>.authoring/<major>` (LSML 1.1 §17.5.1, ADR 001 RC#14).
98
+ * Such profiles are advisory : ignored at render time, never rejected. */
99
+ export declare function isAuthoringProfile(id: string): boolean;
83
100
  export declare class BundleIncompatibleError extends Error {
84
101
  readonly code: "BUNDLE_INCOMPATIBLE";
85
102
  readonly unsupportedProfiles: string[];
@@ -87,7 +104,20 @@ export declare class BundleIncompatibleError extends Error {
87
104
  }
88
105
  /** Validate a bundle's `profiles[]` against the runtime's supported
89
106
  * set. Throws `BundleIncompatibleError` listing every offending entry
90
- * when at least one is not supported. */
107
+ * when at least one behavioural profile is not supported.
108
+ *
109
+ * Authoring profiles (`x-<vendor>.authoring/<major>`, LSML 1.1 §17.5.1)
110
+ * are advisory and skipped : their absence from the supported set is
111
+ * never a rejection cause. Every other (behavioural) unsupported profile
112
+ * keeps the hard §17.3.1 `BUNDLE_INCOMPATIBLE` rejection.
113
+ *
114
+ * Malformed-shape guard : `bundle` may come from an unchecked
115
+ * `json as RenderBundle` cast on untrusted server JSON
116
+ * (`FetcherImpl.get`). A non-array `profiles` or a non-string entry is
117
+ * therefore reachable at runtime and is rejected as
118
+ * `BundleIncompatibleError` (typed, code BUNDLE_INCOMPATIBLE) — never a
119
+ * raw TypeError. The diagnostic never echoes the malformed value, only a
120
+ * shape placeholder. */
91
121
  export declare function validateBundleProfiles(bundle: {
92
122
  profiles?: string[];
93
123
  }, supported?: ReadonlySet<string>): void;
@@ -98,12 +128,24 @@ export interface BundleFetcher {
98
128
  * flight" handoff path. */
99
129
  preload(bundle: RenderBundle): void;
100
130
  }
131
+ /** Resolves the absolute URL of a scene's render bundle. Supplied by the
132
+ * host (`MountOptions.resolveBundleUrl`) when the server is not at the
133
+ * default host-root LSDP/1 layout — e.g. reached through a gateway prefix
134
+ * (`https://gw/orion/api/v1/scenes/{id}/render-bundle?v={hash}`). */
135
+ export type BundleUrlResolver = (sceneId: string, sceneVersion: string) => string;
101
136
  export interface BundleFetcherOptions {
102
137
  /** Base URL of the server. The fetcher constructs
103
- * `${baseUrl}/lsdp/v1/scenes/{id}/bundle?v={hash}`. */
138
+ * `${baseUrl}/lsdp/v1/scenes/{id}/bundle?v={hash}`. Ignored when
139
+ * `resolveUrl` is provided. */
104
140
  baseUrl: string;
105
- /** Path prefix for bundle resolution. Defaults to `/lsdp/v1/scenes`. */
141
+ /** Path prefix for bundle resolution. Defaults to `/lsdp/v1/scenes`.
142
+ * Ignored when `resolveUrl` is provided. */
106
143
  pathPrefix?: string;
144
+ /** When set, takes full control of URL construction — the host owns the
145
+ * whole URL (base, path prefix and `/bundle` vs `/render-bundle` suffix).
146
+ * Lets a gateway-prefixed server be addressed without changing the
147
+ * host-root default. */
148
+ resolveUrl?: BundleUrlResolver;
107
149
  fetchImpl?: typeof fetch;
108
150
  }
109
151
  export declare function createBundleFetcher(opts: BundleFetcherOptions): BundleFetcher;
@@ -1 +1 @@
1
- {"version":3,"file":"bundle.d.ts","sourceRoot":"","sources":["../../src/render/bundle.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"bundle.d.ts","sourceRoot":"","sources":["../../src/render/bundle.ts"],"names":[],"mappings":"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"}
@@ -24,6 +24,45 @@
24
24
  export const SUPPORTED_PROFILES = new Set([
25
25
  "x-lumencast.color-srgb-1.0",
26
26
  ]);
27
+ // LSML 1.1 §17.5.1 + ADR 001 RC#14 — authoring-profile detection.
28
+ //
29
+ // An authoring profile is advisory : a runtime that does not support it
30
+ // MUST NOT reject the bundle and renders the underlying primitives as if
31
+ // the profile were absent. Detection matches the COMPLETE identifier form
32
+ // `x-<vendor>.authoring/<major>` :
33
+ //
34
+ // - `x-` prefix, then one or more lowercase name segments separated by
35
+ // dots, where `.authoring` is the EXACT TERMINAL segment before `/` ;
36
+ // - `<major>` is a bare integer (no `.minor`) ;
37
+ // - never a substring test : a behavioural profile whose name merely
38
+ // *contains* `.authoring` in a non-terminal position is NOT exempted
39
+ // and keeps §17.3.1 hard-rejection semantics.
40
+ //
41
+ // Anti-ReDoS note : both regexes below are anchored and unambiguous —
42
+ // the character classes exclude the `.` and `/` separators, so there is
43
+ // exactly one possible parse per input (linear time, no backtracking).
44
+ const AUTHORING_NAME_RE = /^x-[a-z0-9-]+(?:\.[a-z0-9-]+)*$/;
45
+ const AUTHORING_MAJOR_RE = /^(?:0|[1-9][0-9]*)$/;
46
+ const AUTHORING_SUFFIX = ".authoring";
47
+ /** True when `id` has the complete authoring-profile form
48
+ * `x-<vendor>.authoring/<major>` (LSML 1.1 §17.5.1, ADR 001 RC#14).
49
+ * Such profiles are advisory : ignored at render time, never rejected. */
50
+ export function isAuthoringProfile(id) {
51
+ const slash = id.indexOf("/");
52
+ if (slash < 0)
53
+ return false;
54
+ const name = id.slice(0, slash);
55
+ const major = id.slice(slash + 1);
56
+ if (!AUTHORING_MAJOR_RE.test(major))
57
+ return false;
58
+ if (!name.endsWith(AUTHORING_SUFFIX))
59
+ return false;
60
+ // `name` minus the terminal `.authoring` segment must still be a valid
61
+ // `x-<vendor>[.<segment>...]` prefix — this is what makes `.authoring`
62
+ // a real terminal segment rather than a substring of another one
63
+ // (e.g. `x-evilauthoring/1` or `x-evil.authoring.fx/1` do not match).
64
+ return AUTHORING_NAME_RE.test(name.slice(0, -AUTHORING_SUFFIX.length));
65
+ }
27
66
  export class BundleIncompatibleError extends Error {
28
67
  code = "BUNDLE_INCOMPATIBLE";
29
68
  unsupportedProfiles;
@@ -35,12 +74,32 @@ export class BundleIncompatibleError extends Error {
35
74
  }
36
75
  /** Validate a bundle's `profiles[]` against the runtime's supported
37
76
  * set. Throws `BundleIncompatibleError` listing every offending entry
38
- * when at least one is not supported. */
77
+ * when at least one behavioural profile is not supported.
78
+ *
79
+ * Authoring profiles (`x-<vendor>.authoring/<major>`, LSML 1.1 §17.5.1)
80
+ * are advisory and skipped : their absence from the supported set is
81
+ * never a rejection cause. Every other (behavioural) unsupported profile
82
+ * keeps the hard §17.3.1 `BUNDLE_INCOMPATIBLE` rejection.
83
+ *
84
+ * Malformed-shape guard : `bundle` may come from an unchecked
85
+ * `json as RenderBundle` cast on untrusted server JSON
86
+ * (`FetcherImpl.get`). A non-array `profiles` or a non-string entry is
87
+ * therefore reachable at runtime and is rejected as
88
+ * `BundleIncompatibleError` (typed, code BUNDLE_INCOMPATIBLE) — never a
89
+ * raw TypeError. The diagnostic never echoes the malformed value, only a
90
+ * shape placeholder. */
39
91
  export function validateBundleProfiles(bundle, supported = SUPPORTED_PROFILES) {
40
92
  const profiles = bundle.profiles;
41
- if (!profiles || profiles.length === 0)
93
+ if (!profiles)
94
+ return;
95
+ if (!Array.isArray(profiles)) {
96
+ throw new BundleIncompatibleError(["<malformed: profiles is not an array>"]);
97
+ }
98
+ if (profiles.length === 0)
42
99
  return;
43
- const missing = profiles.filter((p) => !supported.has(p));
100
+ const missing = profiles
101
+ .filter((p) => typeof p !== "string" || (!isAuthoringProfile(p) && !supported.has(p)))
102
+ .map((p) => (typeof p === "string" ? p : "<malformed: non-string profile entry>"));
44
103
  if (missing.length > 0) {
45
104
  throw new BundleIncompatibleError(missing);
46
105
  }
@@ -49,12 +108,20 @@ class FetcherImpl {
49
108
  cache = new Map();
50
109
  baseUrl;
51
110
  pathPrefix;
111
+ resolveUrl;
52
112
  fetchImpl;
53
113
  constructor(opts) {
54
114
  this.baseUrl = opts.baseUrl.replace(/\/$/, "");
55
115
  this.pathPrefix = (opts.pathPrefix ?? "/lsdp/v1/scenes").replace(/\/$/, "");
116
+ this.resolveUrl = opts.resolveUrl;
56
117
  this.fetchImpl = opts.fetchImpl ?? globalThis.fetch.bind(globalThis);
57
118
  }
119
+ buildUrl(sceneId, sceneVersion) {
120
+ if (this.resolveUrl) {
121
+ return this.resolveUrl(sceneId, sceneVersion);
122
+ }
123
+ return `${this.baseUrl}${this.pathPrefix}/${encodeURIComponent(sceneId)}/bundle?v=${encodeURIComponent(sceneVersion)}`;
124
+ }
58
125
  preload(bundle) {
59
126
  // LSML 1.1 §17.3.1 — reject early if any declared profile is
60
127
  // unsupported by this runtime. Authors get an actionable error
@@ -66,7 +133,7 @@ class FetcherImpl {
66
133
  const cached = this.cache.get(sceneVersion);
67
134
  if (cached)
68
135
  return cached;
69
- const url = `${this.baseUrl}${this.pathPrefix}/${encodeURIComponent(sceneId)}/bundle?v=${encodeURIComponent(sceneVersion)}`;
136
+ const url = this.buildUrl(sceneId, sceneVersion);
70
137
  const response = await this.fetchImpl(url);
71
138
  if (!response.ok) {
72
139
  throw new Error(`bundle fetch failed: ${response.status} ${response.statusText}`);
@@ -1 +1 @@
1
- {"version":3,"file":"bundle.js","sourceRoot":"","sources":["../../src/render/bundle.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"bundle.js","sourceRoot":"","sources":["../../src/render/bundle.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /** RGBA channels, each in [0, 1]. */
2
+ export type Rgba = readonly [number, number, number, number];
3
+ /**
4
+ * Canonicalise + convert an untrusted colour value to RGBA channels in
5
+ * [0, 1]. The value passes through `parseCssColor` FIRST — anything the
6
+ * strict parser rejects converts to `null` here (never interpolate a
7
+ * raw string, §6.5 step 1 / RC#11). `currentcolor` is also rejected :
8
+ * it has no concrete channels without computed-style context.
9
+ */
10
+ export declare function cssColorToRgba(value: unknown): Rgba | null;
11
+ /** Component-wise sRGB lerp (§6.5 step 2). `t` may overshoot (springs) ;
12
+ * channels clamp back into [0, 1] after mixing. */
13
+ export declare function mixRgba(a: Rgba, b: Rgba, t: number): Rgba;
14
+ /** Serialise RGBA back to `rgba()` form (§6.5 step 3). The output is
15
+ * always re-accepted by `parseCssColor` (integer channels, alpha with
16
+ * at most 4 decimals). */
17
+ export declare function serializeRgba(rgba: Rgba): string;
18
+ //# sourceMappingURL=color-interp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"color-interp.d.ts","sourceRoot":"","sources":["../../src/render/color-interp.ts"],"names":[],"mappings":"AAmBA,qCAAqC;AACrC,MAAM,MAAM,IAAI,GAAG,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AA8J7D;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,GAAG,IAAI,CAuC1D;AAqDD;oDACoD;AACpD,wBAAgB,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAOzD;AAED;;2BAE2B;AAC3B,wBAAgB,aAAa,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAOhD"}