@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.
- package/LICENSE +201 -0
- package/README.md +79 -0
- package/dist/.tsbuildinfo +1 -0
- package/dist/animate/crossfade.d.ts +13 -0
- package/dist/animate/crossfade.d.ts.map +1 -0
- package/dist/animate/crossfade.js +10 -0
- package/dist/animate/crossfade.js.map +1 -0
- package/dist/animate/keyframes.d.ts +42 -0
- package/dist/animate/keyframes.d.ts.map +1 -0
- package/dist/animate/keyframes.js +94 -0
- package/dist/animate/keyframes.js.map +1 -0
- package/dist/animate/transitions.d.ts +38 -0
- package/dist/animate/transitions.d.ts.map +1 -0
- package/dist/animate/transitions.js +81 -0
- package/dist/animate/transitions.js.map +1 -0
- package/dist/app.d.ts +16 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +35 -0
- package/dist/app.js.map +1 -0
- package/dist/broadcast-BqOhSNsY.js +11 -0
- package/dist/broadcast-BqOhSNsY.js.map +1 -0
- package/dist/control-CRFn328D.js +16 -0
- package/dist/control-CRFn328D.js.map +1 -0
- package/dist/dev-entry.d.ts +2 -0
- package/dist/dev-entry.d.ts.map +1 -0
- package/dist/dev-entry.js +31 -0
- package/dist/dev-entry.js.map +1 -0
- package/dist/index-DUhPPRvw.js +583 -0
- package/dist/index-DUhPPRvw.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.html +46 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/internal/validate-options.d.ts +5 -0
- package/dist/internal/validate-options.d.ts.map +1 -0
- package/dist/internal/validate-options.js +19 -0
- package/dist/internal/validate-options.js.map +1 -0
- package/dist/lumencast.js +5 -0
- package/dist/lumencast.js.map +1 -0
- package/dist/modes/broadcast.d.ts +3 -0
- package/dist/modes/broadcast.d.ts.map +1 -0
- package/dist/modes/broadcast.js +9 -0
- package/dist/modes/broadcast.js.map +1 -0
- package/dist/modes/control.d.ts +4 -0
- package/dist/modes/control.d.ts.map +1 -0
- package/dist/modes/control.js +12 -0
- package/dist/modes/control.js.map +1 -0
- package/dist/modes/test.d.ts +4 -0
- package/dist/modes/test.d.ts.map +1 -0
- package/dist/modes/test.js +13 -0
- package/dist/modes/test.js.map +1 -0
- package/dist/mount.d.ts +3 -0
- package/dist/mount.d.ts.map +1 -0
- package/dist/mount.js +144 -0
- package/dist/mount.js.map +1 -0
- package/dist/overlay/control.d.ts +2 -0
- package/dist/overlay/control.d.ts.map +1 -0
- package/dist/overlay/control.js +127 -0
- package/dist/overlay/control.js.map +1 -0
- package/dist/overlay/runtime-context.d.ts +20 -0
- package/dist/overlay/runtime-context.d.ts.map +1 -0
- package/dist/overlay/runtime-context.js +14 -0
- package/dist/overlay/runtime-context.js.map +1 -0
- package/dist/overlay/status-pill.d.ts +2 -0
- package/dist/overlay/status-pill.d.ts.map +1 -0
- package/dist/overlay/status-pill.js +29 -0
- package/dist/overlay/status-pill.js.map +1 -0
- package/dist/overlay/test.d.ts +5 -0
- package/dist/overlay/test.d.ts.map +1 -0
- package/dist/overlay/test.js +116 -0
- package/dist/overlay/test.js.map +1 -0
- package/dist/render/bundle.d.ts +102 -0
- package/dist/render/bundle.d.ts.map +1 -0
- package/dist/render/bundle.js +86 -0
- package/dist/render/bundle.js.map +1 -0
- package/dist/render/fill.d.ts +41 -0
- package/dist/render/fill.d.ts.map +1 -0
- package/dist/render/fill.js +95 -0
- package/dist/render/fill.js.map +1 -0
- package/dist/render/keyframe-player.d.ts +10 -0
- package/dist/render/keyframe-player.d.ts.map +1 -0
- package/dist/render/keyframe-player.js +65 -0
- package/dist/render/keyframe-player.js.map +1 -0
- package/dist/render/primitives/frame.d.ts +12 -0
- package/dist/render/primitives/frame.d.ts.map +1 -0
- package/dist/render/primitives/frame.js +65 -0
- package/dist/render/primitives/frame.js.map +1 -0
- package/dist/render/primitives/grid.d.ts +4 -0
- package/dist/render/primitives/grid.d.ts.map +1 -0
- package/dist/render/primitives/grid.js +14 -0
- package/dist/render/primitives/grid.js.map +1 -0
- package/dist/render/primitives/image.d.ts +5 -0
- package/dist/render/primitives/image.d.ts.map +1 -0
- package/dist/render/primitives/image.js +25 -0
- package/dist/render/primitives/image.js.map +1 -0
- package/dist/render/primitives/index.d.ts +10 -0
- package/dist/render/primitives/index.d.ts.map +1 -0
- package/dist/render/primitives/index.js +22 -0
- package/dist/render/primitives/index.js.map +1 -0
- package/dist/render/primitives/instance.d.ts +4 -0
- package/dist/render/primitives/instance.d.ts.map +1 -0
- package/dist/render/primitives/instance.js +35 -0
- package/dist/render/primitives/instance.js.map +1 -0
- package/dist/render/primitives/media.d.ts +6 -0
- package/dist/render/primitives/media.d.ts.map +1 -0
- package/dist/render/primitives/media.js +19 -0
- package/dist/render/primitives/media.js.map +1 -0
- package/dist/render/primitives/shape.d.ts +12 -0
- package/dist/render/primitives/shape.d.ts.map +1 -0
- package/dist/render/primitives/shape.js +66 -0
- package/dist/render/primitives/shape.js.map +1 -0
- package/dist/render/primitives/stack.d.ts +13 -0
- package/dist/render/primitives/stack.d.ts.map +1 -0
- package/dist/render/primitives/stack.js +45 -0
- package/dist/render/primitives/stack.js.map +1 -0
- package/dist/render/primitives/text.d.ts +6 -0
- package/dist/render/primitives/text.d.ts.map +1 -0
- package/dist/render/primitives/text.js +27 -0
- package/dist/render/primitives/text.js.map +1 -0
- package/dist/render/scope.d.ts +10 -0
- package/dist/render/scope.d.ts.map +1 -0
- package/dist/render/scope.js +27 -0
- package/dist/render/scope.js.map +1 -0
- package/dist/render/stagger-context.d.ts +9 -0
- package/dist/render/stagger-context.d.ts.map +1 -0
- package/dist/render/stagger-context.js +22 -0
- package/dist/render/stagger-context.js.map +1 -0
- package/dist/render/tree.d.ts +9 -0
- package/dist/render/tree.d.ts.map +1 -0
- package/dist/render/tree.js +139 -0
- package/dist/render/tree.js.map +1 -0
- package/dist/render/universal-wrapper.d.ts +16 -0
- package/dist/render/universal-wrapper.d.ts.map +1 -0
- package/dist/render/universal-wrapper.js +58 -0
- package/dist/render/universal-wrapper.js.map +1 -0
- package/dist/state/apply-delta.d.ts +11 -0
- package/dist/state/apply-delta.d.ts.map +1 -0
- package/dist/state/apply-delta.js +23 -0
- package/dist/state/apply-delta.js.map +1 -0
- package/dist/state/apply-snapshot.d.ts +6 -0
- package/dist/state/apply-snapshot.d.ts.map +1 -0
- package/dist/state/apply-snapshot.js +6 -0
- package/dist/state/apply-snapshot.js.map +1 -0
- package/dist/state/store.d.ts +28 -0
- package/dist/state/store.d.ts.map +1 -0
- package/dist/state/store.js +119 -0
- package/dist/state/store.js.map +1 -0
- package/dist/status-pill-DCHvrd_y.js +241 -0
- package/dist/status-pill-DCHvrd_y.js.map +1 -0
- package/dist/test-DBCtwx_I.js +210 -0
- package/dist/test-DBCtwx_I.js.map +1 -0
- package/dist/transport/reconnect.d.ts +22 -0
- package/dist/transport/reconnect.d.ts.map +1 -0
- package/dist/transport/reconnect.js +60 -0
- package/dist/transport/reconnect.js.map +1 -0
- package/dist/transport/ws.d.ts +66 -0
- package/dist/transport/ws.d.ts.map +1 -0
- package/dist/transport/ws.js +270 -0
- package/dist/transport/ws.js.map +1 -0
- package/dist/tree-CnhX02kd.js +494 -0
- package/dist/tree-CnhX02kd.js.map +1 -0
- package/dist/types.d.ts +38 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/package.json +64 -0
- package/src/animate/crossfade.tsx +31 -0
- package/src/animate/keyframes.ts +142 -0
- package/src/animate/transitions.ts +116 -0
- package/src/app.tsx +84 -0
- package/src/dev-entry.tsx +38 -0
- package/src/index.ts +24 -0
- package/src/internal/validate-options.ts +20 -0
- package/src/modes/broadcast.tsx +8 -0
- package/src/modes/control.tsx +17 -0
- package/src/modes/test.tsx +19 -0
- package/src/mount.ts +169 -0
- package/src/overlay/control.tsx +239 -0
- package/src/overlay/runtime-context.tsx +37 -0
- package/src/overlay/status-pill.tsx +37 -0
- package/src/overlay/test.tsx +213 -0
- package/src/render/bundle.ts +208 -0
- package/src/render/fill.tsx +163 -0
- package/src/render/keyframe-player.tsx +89 -0
- package/src/render/primitives/frame.tsx +78 -0
- package/src/render/primitives/grid.tsx +20 -0
- package/src/render/primitives/image.tsx +35 -0
- package/src/render/primitives/index.ts +35 -0
- package/src/render/primitives/instance.tsx +70 -0
- package/src/render/primitives/media.tsx +28 -0
- package/src/render/primitives/shape.tsx +135 -0
- package/src/render/primitives/stack.tsx +48 -0
- package/src/render/primitives/text.tsx +38 -0
- package/src/render/scope.tsx +27 -0
- package/src/render/stagger-context.tsx +24 -0
- package/src/render/tree.tsx +182 -0
- package/src/render/universal-wrapper.tsx +95 -0
- package/src/state/apply-delta.ts +24 -0
- package/src/state/apply-snapshot.ts +8 -0
- package/src/state/store.ts +141 -0
- package/src/transport/reconnect.ts +83 -0
- package/src/transport/ws.ts +359 -0
- package/src/types.ts +54 -0
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useSignals } from "@preact/signals-react/runtime";
|
|
3
|
+
import { useLumencastRuntime } from "./runtime-context";
|
|
4
|
+
const PANEL_STYLE = {
|
|
5
|
+
position: "fixed",
|
|
6
|
+
bottom: 12,
|
|
7
|
+
left: 12,
|
|
8
|
+
zIndex: 100_000,
|
|
9
|
+
width: 320,
|
|
10
|
+
maxHeight: "70vh",
|
|
11
|
+
overflowY: "auto",
|
|
12
|
+
padding: 12,
|
|
13
|
+
fontFamily: "system-ui, -apple-system, BlinkMacSystemFont, sans-serif",
|
|
14
|
+
fontSize: 12,
|
|
15
|
+
color: "#e5e7eb",
|
|
16
|
+
background: "rgba(17, 24, 39, 0.92)",
|
|
17
|
+
border: "1px solid rgba(75, 85, 99, 0.6)",
|
|
18
|
+
borderRadius: 10,
|
|
19
|
+
boxShadow: "0 8px 32px rgba(0, 0, 0, 0.45)",
|
|
20
|
+
};
|
|
21
|
+
const ROW_STYLE = {
|
|
22
|
+
display: "flex",
|
|
23
|
+
flexDirection: "column",
|
|
24
|
+
gap: 4,
|
|
25
|
+
padding: "6px 0",
|
|
26
|
+
borderBottom: "1px solid rgba(75, 85, 99, 0.35)",
|
|
27
|
+
};
|
|
28
|
+
const LABEL_STYLE = {
|
|
29
|
+
color: "#9ca3af",
|
|
30
|
+
fontSize: 10.5,
|
|
31
|
+
letterSpacing: "0.02em",
|
|
32
|
+
textTransform: "uppercase",
|
|
33
|
+
};
|
|
34
|
+
const INPUT_STYLE = {
|
|
35
|
+
background: "rgba(31, 41, 55, 0.8)",
|
|
36
|
+
border: "1px solid rgba(75, 85, 99, 0.6)",
|
|
37
|
+
borderRadius: 6,
|
|
38
|
+
color: "#f9fafb",
|
|
39
|
+
padding: "4px 6px",
|
|
40
|
+
fontSize: 12,
|
|
41
|
+
width: "100%",
|
|
42
|
+
};
|
|
43
|
+
export function ControlPanel() {
|
|
44
|
+
const { bundle, store, sendInput } = useLumencastRuntime();
|
|
45
|
+
useSignals();
|
|
46
|
+
const inputs = bundle.operator_inputs ?? [];
|
|
47
|
+
if (inputs.length === 0)
|
|
48
|
+
return null;
|
|
49
|
+
// Group entries by `group` field for readability.
|
|
50
|
+
const groups = new Map();
|
|
51
|
+
for (const entry of inputs) {
|
|
52
|
+
const g = entry.group ?? "General";
|
|
53
|
+
const list = groups.get(g) ?? [];
|
|
54
|
+
list.push(entry);
|
|
55
|
+
groups.set(g, list);
|
|
56
|
+
}
|
|
57
|
+
return (_jsxs("div", { style: PANEL_STYLE, "data-testid": "lumencast-control-panel", children: [_jsx("div", { style: {
|
|
58
|
+
fontWeight: 600,
|
|
59
|
+
fontSize: 11,
|
|
60
|
+
letterSpacing: "0.06em",
|
|
61
|
+
color: "#9ca3af",
|
|
62
|
+
textTransform: "uppercase",
|
|
63
|
+
marginBottom: 6,
|
|
64
|
+
}, children: "Operator inputs" }), [...groups.entries()].map(([group, entries]) => (_jsxs("div", { style: { marginBottom: 8 }, children: [_jsx("div", { style: {
|
|
65
|
+
color: "#6b7280",
|
|
66
|
+
fontSize: 10,
|
|
67
|
+
letterSpacing: "0.04em",
|
|
68
|
+
textTransform: "uppercase",
|
|
69
|
+
padding: "4px 0",
|
|
70
|
+
}, children: group }), entries.map((entry) => (_jsx(InputRow, { entry: entry, currentValue: store.signal(entry.path).value, onCommit: (v) =>
|
|
71
|
+
// Operator-control values come from form widgets typed per
|
|
72
|
+
// OperatorInput.type; coerce to LeafValue at the boundary.
|
|
73
|
+
sendInput([
|
|
74
|
+
{
|
|
75
|
+
path: entry.path,
|
|
76
|
+
value: v,
|
|
77
|
+
},
|
|
78
|
+
]) }, entry.path)))] }, group)))] }));
|
|
79
|
+
}
|
|
80
|
+
function InputRow({ entry, currentValue, onCommit, }) {
|
|
81
|
+
return (_jsxs("div", { style: ROW_STYLE, children: [_jsx("span", { style: LABEL_STYLE, children: entry.label }), _jsx(Editor, { entry: entry, currentValue: currentValue, onCommit: onCommit })] }));
|
|
82
|
+
}
|
|
83
|
+
function Editor({ entry, currentValue, onCommit, }) {
|
|
84
|
+
switch (entry.type) {
|
|
85
|
+
case "boolean": {
|
|
86
|
+
const checked = currentValue === true;
|
|
87
|
+
return (_jsxs("label", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [_jsx("input", { type: "checkbox", checked: checked, onChange: (e) => onCommit(e.target.checked) }), _jsx("span", { style: { fontSize: 11, color: "#d1d5db" }, children: checked ? "on" : "off" })] }));
|
|
88
|
+
}
|
|
89
|
+
case "number": {
|
|
90
|
+
const min = entry.min;
|
|
91
|
+
const max = entry.max;
|
|
92
|
+
const step = entry.step;
|
|
93
|
+
return (_jsx("input", { type: "number", style: INPUT_STYLE, value: typeof currentValue === "number" ? currentValue : "", min: min, max: max, step: step, onChange: (e) => {
|
|
94
|
+
const n = Number(e.target.value);
|
|
95
|
+
if (Number.isFinite(n))
|
|
96
|
+
onCommit(n);
|
|
97
|
+
} }));
|
|
98
|
+
}
|
|
99
|
+
case "text": {
|
|
100
|
+
const max = entry.max_length;
|
|
101
|
+
return (_jsx("input", { type: "text", style: INPUT_STYLE, value: typeof currentValue === "string" ? currentValue : "", maxLength: max, onChange: (e) => onCommit(e.target.value) }));
|
|
102
|
+
}
|
|
103
|
+
case "colour": {
|
|
104
|
+
return (_jsx("input", { type: "color", style: INPUT_STYLE, value: typeof currentValue === "string" ? currentValue : "#000000", onChange: (e) => onCommit(e.target.value) }));
|
|
105
|
+
}
|
|
106
|
+
case "duration": {
|
|
107
|
+
return (_jsx("input", { type: "number", style: INPUT_STYLE, value: typeof currentValue === "number" ? currentValue : "", min: 0, step: 100, onChange: (e) => {
|
|
108
|
+
const n = Number(e.target.value);
|
|
109
|
+
if (Number.isFinite(n) && n >= 0)
|
|
110
|
+
onCommit(n);
|
|
111
|
+
} }));
|
|
112
|
+
}
|
|
113
|
+
case "select":
|
|
114
|
+
case "enum": {
|
|
115
|
+
const options = entry.enum_values ??
|
|
116
|
+
entry.options ??
|
|
117
|
+
[];
|
|
118
|
+
return (_jsx("select", { style: INPUT_STYLE, value: typeof currentValue === "string" ? currentValue : "", onChange: (e) => onCommit(e.target.value), children: options.map((opt) => (_jsx("option", { value: opt, children: opt }, opt))) }));
|
|
119
|
+
}
|
|
120
|
+
case "path-ref":
|
|
121
|
+
default:
|
|
122
|
+
// FIXME (v2) — `path-ref` UX is deferred ; for now show a plain
|
|
123
|
+
// text entry so the value is still editable.
|
|
124
|
+
return (_jsx("input", { type: "text", style: INPUT_STYLE, value: typeof currentValue === "string" ? currentValue : "", onChange: (e) => onCommit(e.target.value) }));
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=control.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"control.js","sourceRoot":"","sources":["../../src/overlay/control.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
import type { Patch } from "@lumencast/protocol";
|
|
3
|
+
import type { Store } from "../state/store";
|
|
4
|
+
import type { RenderBundle } from "../render/bundle";
|
|
5
|
+
import type { ConnectionStatus } from "../transport/ws";
|
|
6
|
+
import type { LumencastMode } from "../types";
|
|
7
|
+
export interface LumencastRuntime {
|
|
8
|
+
mode: LumencastMode;
|
|
9
|
+
store: Store;
|
|
10
|
+
bundle: RenderBundle;
|
|
11
|
+
status: ConnectionStatus;
|
|
12
|
+
/** Send LSDP/1 input patches to the server. */
|
|
13
|
+
sendInput: (patches: Patch[]) => void;
|
|
14
|
+
}
|
|
15
|
+
export declare function LumencastRuntimeProvider({ value, children, }: {
|
|
16
|
+
value: LumencastRuntime;
|
|
17
|
+
children: ReactNode;
|
|
18
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
19
|
+
export declare function useLumencastRuntime(): LumencastRuntime;
|
|
20
|
+
//# sourceMappingURL=runtime-context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-context.d.ts","sourceRoot":"","sources":["../../src/overlay/runtime-context.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA6B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAClE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAE9C,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,aAAa,CAAC;IACpB,KAAK,EAAE,KAAK,CAAC;IACb,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,EAAE,gBAAgB,CAAC;IACzB,+CAA+C;IAC/C,SAAS,EAAE,CAAC,OAAO,EAAE,KAAK,EAAE,KAAK,IAAI,CAAC;CACvC;AAID,wBAAgB,wBAAwB,CAAC,EACvC,KAAK,EACL,QAAQ,GACT,EAAE;IACD,KAAK,EAAE,gBAAgB,CAAC;IACxB,QAAQ,EAAE,SAAS,CAAC;CACrB,2CAEA;AAED,wBAAgB,mBAAmB,IAAI,gBAAgB,CAQtD"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { createContext, useContext } from "react";
|
|
3
|
+
const Ctx = createContext(null);
|
|
4
|
+
export function LumencastRuntimeProvider({ value, children, }) {
|
|
5
|
+
return _jsx(Ctx.Provider, { value: value, children: children });
|
|
6
|
+
}
|
|
7
|
+
export function useLumencastRuntime() {
|
|
8
|
+
const v = useContext(Ctx);
|
|
9
|
+
if (!v) {
|
|
10
|
+
throw new Error("Lumencast overlay components must be rendered inside LumencastRuntimeProvider");
|
|
11
|
+
}
|
|
12
|
+
return v;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=runtime-context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-context.js","sourceRoot":"","sources":["../../src/overlay/runtime-context.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAkB,MAAM,OAAO,CAAC;AAgBlE,MAAM,GAAG,GAAG,aAAa,CAA0B,IAAI,CAAC,CAAC;AAEzD,MAAM,UAAU,wBAAwB,CAAC,EACvC,KAAK,EACL,QAAQ,GAIT;IACC,OAAO,KAAC,GAAG,CAAC,QAAQ,IAAC,KAAK,EAAE,KAAK,YAAG,QAAQ,GAAgB,CAAC;AAC/D,CAAC;AAED,MAAM,UAAU,mBAAmB;IACjC,MAAM,CAAC,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;IAC1B,IAAI,CAAC,CAAC,EAAE,CAAC;QACP,MAAM,IAAI,KAAK,CACb,+EAA+E,CAChF,CAAC;IACJ,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status-pill.d.ts","sourceRoot":"","sources":["../../src/overlay/status-pill.tsx"],"names":[],"mappings":"AAcA,wBAAgB,UAAU,4CAsBzB"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useLumencastRuntime } from "./runtime-context";
|
|
3
|
+
const COLOURS = {
|
|
4
|
+
live: "rgba(34, 197, 94, 0.85)",
|
|
5
|
+
connecting: "rgba(234, 179, 8, 0.85)",
|
|
6
|
+
disconnected: "rgba(239, 68, 68, 0.85)",
|
|
7
|
+
};
|
|
8
|
+
const LABELS = {
|
|
9
|
+
live: "live",
|
|
10
|
+
connecting: "reconnecting",
|
|
11
|
+
disconnected: "disconnected",
|
|
12
|
+
};
|
|
13
|
+
export function StatusPill() {
|
|
14
|
+
const { status } = useLumencastRuntime();
|
|
15
|
+
return (_jsx("div", { "data-testid": "lumencast-status-pill", style: {
|
|
16
|
+
position: "fixed",
|
|
17
|
+
top: 12,
|
|
18
|
+
right: 12,
|
|
19
|
+
padding: "4px 10px",
|
|
20
|
+
fontSize: 11,
|
|
21
|
+
fontFamily: "system-ui, -apple-system, BlinkMacSystemFont, sans-serif",
|
|
22
|
+
color: "white",
|
|
23
|
+
background: COLOURS[status] ?? "#444",
|
|
24
|
+
borderRadius: 999,
|
|
25
|
+
userSelect: "none",
|
|
26
|
+
pointerEvents: "none",
|
|
27
|
+
}, children: LABELS[status] ?? status }));
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=status-pill.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status-pill.js","sourceRoot":"","sources":["../../src/overlay/status-pill.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAExD,MAAM,OAAO,GAA2B;IACtC,IAAI,EAAE,yBAAyB;IAC/B,UAAU,EAAE,yBAAyB;IACrC,YAAY,EAAE,yBAAyB;CACxC,CAAC;AAEF,MAAM,MAAM,GAA2B;IACrC,IAAI,EAAE,MAAM;IACZ,UAAU,EAAE,cAAc;IAC1B,YAAY,EAAE,cAAc;CAC7B,CAAC;AAEF,MAAM,UAAU,UAAU;IACxB,MAAM,EAAE,MAAM,EAAE,GAAG,mBAAmB,EAAE,CAAC;IACzC,OAAO,CACL,6BACc,uBAAuB,EACnC,KAAK,EAAE;YACL,QAAQ,EAAE,OAAO;YACjB,GAAG,EAAE,EAAE;YACP,KAAK,EAAE,EAAE;YACT,OAAO,EAAE,UAAU;YACnB,QAAQ,EAAE,EAAE;YACZ,UAAU,EAAE,0DAA0D;YACtE,KAAK,EAAE,OAAO;YACd,UAAU,EAAE,OAAO,CAAC,MAAM,CAAC,IAAI,MAAM;YACrC,YAAY,EAAE,GAAG;YACjB,UAAU,EAAE,MAAM;YAClB,aAAa,EAAE,MAAM;SACtB,YAEA,MAAM,CAAC,MAAM,CAAC,IAAI,MAAM,GACrB,CACP,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test.d.ts","sourceRoot":"","sources":["../../src/overlay/test.tsx"],"names":[],"mappings":"AAiDA;;eAEe;AACf,wBAAgB,SAAS,4CAmGxB"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useSignals } from "@preact/signals-react/runtime";
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
import { useLumencastRuntime } from "./runtime-context";
|
|
5
|
+
const PANEL_STYLE = {
|
|
6
|
+
position: "fixed",
|
|
7
|
+
bottom: 12,
|
|
8
|
+
right: 12,
|
|
9
|
+
zIndex: 100_001,
|
|
10
|
+
width: 360,
|
|
11
|
+
maxHeight: "70vh",
|
|
12
|
+
overflowY: "auto",
|
|
13
|
+
padding: 12,
|
|
14
|
+
fontFamily: "system-ui, -apple-system, BlinkMacSystemFont, sans-serif",
|
|
15
|
+
fontSize: 12,
|
|
16
|
+
color: "#e5e7eb",
|
|
17
|
+
background: "rgba(8, 47, 73, 0.92)",
|
|
18
|
+
border: "1px solid rgba(56, 189, 248, 0.4)",
|
|
19
|
+
borderRadius: 10,
|
|
20
|
+
boxShadow: "0 8px 32px rgba(0, 0, 0, 0.45)",
|
|
21
|
+
};
|
|
22
|
+
const SECTION_TITLE = {
|
|
23
|
+
fontWeight: 600,
|
|
24
|
+
fontSize: 11,
|
|
25
|
+
letterSpacing: "0.06em",
|
|
26
|
+
color: "#7dd3fc",
|
|
27
|
+
textTransform: "uppercase",
|
|
28
|
+
marginBottom: 6,
|
|
29
|
+
};
|
|
30
|
+
const BUTTON_STYLE = {
|
|
31
|
+
background: "rgba(14, 165, 233, 0.4)",
|
|
32
|
+
border: "1px solid rgba(125, 211, 252, 0.5)",
|
|
33
|
+
borderRadius: 6,
|
|
34
|
+
color: "#f0f9ff",
|
|
35
|
+
padding: "3px 8px",
|
|
36
|
+
fontSize: 11,
|
|
37
|
+
cursor: "pointer",
|
|
38
|
+
};
|
|
39
|
+
const ADAPTER_ROW = {
|
|
40
|
+
display: "flex",
|
|
41
|
+
flexDirection: "column",
|
|
42
|
+
gap: 4,
|
|
43
|
+
padding: "6px 0",
|
|
44
|
+
borderBottom: "1px solid rgba(56, 189, 248, 0.2)",
|
|
45
|
+
};
|
|
46
|
+
/** Test-mode overlay : adapter mocker + state inspector + time
|
|
47
|
+
* controls. Drives the server's __test.* family via the same `sendInput`
|
|
48
|
+
* channel. */
|
|
49
|
+
export function TestPanel() {
|
|
50
|
+
const { bundle, store, sendInput } = useLumencastRuntime();
|
|
51
|
+
useSignals();
|
|
52
|
+
const [filter, setFilter] = useState("");
|
|
53
|
+
const adapters = bundle.external_adapters ?? [];
|
|
54
|
+
const stateRecord = store.toRecord();
|
|
55
|
+
const filteredEntries = Object.entries(stateRecord).filter(([k]) => filter === "" || k.includes(filter));
|
|
56
|
+
return (_jsxs("div", { style: PANEL_STYLE, "data-testid": "lumencast-test-panel", children: [_jsx("div", { style: SECTION_TITLE, children: "Time" }), _jsxs("div", { style: { display: "flex", gap: 6, marginBottom: 8 }, children: [_jsx("button", { type: "button", style: BUTTON_STYLE, onClick: () => sendInput([{ path: "__test.tick", value: 100 }]), children: "tick +100ms" }), _jsx("button", { type: "button", style: BUTTON_STYLE, onClick: () => sendInput([{ path: "__test.tick", value: 1_000 }]), children: "tick +1s" }), _jsx("button", { type: "button", style: BUTTON_STYLE, onClick: () => sendInput([{ path: "__test.reset", value: true }]), children: "reset" })] }), _jsx("div", { style: SECTION_TITLE, children: "External adapters" }), adapters.length === 0 && (_jsx("div", { style: { color: "#94a3b8", fontStyle: "italic", fontSize: 11 }, children: "No external adapters declared in this scene." })), adapters.map((adapter) => (_jsx(AdapterRow, { adapter: adapter, onMock: (payload) =>
|
|
57
|
+
// LSDP/1 patch values must be leaf — JSON-encode the structured payload.
|
|
58
|
+
sendInput([
|
|
59
|
+
{
|
|
60
|
+
path: "__test.mock_adapter",
|
|
61
|
+
value: JSON.stringify({ key: adapter.key, payload }),
|
|
62
|
+
},
|
|
63
|
+
]) }, adapter.key))), _jsx("div", { style: { ...SECTION_TITLE, marginTop: 12 }, children: "State" }), _jsx("input", { type: "text", placeholder: "filter paths\u2026", value: filter, onChange: (e) => setFilter(e.target.value), style: {
|
|
64
|
+
background: "rgba(8, 47, 73, 0.6)",
|
|
65
|
+
border: "1px solid rgba(125, 211, 252, 0.4)",
|
|
66
|
+
borderRadius: 6,
|
|
67
|
+
color: "#e0f2fe",
|
|
68
|
+
padding: "4px 6px",
|
|
69
|
+
fontSize: 11,
|
|
70
|
+
width: "100%",
|
|
71
|
+
marginBottom: 6,
|
|
72
|
+
} }), _jsx("div", { style: { fontFamily: "monospace", fontSize: 10.5 }, children: filteredEntries.map(([path, value]) => (_jsxs("div", { style: {
|
|
73
|
+
display: "grid",
|
|
74
|
+
gridTemplateColumns: "1fr auto",
|
|
75
|
+
gap: 8,
|
|
76
|
+
padding: "2px 0",
|
|
77
|
+
borderBottom: "1px dashed rgba(125, 211, 252, 0.15)",
|
|
78
|
+
}, children: [_jsx("span", { style: { color: "#bae6fd" }, children: path }), _jsx("span", { style: { color: "#fef3c7" }, children: formatValue(value) })] }, path))) })] }));
|
|
79
|
+
}
|
|
80
|
+
function AdapterRow({ adapter, onMock, }) {
|
|
81
|
+
const [draft, setDraft] = useState("{}");
|
|
82
|
+
return (_jsxs("div", { style: ADAPTER_ROW, children: [_jsxs("div", { style: {
|
|
83
|
+
display: "flex",
|
|
84
|
+
justifyContent: "space-between",
|
|
85
|
+
alignItems: "center",
|
|
86
|
+
}, children: [_jsx("span", { style: { color: "#e0f2fe" }, children: adapter.label }), _jsx("span", { style: { color: "#94a3b8", fontSize: 10 }, children: adapter.kind })] }), _jsx("textarea", { value: draft, onChange: (e) => setDraft(e.target.value), rows: 2, style: {
|
|
87
|
+
fontFamily: "monospace",
|
|
88
|
+
fontSize: 10.5,
|
|
89
|
+
background: "rgba(8, 47, 73, 0.6)",
|
|
90
|
+
color: "#e0f2fe",
|
|
91
|
+
border: "1px solid rgba(125, 211, 252, 0.3)",
|
|
92
|
+
borderRadius: 4,
|
|
93
|
+
padding: 4,
|
|
94
|
+
resize: "vertical",
|
|
95
|
+
} }), _jsx("button", { type: "button", style: BUTTON_STYLE, onClick: () => {
|
|
96
|
+
try {
|
|
97
|
+
const parsed = JSON.parse(draft);
|
|
98
|
+
onMock(parsed);
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
onMock(draft);
|
|
102
|
+
}
|
|
103
|
+
}, children: "fire" })] }));
|
|
104
|
+
}
|
|
105
|
+
function formatValue(value) {
|
|
106
|
+
if (value === undefined)
|
|
107
|
+
return "—";
|
|
108
|
+
if (value === null)
|
|
109
|
+
return "null";
|
|
110
|
+
if (typeof value === "string")
|
|
111
|
+
return JSON.stringify(value);
|
|
112
|
+
if (typeof value === "object")
|
|
113
|
+
return JSON.stringify(value);
|
|
114
|
+
return String(value);
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test.js","sourceRoot":"","sources":["../../src/overlay/test.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import type { Transition } from "../animate/transitions.js";
|
|
2
|
+
import type { Keyframes } from "../animate/keyframes.js";
|
|
3
|
+
export type RenderKind = "stack" | "grid" | "frame" | "text" | "image" | "shape" | "media" | "repeat" | "instance";
|
|
4
|
+
export interface RenderNode {
|
|
5
|
+
kind: RenderKind;
|
|
6
|
+
/** Stable identifier for keyed reconciliation. */
|
|
7
|
+
id?: string;
|
|
8
|
+
/** Static props (frozen at build/compile time). */
|
|
9
|
+
props?: Record<string, unknown>;
|
|
10
|
+
/** Prop name → state path. The render layer subscribes the path's signal
|
|
11
|
+
* and applies the value to the named prop on each change. */
|
|
12
|
+
bindings?: Record<string, string>;
|
|
13
|
+
/** Default transition per bound prop. Aligns with LSML 1.0 §6 `animate`
|
|
14
|
+
* directives. The runtime applies these as CSS transitions / Framer Motion
|
|
15
|
+
* configs at render time. */
|
|
16
|
+
transitions?: Record<string, Transition>;
|
|
17
|
+
/** LSML 1.1 §6.6 — multi-step keyframe sequence played on mount or
|
|
18
|
+
* whenever `keyframes.key` (LeafPath) changes. Coexists with
|
|
19
|
+
* `transitions` ; the runtime applies whichever was last triggered
|
|
20
|
+
* (no blending — see §6.6 last paragraph). */
|
|
21
|
+
keyframes?: Keyframes;
|
|
22
|
+
/** LSML 1.1 §6.7 — only meaningful on `repeat`. Each iteration's
|
|
23
|
+
* animations start `index * stagger_ms` after iteration 0. */
|
|
24
|
+
stagger_ms?: number;
|
|
25
|
+
/** Children — already-inlined primitives only. */
|
|
26
|
+
children?: RenderNode[];
|
|
27
|
+
}
|
|
28
|
+
export type OperatorInputType = "boolean" | "number" | "text" | "select" | "enum" | "path-ref" | "colour" | "duration";
|
|
29
|
+
export interface OperatorInput {
|
|
30
|
+
path: string;
|
|
31
|
+
label: string;
|
|
32
|
+
type: OperatorInputType;
|
|
33
|
+
default?: unknown;
|
|
34
|
+
group?: string;
|
|
35
|
+
writable_by?: string[];
|
|
36
|
+
[extra: string]: unknown;
|
|
37
|
+
}
|
|
38
|
+
export interface ExternalAdapter {
|
|
39
|
+
key: string;
|
|
40
|
+
label: string;
|
|
41
|
+
kind: string;
|
|
42
|
+
target_paths: string[];
|
|
43
|
+
[extra: string]: unknown;
|
|
44
|
+
}
|
|
45
|
+
export interface Asset {
|
|
46
|
+
id: string;
|
|
47
|
+
url: string;
|
|
48
|
+
kind: string;
|
|
49
|
+
[extra: string]: unknown;
|
|
50
|
+
}
|
|
51
|
+
export interface RenderBundle {
|
|
52
|
+
scene_version: string;
|
|
53
|
+
root: RenderNode;
|
|
54
|
+
operator_inputs?: OperatorInput[];
|
|
55
|
+
external_adapters?: ExternalAdapter[];
|
|
56
|
+
assets?: Asset[];
|
|
57
|
+
/** LSML 1.1 §17.3 — capability profiles required for correct rendering.
|
|
58
|
+
* Each entry is a `<vendor>.<name>-<version>` string. The runtime
|
|
59
|
+
* checks every entry against its supported list ; an unrecognised
|
|
60
|
+
* profile raises BUNDLE_INCOMPATIBLE per §17.3.1. */
|
|
61
|
+
profiles?: string[];
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Profiles the JS runtime advertises support for. Bundle authors who
|
|
65
|
+
* declare `profiles: [...]` get a hard `BUNDLE_INCOMPATIBLE` rejection
|
|
66
|
+
* when any entry is not in this set (LSML 1.1 §17.3.1).
|
|
67
|
+
*
|
|
68
|
+
* 1.1 ships with no standard profiles ; future minors / vendor specs
|
|
69
|
+
* register here. The `x-lumencast.color-srgb-1.0` entry is the
|
|
70
|
+
* default-color-space marker ; bundles that opt into a perceptual
|
|
71
|
+
* space (OKLCH) would request a different profile and currently
|
|
72
|
+
* reject.
|
|
73
|
+
*/
|
|
74
|
+
export declare const SUPPORTED_PROFILES: ReadonlySet<string>;
|
|
75
|
+
export declare class BundleIncompatibleError extends Error {
|
|
76
|
+
readonly code: "BUNDLE_INCOMPATIBLE";
|
|
77
|
+
readonly unsupportedProfiles: string[];
|
|
78
|
+
constructor(unsupportedProfiles: string[]);
|
|
79
|
+
}
|
|
80
|
+
/** Validate a bundle's `profiles[]` against the runtime's supported
|
|
81
|
+
* set. Throws `BundleIncompatibleError` listing every offending entry
|
|
82
|
+
* when at least one is not supported. */
|
|
83
|
+
export declare function validateBundleProfiles(bundle: {
|
|
84
|
+
profiles?: string[];
|
|
85
|
+
}, supported?: ReadonlySet<string>): void;
|
|
86
|
+
export interface BundleFetcher {
|
|
87
|
+
/** Fetch the bundle for a scene version. Cached forever by hash. */
|
|
88
|
+
get(sceneId: string, sceneVersion: string): Promise<RenderBundle>;
|
|
89
|
+
/** Inject a bundle directly — used by tests and for the "scene already in
|
|
90
|
+
* flight" handoff path. */
|
|
91
|
+
preload(bundle: RenderBundle): void;
|
|
92
|
+
}
|
|
93
|
+
export interface BundleFetcherOptions {
|
|
94
|
+
/** Base URL of the server. The fetcher constructs
|
|
95
|
+
* `${baseUrl}/lsdp/v1/scenes/{id}/bundle?v={hash}`. */
|
|
96
|
+
baseUrl: string;
|
|
97
|
+
/** Path prefix for bundle resolution. Defaults to `/lsdp/v1/scenes`. */
|
|
98
|
+
pathPrefix?: string;
|
|
99
|
+
fetchImpl?: typeof fetch;
|
|
100
|
+
}
|
|
101
|
+
export declare function createBundleFetcher(opts: BundleFetcherOptions): BundleFetcher;
|
|
102
|
+
//# sourceMappingURL=bundle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bundle.d.ts","sourceRoot":"","sources":["../../src/render/bundle.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
// Render bundle — the runtime's flat, pre-compiled representation of a scene.
|
|
2
|
+
//
|
|
3
|
+
// The bundle is content-addressed by `scene_version` (sha256 of the
|
|
4
|
+
// canonical JSON form). Lumencast fetches it once per `scene_version` and
|
|
5
|
+
// caches forever; the server serves it with long-TTL immutable cache headers.
|
|
6
|
+
//
|
|
7
|
+
// Note on shape: this `RenderBundle` is the flat, runtime-internal form. The
|
|
8
|
+
// canonical *authoring* format (LSML 1.0, see lumencast-protocol/spec/LSML-1.md)
|
|
9
|
+
// uses inline `bind: { value: "path" }` per primitive instead of a `bindings`
|
|
10
|
+
// map. A compiler step (forthcoming `@lumencast/compiler`) will translate
|
|
11
|
+
// LSML 1.0 → RenderBundle. For now, callers who want to feed an LSML 1.0
|
|
12
|
+
// bundle pre-compile or use a hand-rolled adapter.
|
|
13
|
+
/**
|
|
14
|
+
* Profiles the JS runtime advertises support for. Bundle authors who
|
|
15
|
+
* declare `profiles: [...]` get a hard `BUNDLE_INCOMPATIBLE` rejection
|
|
16
|
+
* when any entry is not in this set (LSML 1.1 §17.3.1).
|
|
17
|
+
*
|
|
18
|
+
* 1.1 ships with no standard profiles ; future minors / vendor specs
|
|
19
|
+
* register here. The `x-lumencast.color-srgb-1.0` entry is the
|
|
20
|
+
* default-color-space marker ; bundles that opt into a perceptual
|
|
21
|
+
* space (OKLCH) would request a different profile and currently
|
|
22
|
+
* reject.
|
|
23
|
+
*/
|
|
24
|
+
export const SUPPORTED_PROFILES = new Set([
|
|
25
|
+
"x-lumencast.color-srgb-1.0",
|
|
26
|
+
]);
|
|
27
|
+
export class BundleIncompatibleError extends Error {
|
|
28
|
+
code = "BUNDLE_INCOMPATIBLE";
|
|
29
|
+
unsupportedProfiles;
|
|
30
|
+
constructor(unsupportedProfiles) {
|
|
31
|
+
super(`BUNDLE_INCOMPATIBLE: profile(s) not supported by this runtime: ${unsupportedProfiles.join(", ")}`);
|
|
32
|
+
this.name = "BundleIncompatibleError";
|
|
33
|
+
this.unsupportedProfiles = unsupportedProfiles;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/** Validate a bundle's `profiles[]` against the runtime's supported
|
|
37
|
+
* set. Throws `BundleIncompatibleError` listing every offending entry
|
|
38
|
+
* when at least one is not supported. */
|
|
39
|
+
export function validateBundleProfiles(bundle, supported = SUPPORTED_PROFILES) {
|
|
40
|
+
const profiles = bundle.profiles;
|
|
41
|
+
if (!profiles || profiles.length === 0)
|
|
42
|
+
return;
|
|
43
|
+
const missing = profiles.filter((p) => !supported.has(p));
|
|
44
|
+
if (missing.length > 0) {
|
|
45
|
+
throw new BundleIncompatibleError(missing);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
class FetcherImpl {
|
|
49
|
+
cache = new Map();
|
|
50
|
+
baseUrl;
|
|
51
|
+
pathPrefix;
|
|
52
|
+
fetchImpl;
|
|
53
|
+
constructor(opts) {
|
|
54
|
+
this.baseUrl = opts.baseUrl.replace(/\/$/, "");
|
|
55
|
+
this.pathPrefix = (opts.pathPrefix ?? "/lsdp/v1/scenes").replace(/\/$/, "");
|
|
56
|
+
this.fetchImpl = opts.fetchImpl ?? globalThis.fetch.bind(globalThis);
|
|
57
|
+
}
|
|
58
|
+
preload(bundle) {
|
|
59
|
+
// LSML 1.1 §17.3.1 — reject early if any declared profile is
|
|
60
|
+
// unsupported by this runtime. Authors get an actionable error
|
|
61
|
+
// instead of a silent rendering glitch.
|
|
62
|
+
validateBundleProfiles(bundle);
|
|
63
|
+
this.cache.set(bundle.scene_version, bundle);
|
|
64
|
+
}
|
|
65
|
+
async get(sceneId, sceneVersion) {
|
|
66
|
+
const cached = this.cache.get(sceneVersion);
|
|
67
|
+
if (cached)
|
|
68
|
+
return cached;
|
|
69
|
+
const url = `${this.baseUrl}${this.pathPrefix}/${encodeURIComponent(sceneId)}/bundle?v=${encodeURIComponent(sceneVersion)}`;
|
|
70
|
+
const response = await this.fetchImpl(url);
|
|
71
|
+
if (!response.ok) {
|
|
72
|
+
throw new Error(`bundle fetch failed: ${response.status} ${response.statusText}`);
|
|
73
|
+
}
|
|
74
|
+
const json = (await response.json());
|
|
75
|
+
if (json.scene_version !== sceneVersion) {
|
|
76
|
+
throw new Error(`bundle scene_version mismatch: expected ${sceneVersion}, got ${json.scene_version}`);
|
|
77
|
+
}
|
|
78
|
+
validateBundleProfiles(json);
|
|
79
|
+
this.cache.set(sceneVersion, json);
|
|
80
|
+
return json;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
export function createBundleFetcher(opts) {
|
|
84
|
+
return new FetcherImpl(opts);
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=bundle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bundle.js","sourceRoot":"","sources":["../../src/render/bundle.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { CSSProperties, ReactElement } from "react";
|
|
2
|
+
export interface FillStop {
|
|
3
|
+
offset: number;
|
|
4
|
+
color: string;
|
|
5
|
+
opacity?: number;
|
|
6
|
+
}
|
|
7
|
+
export type Fill = {
|
|
8
|
+
kind: "solid";
|
|
9
|
+
color: string;
|
|
10
|
+
opacity?: number;
|
|
11
|
+
} | {
|
|
12
|
+
kind: "linear-gradient";
|
|
13
|
+
angle_deg?: number;
|
|
14
|
+
stops: FillStop[];
|
|
15
|
+
opacity?: number;
|
|
16
|
+
} | {
|
|
17
|
+
kind: "radial-gradient";
|
|
18
|
+
center?: {
|
|
19
|
+
x: number;
|
|
20
|
+
y: number;
|
|
21
|
+
};
|
|
22
|
+
radius?: number;
|
|
23
|
+
stops: FillStop[];
|
|
24
|
+
opacity?: number;
|
|
25
|
+
};
|
|
26
|
+
export interface FillRenderResult {
|
|
27
|
+
/** SVG <defs> contributions (gradient definitions). */
|
|
28
|
+
defs: ReactElement[];
|
|
29
|
+
/** Reference to use as the `fill` attribute on the shape. */
|
|
30
|
+
ref: string;
|
|
31
|
+
}
|
|
32
|
+
/** Compile a Fill into an SVG `<defs>` entry + a `fill="url(#…)"` ref.
|
|
33
|
+
* Solid fills produce no defs and return the colour directly. */
|
|
34
|
+
export declare function renderFill(fill: Fill): FillRenderResult;
|
|
35
|
+
/** Compile an array of Fill into a CSS `background-image` value usable
|
|
36
|
+
* on a `<div>` (frame backgrounds — non-SVG context). Returns the CSS
|
|
37
|
+
* string + opacity. Stops use percentages in CSS gradient syntax. */
|
|
38
|
+
export declare function backgroundsToCss(fills: Fill[]): CSSProperties;
|
|
39
|
+
/** Coerce loose JSON into a Fill array. Returns [] for non-arrays. */
|
|
40
|
+
export declare function parseFills(value: unknown): Fill[];
|
|
41
|
+
//# sourceMappingURL=fill.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fill.d.ts","sourceRoot":"","sources":["../../src/render/fill.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAEzD,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,MAAM,IAAI,GACZ;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAClD;IACE,IAAI,EAAE,iBAAiB,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,GACD;IACE,IAAI,EAAE,iBAAiB,CAAC;IACxB,MAAM,CAAC,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAClC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAQN,MAAM,WAAW,gBAAgB;IAC/B,uDAAuD;IACvD,IAAI,EAAE,YAAY,EAAE,CAAC;IACrB,6DAA6D;IAC7D,GAAG,EAAE,MAAM,CAAC;CACb;AAED;iEACiE;AACjE,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,gBAAgB,CAuDvD;AAED;;qEAEqE;AACrE,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,aAAa,CAM7D;AAoCD,sEAAsE;AACtE,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,EAAE,CAGjD"}
|