@lumencast/runtime 0.5.0 → 0.7.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/dist/.tsbuildinfo +1 -1
- package/dist/broadcast-DUYqvcgo.js +12 -0
- package/dist/broadcast-DUYqvcgo.js.map +1 -0
- package/dist/control-CL8TWXaE.js +17 -0
- package/dist/control-CL8TWXaE.js.map +1 -0
- package/dist/{index-CyOlpZAL.js → index-C6viWFcT.js} +216 -182
- package/dist/index-C6viWFcT.js.map +1 -0
- package/dist/index.html +1 -1
- package/dist/lumencast.js +1 -1
- package/dist/modes/broadcast.d.ts.map +1 -1
- package/dist/modes/broadcast.js +6 -1
- package/dist/modes/broadcast.js.map +1 -1
- package/dist/modes/control.d.ts.map +1 -1
- package/dist/modes/control.js +6 -1
- package/dist/modes/control.js.map +1 -1
- package/dist/modes/test.d.ts.map +1 -1
- package/dist/modes/test.js +2 -1
- package/dist/modes/test.js.map +1 -1
- package/dist/mount.d.ts.map +1 -1
- package/dist/mount.js +5 -0
- package/dist/mount.js.map +1 -1
- package/dist/render/allowed-hosts.d.ts +41 -0
- package/dist/render/allowed-hosts.d.ts.map +1 -0
- package/dist/render/allowed-hosts.js +88 -0
- package/dist/render/allowed-hosts.js.map +1 -0
- package/dist/render/blend-mode.d.ts +7 -0
- package/dist/render/blend-mode.d.ts.map +1 -0
- package/dist/render/blend-mode.js +49 -0
- package/dist/render/blend-mode.js.map +1 -0
- package/dist/render/bundle.d.ts +17 -1
- package/dist/render/bundle.d.ts.map +1 -1
- package/dist/render/bundle.js +15 -1
- package/dist/render/bundle.js.map +1 -1
- package/dist/render/fill.d.ts +36 -3
- package/dist/render/fill.d.ts.map +1 -1
- package/dist/render/fill.js +222 -23
- package/dist/render/fill.js.map +1 -1
- package/dist/render/mask.d.ts +87 -0
- package/dist/render/mask.d.ts.map +1 -0
- package/dist/render/mask.js +243 -0
- package/dist/render/mask.js.map +1 -0
- package/dist/render/primitives/frame.d.ts.map +1 -1
- package/dist/render/primitives/frame.js +91 -5
- package/dist/render/primitives/frame.js.map +1 -1
- package/dist/render/primitives/grid.d.ts +1 -1
- package/dist/render/primitives/grid.d.ts.map +1 -1
- package/dist/render/primitives/grid.js +4 -1
- package/dist/render/primitives/grid.js.map +1 -1
- package/dist/render/primitives/image.d.ts +8 -1
- package/dist/render/primitives/image.d.ts.map +1 -1
- package/dist/render/primitives/image.js +17 -3
- package/dist/render/primitives/image.js.map +1 -1
- package/dist/render/primitives/index.d.ts +7 -0
- package/dist/render/primitives/index.d.ts.map +1 -1
- package/dist/render/primitives/index.js.map +1 -1
- package/dist/render/primitives/shape.d.ts.map +1 -1
- package/dist/render/primitives/shape.js +29 -26
- package/dist/render/primitives/shape.js.map +1 -1
- package/dist/render/primitives/stack.d.ts +1 -1
- package/dist/render/primitives/stack.d.ts.map +1 -1
- package/dist/render/primitives/stack.js +5 -1
- package/dist/render/primitives/stack.js.map +1 -1
- package/dist/render/primitives/text.d.ts.map +1 -1
- package/dist/render/primitives/text.js +0 -1
- package/dist/render/primitives/text.js.map +1 -1
- package/dist/render/prop-allowlist.d.ts.map +1 -1
- package/dist/render/prop-allowlist.js +25 -2
- package/dist/render/prop-allowlist.js.map +1 -1
- package/dist/render/shape-geometry.d.ts +81 -0
- package/dist/render/shape-geometry.d.ts.map +1 -0
- package/dist/render/shape-geometry.js +199 -0
- package/dist/render/shape-geometry.js.map +1 -0
- package/dist/render/shape-index.d.ts +28 -0
- package/dist/render/shape-index.d.ts.map +1 -0
- package/dist/render/shape-index.js +77 -0
- package/dist/render/shape-index.js.map +1 -0
- package/dist/render/tree.d.ts.map +1 -1
- package/dist/render/tree.js +175 -3
- package/dist/render/tree.js.map +1 -1
- package/dist/render/universal-wrapper.d.ts +27 -1
- package/dist/render/universal-wrapper.d.ts.map +1 -1
- package/dist/render/universal-wrapper.js +98 -22
- package/dist/render/universal-wrapper.js.map +1 -1
- package/dist/{status-pill-DIpXc5du.js → status-pill-jJT54n07.js} +2 -2
- package/dist/{status-pill-DIpXc5du.js.map → status-pill-jJT54n07.js.map} +1 -1
- package/dist/{test-ByRec1kd.js → test-84XodL1c.js} +51 -51
- package/dist/{test-ByRec1kd.js.map → test-84XodL1c.js.map} +1 -1
- package/dist/transport/ws.d.ts +5 -0
- package/dist/transport/ws.d.ts.map +1 -1
- package/dist/transport/ws.js +7 -0
- package/dist/transport/ws.js.map +1 -1
- package/dist/tree-BIimahCf.js +1777 -0
- package/dist/tree-BIimahCf.js.map +1 -0
- package/package.json +4 -4
- package/src/modes/broadcast.tsx +12 -1
- package/src/modes/control.tsx +10 -1
- package/src/modes/test.tsx +4 -1
- package/src/mount.ts +5 -0
- package/src/render/allowed-hosts.tsx +100 -0
- package/src/render/blend-mode.ts +50 -0
- package/src/render/bundle.ts +28 -2
- package/src/render/fill.tsx +266 -24
- package/src/render/mask.tsx +389 -0
- package/src/render/primitives/frame.tsx +101 -5
- package/src/render/primitives/grid.tsx +4 -1
- package/src/render/primitives/image.tsx +17 -3
- package/src/render/primitives/index.ts +7 -0
- package/src/render/primitives/shape.tsx +39 -75
- package/src/render/primitives/stack.tsx +5 -1
- package/src/render/primitives/text.tsx +0 -1
- package/src/render/prop-allowlist.ts +25 -2
- package/src/render/shape-geometry.tsx +315 -0
- package/src/render/shape-index.tsx +90 -0
- package/src/render/tree.tsx +214 -12
- package/src/render/universal-wrapper.tsx +128 -21
- package/src/transport/ws.ts +8 -0
- package/dist/broadcast-3vYij4k-.js +0 -11
- package/dist/broadcast-3vYij4k-.js.map +0 -1
- package/dist/control-BFNkY7-6.js +0 -16
- package/dist/control-BFNkY7-6.js.map +0 -1
- package/dist/index-CyOlpZAL.js.map +0 -1
- package/dist/tree-D5wYHpPu.js +0 -1230
- package/dist/tree-D5wYHpPu.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mask.d.ts","sourceRoot":"","sources":["../../src/render/mask.tsx"],"names":[],"mappings":"AA6BA,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAIzD;;;;kEAIkE;AAClE,MAAM,MAAM,gBAAgB,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,YAAY,GAAG,IAAI,CAAC;AAOpE;;;;;0EAK0E;AAC1E,eAAO,MAAM,gBAAgB,MAAM,CAAC;AAKpC;;4EAE4E;AAC5E,MAAM,MAAM,UAAU,GAClB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,GACxF;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnC;0EAC0E;AAC1E,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,UAAU,CAAC;IACnB,IAAI,EAAE,OAAO,GAAG,WAAW,CAAC;IAC5B,EAAE,EAAE,WAAW,GAAG,UAAU,GAAG,OAAO,CAAC;IACvC,QAAQ,CAAC,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACpC,IAAI,CAAC,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACjC;AAED,gEAAgE;AAChE,MAAM,WAAW,SAAS;IACxB,2EAA2E;IAC3E,GAAG,EAAE,YAAY,CAAC;IAClB,sEAAsE;IACtE,KAAK,EAAE,aAAa,CAAC;IACrB,wEAAwE;IACxE,EAAE,EAAE,MAAM,CAAC;IACX;;;+EAG2E;IAC3E,OAAO,EAAE,OAAO,CAAC;CAClB;AAoBD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,QAAQ,GAAG,IAAI,CAuDzF;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,SAAS,CACvB,IAAI,EAAE,QAAQ,EACd,YAAY,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,EAC3C,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,YAAY,CAAC,EAAE,gBAAgB,EAC/B,OAAO,CAAC,EAAE;IAAE,CAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,CAAC,EAAE,MAAM,CAAA;CAAE,EACpC,OAAO,UAAQ,GACd,SAAS,GAAG,IAAI,CAsMlB"}
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { checkHostAllowed } from "@lumencast/protocol";
|
|
3
|
+
import { emitDiagnostic } from "./diagnostics";
|
|
4
|
+
/** Closed `mask.type` allowlist — runtime half of the double-gate (T4).
|
|
5
|
+
* Mirrors `@lumencast/compiler` `MASK_TYPES` ; kept local so the runtime
|
|
6
|
+
* has no compile-time dependency on the compiler package. */
|
|
7
|
+
const MASK_TYPES = new Set(["alpha", "luminance"]);
|
|
8
|
+
/** Feather pad (px). The group/shape mask wrapper's `overflow:hidden` box is
|
|
9
|
+
* grown by this on every side (tree.tsx, `inset:-PAD`) and the coverage is
|
|
10
|
+
* shifted back by the same amount (buildMask) so a BLURRED mask rim isn't
|
|
11
|
+
* re-cut into a hard square at the box edge. Generous enough for the
|
|
12
|
+
* bg-texture ellipse's ~3σ (53.88 CSS sigma) feather. Sharp masks are
|
|
13
|
+
* unaffected (their alpha-0 region simply sits inside the grown box). */
|
|
14
|
+
export const MASK_FEATHER_PAD = 180;
|
|
15
|
+
/** Closed `mask.op` allowlist — runtime half of the double-gate (T4). */
|
|
16
|
+
const MASK_OPS = new Set(["intersect", "subtract", "union"]);
|
|
17
|
+
let maskIdSeq = 0;
|
|
18
|
+
function nextMaskId() {
|
|
19
|
+
maskIdSeq = (maskIdSeq + 1) % 1_000_000;
|
|
20
|
+
return `lumen-mask-${maskIdSeq.toString(36)}`;
|
|
21
|
+
}
|
|
22
|
+
/** Sanitise a shape `ref` to a safe SVG id token. A legitimate ref is a
|
|
23
|
+
* compiler-assigned node id (`[A-Za-z0-9_:-]`). Anything carrying markup
|
|
24
|
+
* characters (`<`, `"`, `#`, whitespace, `(`) is rejected — it can only be
|
|
25
|
+
* an injection attempt, and there is no legitimate id that needs them. */
|
|
26
|
+
function safeIdRef(ref) {
|
|
27
|
+
return /^[A-Za-z0-9_:-]+$/.test(ref) ? ref : null;
|
|
28
|
+
}
|
|
29
|
+
function finite(v) {
|
|
30
|
+
return typeof v === "number" && Number.isFinite(v);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Validate a loose `mask` value into a strict {@link MaskSpec}, or `null`.
|
|
34
|
+
* Re-runs the closed-enum gates (T4) and the source-shape discriminant ;
|
|
35
|
+
* a malformed mask is dropped whole (it cannot be partially honoured).
|
|
36
|
+
*/
|
|
37
|
+
export function parseMaskSpec(value, nodeId) {
|
|
38
|
+
if (typeof value !== "object" || value === null)
|
|
39
|
+
return null;
|
|
40
|
+
const m = value;
|
|
41
|
+
if (typeof m.type !== "string" || !MASK_TYPES.has(m.type)) {
|
|
42
|
+
emitDiagnostic(nodeId, "mask.type", "is not alpha|luminance ; mask omitted (ADR 002 §3.2, T4)");
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
if (typeof m.op !== "string" || !MASK_OPS.has(m.op)) {
|
|
46
|
+
emitDiagnostic(nodeId, "mask.op", "is not intersect|subtract|union ; mask omitted (ADR 002 §3.2, T4)");
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
const src = m.source;
|
|
50
|
+
if (typeof src !== "object" || src === null) {
|
|
51
|
+
emitDiagnostic(nodeId, "mask.source", "is not a typed shape|image source ; mask omitted (T3)");
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
const s = src;
|
|
55
|
+
let source;
|
|
56
|
+
if (s.kind === "shape" && typeof s.ref === "string") {
|
|
57
|
+
source = { kind: "shape", ref: s.ref };
|
|
58
|
+
}
|
|
59
|
+
else if (s.kind === "image" && typeof s.src === "string") {
|
|
60
|
+
// Preserve the mask source's box (`srcRect`: offset from THIS node + size)
|
|
61
|
+
// when present — it places/sizes the CSS mask to the source raster, shared
|
|
62
|
+
// across siblings of different boxes (the caramel halo + drift fix).
|
|
63
|
+
const sr = s.srcRect;
|
|
64
|
+
source =
|
|
65
|
+
sr && finite(sr.x) && finite(sr.y) && finite(sr.w) && finite(sr.h)
|
|
66
|
+
? { kind: "image", src: s.src, srcRect: { x: sr.x, y: sr.y, w: sr.w, h: sr.h } }
|
|
67
|
+
: { kind: "image", src: s.src };
|
|
68
|
+
}
|
|
69
|
+
else if (s.kind === "group" && typeof s.ref === "string") {
|
|
70
|
+
source = { kind: "group", ref: s.ref };
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
emitDiagnostic(nodeId, "mask.source", "is not a typed shape|image|group source ; mask omitted (T3)");
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
const spec = { source, type: m.type, op: m.op };
|
|
77
|
+
const pos = m.position;
|
|
78
|
+
if (pos && finite(pos.x) && finite(pos.y))
|
|
79
|
+
spec.position = { x: pos.x, y: pos.y };
|
|
80
|
+
const size = m.size;
|
|
81
|
+
if (size && finite(size.w) && finite(size.h))
|
|
82
|
+
spec.size = { w: size.w, h: size.h };
|
|
83
|
+
return spec;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Build a `<mask>` element + the CSS reference from a typed mask spec.
|
|
87
|
+
* Returns `null` when the mask must be omitted (bad enum, rejected host,
|
|
88
|
+
* unsafe ref) — the caller renders the subtree unmasked.
|
|
89
|
+
*
|
|
90
|
+
* @param mask the typed spec (already enum-checked by parseMaskSpec,
|
|
91
|
+
* but re-checked here so the builder is safe standalone).
|
|
92
|
+
* @param allowedHosts the bundle's `assets.allowedHosts` ; an image source is
|
|
93
|
+
* gated against it (T1/T2) before reaching `<image href>`.
|
|
94
|
+
* @param nodeId for diagnostics (never carries a value, R9).
|
|
95
|
+
* @param resolveShape resolves a shape `mask.source.ref` to its inlined
|
|
96
|
+
* coverage geometry (#K). Omitted / returns `null` ⇒ the
|
|
97
|
+
* shape source is pending → the whole mask is omitted.
|
|
98
|
+
*/
|
|
99
|
+
export function buildMask(mask, allowedHosts, nodeId, resolveShape, boxSize, feather = false) {
|
|
100
|
+
// T4 — defence in depth : re-validate the enums even though parseMaskSpec
|
|
101
|
+
// already did, so `buildMask` is safe to call on any typed input.
|
|
102
|
+
if (!MASK_TYPES.has(mask.type) || !MASK_OPS.has(mask.op)) {
|
|
103
|
+
emitDiagnostic(nodeId, "mask", "type/op outside the closed enum ; mask omitted (T4)");
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
const id = nextMaskId();
|
|
107
|
+
// The mask content : a single element painted into the mask's luminance
|
|
108
|
+
// (or alpha) channel. Coordinates come from typed numbers only.
|
|
109
|
+
const x = mask.position?.x;
|
|
110
|
+
const y = mask.position?.y;
|
|
111
|
+
const w = mask.size?.w;
|
|
112
|
+
const h = mask.size?.h;
|
|
113
|
+
const geom = {
|
|
114
|
+
...(finite(x) ? { x } : {}),
|
|
115
|
+
...(finite(y) ? { y } : {}),
|
|
116
|
+
...(finite(w) ? { width: w } : {}),
|
|
117
|
+
...(finite(h) ? { height: h } : {}),
|
|
118
|
+
};
|
|
119
|
+
let content;
|
|
120
|
+
if (mask.source.kind === "image") {
|
|
121
|
+
// T1/T2 — gate the URL BEFORE it reaches the `<image href>`. A rejected
|
|
122
|
+
// host/scheme omits the whole mask with a static-reason diagnostic.
|
|
123
|
+
const decision = checkHostAllowed(mask.source.src, allowedHosts);
|
|
124
|
+
if (!decision.allowed) {
|
|
125
|
+
emitDiagnostic(nodeId, "mask.source.src", `image host/scheme rejected ; mask omitted (T1/T2 — ${decision.reason ?? "denied"})`);
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
// `href` is a typed attribute on a constructed element — never markup.
|
|
129
|
+
// For an alpha mask, read the source's own alpha (mask-type:alpha on the
|
|
130
|
+
// <mask>) ; luminance is the SVG default. The image fills the masked box
|
|
131
|
+
// when no explicit geometry is given.
|
|
132
|
+
// External <image> in an SVG <mask> (0×0 SVG) never loads. For `intersect`
|
|
133
|
+
// apply the raster directly as a CSS mask-image. The masked image content is
|
|
134
|
+
// drawn with `object-fit: cover` (Figma scaleMode FILL), so the mask raster
|
|
135
|
+
// — the SAME source image — must `cover` too, else a `Wpx Hpx` (stretch)
|
|
136
|
+
// mask clips a differently-scaled crop and the caramel ribbon shrinks /
|
|
137
|
+
// shifts off its wave. `cover` keeps the alpha aligned with the content.
|
|
138
|
+
if (mask.op === "intersect") {
|
|
139
|
+
const mode = mask.type === "alpha" ? "alpha" : "luminance";
|
|
140
|
+
const url = `url("${mask.source.src}")`;
|
|
141
|
+
// Place + size the mask to the SOURCE raster's box (`srcRect`: offset from
|
|
142
|
+
// this node's box top-left + size), shared by every masked sibling — NOT
|
|
143
|
+
// `cover` of each sibling's box (inflates → orange halo) nor centred
|
|
144
|
+
// (drifts → mask pulled down). The caramel gradient (1146) and 3d-render
|
|
145
|
+
// (930) thus clip to the SAME wave at the SAME spot.
|
|
146
|
+
const rect = mask.source
|
|
147
|
+
.srcRect;
|
|
148
|
+
const usable = rect && finite(rect.x) && finite(rect.y) && finite(rect.w) && finite(rect.h);
|
|
149
|
+
const sizeCss = usable ? `${rect.w}px ${rect.h}px` : "cover";
|
|
150
|
+
const posCss = usable ? `${rect.x}px ${rect.y}px` : "center";
|
|
151
|
+
return {
|
|
152
|
+
def: _jsx("defs", {}, id),
|
|
153
|
+
style: {
|
|
154
|
+
maskImage: url,
|
|
155
|
+
WebkitMaskImage: url,
|
|
156
|
+
maskSize: sizeCss,
|
|
157
|
+
WebkitMaskSize: sizeCss,
|
|
158
|
+
maskRepeat: "no-repeat",
|
|
159
|
+
WebkitMaskRepeat: "no-repeat",
|
|
160
|
+
maskPosition: posCss,
|
|
161
|
+
WebkitMaskPosition: posCss,
|
|
162
|
+
maskMode: mode,
|
|
163
|
+
},
|
|
164
|
+
id,
|
|
165
|
+
feather: false,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
const imgGeom = Object.keys(geom).length > 0
|
|
169
|
+
? geom
|
|
170
|
+
: finite(boxSize?.w) && finite(boxSize?.h)
|
|
171
|
+
? { x: 0, y: 0, width: boxSize.w, height: boxSize.h }
|
|
172
|
+
: { width: "100%", height: "100%" };
|
|
173
|
+
content = _jsx("image", { href: mask.source.src, preserveAspectRatio: "none", ...imgGeom });
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
// Shape (#K) or group/frame (#O) source — INLINE the referenced node's
|
|
177
|
+
// resolved coverage geometry into the `<mask>`, built element-by-element
|
|
178
|
+
// (T3 : zero markup). For a `shape` the resolver returns its own outline ;
|
|
179
|
+
// for a `group` it returns the composite of the container's visible
|
|
180
|
+
// children (the resolver routes on the referenced node's kind).
|
|
181
|
+
//
|
|
182
|
+
// The ref is first re-sanitised (defence in depth : a live LSDP delta could
|
|
183
|
+
// smuggle markup chars), then resolved against the Tree's referenceable-node
|
|
184
|
+
// index. A PENDING ref (id absent) → the mask is omitted, sub-tree rendered
|
|
185
|
+
// unmasked (A2.1 : omission, not crash). Anti-cycle is enforced by the
|
|
186
|
+
// resolver inlining ONLY geometry — never any node's own mask.
|
|
187
|
+
const safeRef = safeIdRef(mask.source.ref);
|
|
188
|
+
if (safeRef === null) {
|
|
189
|
+
emitDiagnostic(nodeId, "mask.source.ref", "shape ref is not a safe id token ; mask omitted (T3)");
|
|
190
|
+
return null;
|
|
191
|
+
}
|
|
192
|
+
const resolved = resolveShape?.(safeRef) ?? null;
|
|
193
|
+
if (resolved === null) {
|
|
194
|
+
emitDiagnostic(nodeId, "mask.source.ref", "shape ref does not resolve to an indexed shape ; mask omitted (ADR 002 A2.1 #K)");
|
|
195
|
+
return null;
|
|
196
|
+
}
|
|
197
|
+
// Position/size place the inlined geometry numerically when given,
|
|
198
|
+
// wrapping it in a translated group (typed numbers only, never a string).
|
|
199
|
+
content =
|
|
200
|
+
Object.keys(geom).length > 0 ? (_jsx("g", { transform: finite(geom.x) || finite(geom.y)
|
|
201
|
+
? `translate(${finite(geom.x) ? geom.x : 0} ${finite(geom.y) ? geom.y : 0})`
|
|
202
|
+
: undefined, children: resolved })) : (resolved);
|
|
203
|
+
}
|
|
204
|
+
// Feather pad : the mask wrapper's box is grown by MASK_FEATHER_PAD on every
|
|
205
|
+
// side (tree.tsx, `inset:-PAD`) so a BLURRED coverage edge isn't re-cut into a
|
|
206
|
+
// hard square by the wrapper's `overflow:hidden`. The coverage is shifted back
|
|
207
|
+
// by the SAME amount here (userSpaceOnUse), so the mask stays put while the box
|
|
208
|
+
// grows. A sharp mask is unaffected (its alpha-0 region just sits inside the
|
|
209
|
+
// grown box). Applied to the coverage only — never the full-coverage union/
|
|
210
|
+
// subtract rect, which must keep spanning the whole (grown) box.
|
|
211
|
+
if (feather) {
|
|
212
|
+
content = (_jsx("g", { transform: `translate(${MASK_FEATHER_PAD} ${MASK_FEATHER_PAD})`, children: content }, "feather-pad"));
|
|
213
|
+
}
|
|
214
|
+
// `union` widens coverage : a base full-coverage white rect is unioned with
|
|
215
|
+
// the source paint. `subtract` removes the source area from full coverage by
|
|
216
|
+
// painting the source black over a white base. `intersect` (default) keeps
|
|
217
|
+
// only the source's own coverage. All three are expressed by which fixed
|
|
218
|
+
// elements we emit — never by interpolating an author string.
|
|
219
|
+
let inner;
|
|
220
|
+
if (mask.op === "intersect") {
|
|
221
|
+
inner = content;
|
|
222
|
+
}
|
|
223
|
+
else if (mask.op === "union") {
|
|
224
|
+
inner = (_jsxs(_Fragment, { children: [_jsx("rect", { x: 0, y: 0, width: "100%", height: "100%", fill: "white" }), content] }));
|
|
225
|
+
}
|
|
226
|
+
else {
|
|
227
|
+
// subtract : white base, source painted black to carve it out.
|
|
228
|
+
inner = (_jsxs(_Fragment, { children: [_jsx("rect", { x: 0, y: 0, width: "100%", height: "100%", fill: "white" }), _jsx("g", { style: { filter: "invert(1)" }, children: content })] }));
|
|
229
|
+
}
|
|
230
|
+
const def = (_jsx("mask", { id: id,
|
|
231
|
+
// `maskContentUnits` (not `maskUnits`) places the coverage in the masked
|
|
232
|
+
// element's user space. The mask REGION is widened to −50%..150% of the
|
|
233
|
+
// masked box (objectBoundingBox units) so a FEATHERED coverage (the
|
|
234
|
+
// bg-texture ellipse blurred 107.76) keeps its soft rim — the default
|
|
235
|
+
// −10%..120% clipped the blur to a hard SQUARE edge. (The prior
|
|
236
|
+
// `maskUnits="userSpaceOnUse"` WITHOUT x/y/width/height shrank the region
|
|
237
|
+
// to the 0×0 defs-svg viewport, hiding every group/shape-masked subtree —
|
|
238
|
+
// the platform-wide bug ; an explicit region is the robust form.)
|
|
239
|
+
maskContentUnits: "userSpaceOnUse", x: "-50%", y: "-50%", width: "200%", height: "200%", ...(mask.type === "alpha" && mask.source.kind !== "image" ? { "mask-type": "alpha" } : {}), children: inner }, id));
|
|
240
|
+
const ref = `url(#${id})`;
|
|
241
|
+
return { def, style: { mask: ref, WebkitMask: ref }, id, feather };
|
|
242
|
+
}
|
|
243
|
+
//# sourceMappingURL=mask.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mask.js","sourceRoot":"","sources":["../../src/render/mask.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frame.d.ts","sourceRoot":"","sources":["../../../src/render/primitives/frame.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"frame.d.ts","sourceRoot":"","sources":["../../../src/render/primitives/frame.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAO9C;;;;;;;;;;;GAWG;AACH,wBAAgB,KAAK,CAAC,EACpB,QAAQ,EACR,MAAM,EACN,aAAa,EACb,cAAc,EACd,QAAQ,GACT,EAAE,cAAc,2CAsGhB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAKxE"}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { motion } from "framer-motion";
|
|
3
3
|
import { toFramer, mountPlay, resolveTransition } from "../../animate/transitions";
|
|
4
|
-
import { backgroundsToCss, parseFills } from "../fill";
|
|
4
|
+
import { backgroundsToCss, parseFills, gateImageFills } from "../fill";
|
|
5
5
|
import { parseCssColor, warnRejectedColor } from "../css-color";
|
|
6
6
|
import { emitDiagnostic } from "../diagnostics";
|
|
7
|
+
import { useAllowedHosts } from "../allowed-hosts";
|
|
7
8
|
/** Absolute-positioned container with size + transform + opacity.
|
|
8
9
|
* Animatable on `transform` and `opacity` only — width/height/position
|
|
9
10
|
* changes are intentionally *not* animatable to keep the broadcast
|
|
@@ -23,7 +24,20 @@ export function Frame({ resolved, nodeId, transitionFor, animateInitial, childre
|
|
|
23
24
|
const height = sizeProp(resolved.height);
|
|
24
25
|
const opacity = numberOr(resolved.opacity, 1);
|
|
25
26
|
const scale = numberOr(resolved.scale, 1);
|
|
26
|
-
|
|
27
|
+
// Static `rotation` (LSML §5.4) is applied HERE, on the frame's own box, so it
|
|
28
|
+
// pivots around the frame centre (transform-origin: center). It must NOT go on
|
|
29
|
+
// the UniversalWrapper for a frame : the wrapper carries no position/size for
|
|
30
|
+
// a self-positioning frame, so it collapses to a 0-height box and the rotation
|
|
31
|
+
// pivots around the wrong point (the picto/caramel swung off-place). `rotate`
|
|
32
|
+
// (animated) still wins when present.
|
|
33
|
+
const rotate = numberOr(resolved.rotate, numberOr(resolved.rotation, 0));
|
|
34
|
+
// Mirror (Figma `scaleY(-1)`, from a negative transform determinant). Applied
|
|
35
|
+
// on the frame box like the rotation so it composes correctly.
|
|
36
|
+
const flipY = resolved.flipY === true;
|
|
37
|
+
// Compiler forwards `cornerRadius` → `radius` (compile.ts). A frame can be a
|
|
38
|
+
// rounded container (Figma pills, the rounded picto square) — apply it as
|
|
39
|
+
// `border-radius` so the frame isn't rendered square.
|
|
40
|
+
const radius = numberOr(resolved.radius, 0);
|
|
27
41
|
// 1.0 single-fill prop — used as fallback when 1.1 `backgrounds[]`
|
|
28
42
|
// is empty. RC#11 : the value is untrusted (static prop OR live LSDP
|
|
29
43
|
// delta) and lands in inline CSS — strict-parse, never passthrough.
|
|
@@ -32,7 +46,11 @@ export function Frame({ resolved, nodeId, transitionFor, animateInitial, childre
|
|
|
32
46
|
if (rawBackground !== undefined && legacyBackground === null) {
|
|
33
47
|
warnRejectedColor("frame.background", nodeId);
|
|
34
48
|
}
|
|
35
|
-
|
|
49
|
+
// LSML 1.2 §3.2 — image-fill `src` is host/scheme-gated (Bastion T1/T2)
|
|
50
|
+
// BEFORE any URL reaches `background-image`. A rejected image-fill is
|
|
51
|
+
// dropped (no passthrough) with an R9-clean diagnostic.
|
|
52
|
+
const allowedHosts = useAllowedHosts();
|
|
53
|
+
const backgrounds = gateImageFills(parseFills(resolved.backgrounds, "frame.backgrounds", nodeId), allowedHosts, "frame.backgrounds", nodeId);
|
|
36
54
|
const clipsContent = resolveClipsContent(resolved.clipsContent, nodeId);
|
|
37
55
|
// Pick the most expressive declared transition among the animated
|
|
38
56
|
// bindings (transform / opacity). If none, no animation.
|
|
@@ -43,12 +61,18 @@ export function Frame({ resolved, nodeId, transitionFor, animateInitial, childre
|
|
|
43
61
|
top: 0,
|
|
44
62
|
width,
|
|
45
63
|
height,
|
|
46
|
-
|
|
64
|
+
// NB: NO permanent `will-change`. `will-change: opacity` makes the frame an
|
|
65
|
+
// isolated group (the browser pre-promotes it as if opacity < 1), which
|
|
66
|
+
// CONTAINS any descendant `mix-blend-mode` to the frame's own backdrop — so
|
|
67
|
+
// a screen/hard-light layer (Sunshine, Ruby20) silently stops compositing
|
|
68
|
+
// with the scene below. The hint also belongs only on actively-animating
|
|
69
|
+
// nodes (bind-animate adds it there) ; a static board doesn't need it.
|
|
47
70
|
// LSML 1.1 §4.3 `clipsContent` (default `true`) — children outside
|
|
48
71
|
// the frame's `size` are clipped. Static layout property : it never
|
|
49
72
|
// animates, so it stays off the 0-layout-event hot path (ADR 001
|
|
50
73
|
// §3.2.5). `false` => omit the declaration (CSS initial = visible).
|
|
51
74
|
...(clipsContent ? { overflow: "hidden" } : {}),
|
|
75
|
+
...(radius > 0 ? { borderRadius: radius } : {}),
|
|
52
76
|
};
|
|
53
77
|
if (backgrounds.length > 0) {
|
|
54
78
|
Object.assign(style, backgroundsToCss(backgrounds, nodeId));
|
|
@@ -56,7 +80,20 @@ export function Frame({ resolved, nodeId, transitionFor, animateInitial, childre
|
|
|
56
80
|
else if (legacyBackground !== undefined && legacyBackground !== null) {
|
|
57
81
|
style.background = legacyBackground;
|
|
58
82
|
}
|
|
59
|
-
|
|
83
|
+
// Figma DROP_SHADOW / INNER_SHADOW. INNER → CSS `box-shadow: inset` (the
|
|
84
|
+
// square's orange/red rim, on the rotated rounded frame, rotates with it in
|
|
85
|
+
// local space — matches Figma). A no-spread DROP → CSS `filter: drop-shadow`,
|
|
86
|
+
// which casts the shadow from the element's RENDERED CONTENT silhouette, not
|
|
87
|
+
// its own rectangular box : the 5 drop shadows live on the UN-rotated wrapper
|
|
88
|
+
// GROUP, so a plain `box-shadow` would project a sharp axis-aligned 464² rect
|
|
89
|
+
// instead of the rotated (8.63°) rounded (r=111) square held inside. The
|
|
90
|
+
// colour is strict-parsed (RC#11) ; geometry is numeric.
|
|
91
|
+
const { filter: shadowFilter, boxShadow } = buildShadows(resolved.shadow, nodeId);
|
|
92
|
+
if (boxShadow !== undefined)
|
|
93
|
+
style.boxShadow = boxShadow;
|
|
94
|
+
if (shadowFilter !== undefined)
|
|
95
|
+
style.filter = shadowFilter;
|
|
96
|
+
const play = mountPlay({ opacity, x, y, scale, rotate, ...(flipY ? { scaleY: -1 } : {}) }, animateInitial, nodeId);
|
|
60
97
|
return (_jsx(motion.div, { style: style, initial: play.initial, animate: play.animate, transition: toFramer(tx), children: children }));
|
|
61
98
|
}
|
|
62
99
|
/**
|
|
@@ -81,6 +118,55 @@ export function resolveClipsContent(v, nodeId) {
|
|
|
81
118
|
function numberOr(v, fallback) {
|
|
82
119
|
return typeof v === "number" && Number.isFinite(v) ? v : fallback;
|
|
83
120
|
}
|
|
121
|
+
/** Build validated shadow CSS from the node's `shadow[]` (each entry:
|
|
122
|
+
* `{ inset?, color, x, y, blur, spread }`). Every colour goes through the
|
|
123
|
+
* strict `parseCssColor` gate (RC#11 : the value is wire-drivable) — a
|
|
124
|
+
* rejected colour drops that layer with a diagnostic, never reaches CSS.
|
|
125
|
+
* Geometry values are coerced to finite numbers.
|
|
126
|
+
*
|
|
127
|
+
* Splits by kind :
|
|
128
|
+
* - INNER (inset) OR any shadow with a non-zero spread → `box-shadow`
|
|
129
|
+
* (inset rim / spread halo — both follow the element's own border box,
|
|
130
|
+
* which for the rotated rounded square IS the right silhouette).
|
|
131
|
+
* - no-spread DROP → `filter: drop-shadow`, cast from the element's rendered
|
|
132
|
+
* CONTENT (so a wrapper group's drop shadow tracks its rotated/rounded
|
|
133
|
+
* child instead of the wrapper's rectangular box). drop-shadow's blur maps
|
|
134
|
+
* to a Gaussian stdDeviation ; box-shadow uses 2×σ, so halve to match.
|
|
135
|
+
* Returns `{}` when nothing usable survives. */
|
|
136
|
+
function buildShadows(value, nodeId) {
|
|
137
|
+
if (!Array.isArray(value) || value.length === 0)
|
|
138
|
+
return {};
|
|
139
|
+
const dropParts = [];
|
|
140
|
+
const boxParts = [];
|
|
141
|
+
for (const s of value) {
|
|
142
|
+
if (typeof s !== "object" || s === null)
|
|
143
|
+
continue;
|
|
144
|
+
const spec = s;
|
|
145
|
+
const color = typeof spec.color === "string" ? parseCssColor(spec.color) : null;
|
|
146
|
+
if (color === null) {
|
|
147
|
+
warnRejectedColor("frame.shadow.color", nodeId);
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
const x = numberOr(spec.x, 0);
|
|
151
|
+
const y = numberOr(spec.y, 0);
|
|
152
|
+
const blur = numberOr(spec.blur, 0);
|
|
153
|
+
const spread = numberOr(spec.spread, 0);
|
|
154
|
+
const inset = spec.inset === true;
|
|
155
|
+
if (!inset && spread === 0) {
|
|
156
|
+
dropParts.push(`drop-shadow(${x}px ${y}px ${blur / 2}px ${color})`);
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
const insetKw = inset ? "inset " : "";
|
|
160
|
+
boxParts.push(`${insetKw}${x}px ${y}px ${blur}px ${spread}px ${color}`);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
const out = {};
|
|
164
|
+
if (dropParts.length > 0)
|
|
165
|
+
out.filter = dropParts.join(" ");
|
|
166
|
+
if (boxParts.length > 0)
|
|
167
|
+
out.boxShadow = boxParts.join(", ");
|
|
168
|
+
return out;
|
|
169
|
+
}
|
|
84
170
|
function sizeProp(v) {
|
|
85
171
|
if (typeof v === "number" && Number.isFinite(v))
|
|
86
172
|
return v;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frame.js","sourceRoot":"","sources":["../../../src/render/primitives/frame.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAGvC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AACnF,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"frame.js","sourceRoot":"","sources":["../../../src/render/primitives/frame.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { PrimitiveProps } from "./index";
|
|
2
2
|
/** CSS Grid container with declared rows / cols. */
|
|
3
|
-
export declare function Grid({ resolved, children }: PrimitiveProps): import("react/jsx-runtime").JSX.Element;
|
|
3
|
+
export declare function Grid({ resolved, children, establishesContainingBlock }: PrimitiveProps): import("react/jsx-runtime").JSX.Element;
|
|
4
4
|
//# sourceMappingURL=grid.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"grid.d.ts","sourceRoot":"","sources":["../../../src/render/primitives/grid.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE9C,oDAAoD;AACpD,wBAAgB,IAAI,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,cAAc,
|
|
1
|
+
{"version":3,"file":"grid.d.ts","sourceRoot":"","sources":["../../../src/render/primitives/grid.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE9C,oDAAoD;AACpD,wBAAgB,IAAI,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,0BAA0B,EAAE,EAAE,cAAc,2CAmBtF"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
/** CSS Grid container with declared rows / cols. */
|
|
3
|
-
export function Grid({ resolved, children }) {
|
|
3
|
+
export function Grid({ resolved, children, establishesContainingBlock }) {
|
|
4
4
|
const cols = resolved.cols ?? "1fr";
|
|
5
5
|
const rows = resolved.rows ?? "auto";
|
|
6
6
|
const gap = resolved.gap ?? 0;
|
|
@@ -9,6 +9,9 @@ export function Grid({ resolved, children }) {
|
|
|
9
9
|
gridTemplateColumns: cols,
|
|
10
10
|
gridTemplateRows: rows,
|
|
11
11
|
gap,
|
|
12
|
+
// ADR 002 §3.1 (D1) — establish a containing block for absolutely
|
|
13
|
+
// placed children ; untouched for pure auto-layout grids (RC#2).
|
|
14
|
+
...(establishesContainingBlock ? { position: "relative" } : {}),
|
|
12
15
|
}, children: children }));
|
|
13
16
|
}
|
|
14
17
|
//# sourceMappingURL=grid.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"grid.js","sourceRoot":"","sources":["../../../src/render/primitives/grid.tsx"],"names":[],"mappings":";AAEA,oDAAoD;AACpD,MAAM,UAAU,IAAI,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAkB;
|
|
1
|
+
{"version":3,"file":"grid.js","sourceRoot":"","sources":["../../../src/render/primitives/grid.tsx"],"names":[],"mappings":";AAEA,oDAAoD;AACpD,MAAM,UAAU,IAAI,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,0BAA0B,EAAkB;IACrF,MAAM,IAAI,GAAI,QAAQ,CAAC,IAAe,IAAI,KAAK,CAAC;IAChD,MAAM,IAAI,GAAI,QAAQ,CAAC,IAAe,IAAI,MAAM,CAAC;IACjD,MAAM,GAAG,GAAI,QAAQ,CAAC,GAAmC,IAAI,CAAC,CAAC;IAC/D,OAAO,CACL,cACE,KAAK,EAAE;YACL,OAAO,EAAE,MAAM;YACf,mBAAmB,EAAE,IAAI;YACzB,gBAAgB,EAAE,IAAI;YACtB,GAAG;YACH,kEAAkE;YAClE,iEAAiE;YACjE,GAAG,CAAC,0BAA0B,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAChE,YAEA,QAAQ,GACL,CACP,CAAC;AACJ,CAAC"}
|
|
@@ -2,6 +2,13 @@ import type { PrimitiveProps } from "./index";
|
|
|
2
2
|
/** Image leaf. `src`, `fit` (cover/contain/fill), `position`,
|
|
3
3
|
* `opacity`. Opacity is animated when a transition is declared. When an
|
|
4
4
|
* `animate.from` is lowered onto the node, it mounts at that state and
|
|
5
|
-
* plays to its target on mount (mount-play).
|
|
5
|
+
* plays to its target on mount (mount-play).
|
|
6
|
+
*
|
|
7
|
+
* Security (Bastion T1/T2, ADR 002 #F) : `src` is untrusted (static prop
|
|
8
|
+
* OR live LSDP delta) and was placed into the DOM with NO host/scheme
|
|
9
|
+
* check until #F (the latent 1.1 hole — `assets.allowedHosts` was declared
|
|
10
|
+
* but never enforced). It now passes `gateSrc` BEFORE reaching the `<img>`
|
|
11
|
+
* — a rejected host/scheme omits the image entirely (no passthrough), with
|
|
12
|
+
* an R9-clean diagnostic. This is the runtime arm of the double-gate. */
|
|
6
13
|
export declare function Image({ resolved, nodeId, transitionFor, animateInitial }: PrimitiveProps): import("react/jsx-runtime").JSX.Element | null;
|
|
7
14
|
//# sourceMappingURL=image.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../../../src/render/primitives/image.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../../../src/render/primitives/image.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAI9C;;;;;;;;;;0EAU0E;AAC1E,wBAAgB,KAAK,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,cAAc,EAAE,EAAE,cAAc,kDAyCxF"}
|
|
@@ -1,12 +1,21 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { motion } from "framer-motion";
|
|
3
3
|
import { toFramer, mountPlay, resolveTransition } from "../../animate/transitions";
|
|
4
|
+
import { gateSrc, useAllowedHosts } from "../allowed-hosts";
|
|
4
5
|
/** Image leaf. `src`, `fit` (cover/contain/fill), `position`,
|
|
5
6
|
* `opacity`. Opacity is animated when a transition is declared. When an
|
|
6
7
|
* `animate.from` is lowered onto the node, it mounts at that state and
|
|
7
|
-
* plays to its target on mount (mount-play).
|
|
8
|
+
* plays to its target on mount (mount-play).
|
|
9
|
+
*
|
|
10
|
+
* Security (Bastion T1/T2, ADR 002 #F) : `src` is untrusted (static prop
|
|
11
|
+
* OR live LSDP delta) and was placed into the DOM with NO host/scheme
|
|
12
|
+
* check until #F (the latent 1.1 hole — `assets.allowedHosts` was declared
|
|
13
|
+
* but never enforced). It now passes `gateSrc` BEFORE reaching the `<img>`
|
|
14
|
+
* — a rejected host/scheme omits the image entirely (no passthrough), with
|
|
15
|
+
* an R9-clean diagnostic. This is the runtime arm of the double-gate. */
|
|
8
16
|
export function Image({ resolved, nodeId, transitionFor, animateInitial }) {
|
|
9
|
-
const
|
|
17
|
+
const allowedHosts = useAllowedHosts();
|
|
18
|
+
const src = gateSrc(resolved.src, allowedHosts, "image.src", nodeId);
|
|
10
19
|
if (!src)
|
|
11
20
|
return null;
|
|
12
21
|
// LSML §4.5 `alt` is required and was silently unrendered until
|
|
@@ -27,7 +36,12 @@ export function Image({ resolved, nodeId, transitionFor, animateInitial }) {
|
|
|
27
36
|
objectPosition: position,
|
|
28
37
|
width,
|
|
29
38
|
height,
|
|
30
|
-
|
|
39
|
+
// NB: NO `will-change` here. Promoting the <img> to its own GPU layer
|
|
40
|
+
// hoists it out of the wrapper's paint buffer, so a `mix-blend-mode`
|
|
41
|
+
// on the wrapper (Sunshine screen, Ruby20 / caramel hard-light) blends
|
|
42
|
+
// an EMPTY box with the backdrop → the blend silently no-ops and the
|
|
43
|
+
// image's contribution (the diagonal light streaks, the warm Ruby) is
|
|
44
|
+
// lost. Static images don't need the compositor hint anyway.
|
|
31
45
|
}, initial: play.initial, animate: play.animate, transition: toFramer(tx), draggable: false }));
|
|
32
46
|
}
|
|
33
47
|
function numberOr(v, fallback) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image.js","sourceRoot":"","sources":["../../../src/render/primitives/image.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAEvC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"image.js","sourceRoot":"","sources":["../../../src/render/primitives/image.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAEvC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AACnF,OAAO,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAE5D;;;;;;;;;;0EAU0E;AAC1E,MAAM,UAAU,KAAK,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,cAAc,EAAkB;IACvF,MAAM,YAAY,GAAG,eAAe,EAAE,CAAC;IACvC,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,GAAG,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC;IACrE,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC;IACtB,gEAAgE;IAChE,sEAAsE;IACtE,MAAM,GAAG,GAAG,OAAO,QAAQ,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IACjE,MAAM,GAAG,GAAI,QAAQ,CAAC,GAA0B,IAAI,SAAS,CAAC;IAC9D,MAAM,QAAQ,GAAI,QAAQ,CAAC,QAA+B,IAAI,QAAQ,CAAC;IACvE,MAAM,OAAO,GAAG,QAAQ,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IAC9C,mFAAmF;IACnF,0EAA0E;IAC1E,sEAAsE;IACtE,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IAC5C,MAAM,MAAM,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAE9C,MAAM,EAAE,GAAG,iBAAiB,CAAC,aAAa,EAAE,CAAC,SAAS,EAAE,KAAK,CAAC,EAAE,cAAc,CAAC,CAAC;IAChF,MAAM,IAAI,GAAG,SAAS,CAAC,EAAE,OAAO,EAAE,EAAE,cAAc,EAAE,MAAM,CAAC,CAAC;IAE5D,OAAO,CACL,KAAC,MAAM,CAAC,GAAG,IACT,GAAG,EAAE,GAAG,EACR,GAAG,EAAE,GAAG,EACR,KAAK,EAAE;YACL,SAAS,EAAE,GAAuC;YAClD,cAAc,EAAE,QAAQ;YACxB,KAAK;YACL,MAAM;YACN,sEAAsE;YACtE,qEAAqE;YACrE,uEAAuE;YACvE,qEAAqE;YACrE,sEAAsE;YACtE,6DAA6D;SAC9D,EACD,OAAO,EAAE,IAAI,CAAC,OAAO,EACrB,OAAO,EAAE,IAAI,CAAC,OAAO,EACrB,UAAU,EAAE,QAAQ,CAAC,EAAE,CAAC,EACxB,SAAS,EAAE,KAAK,GAChB,CACH,CAAC;AACJ,CAAC;AAED,SAAS,QAAQ,CAAC,CAAU,EAAE,QAAgB;IAC5C,OAAO,OAAO,CAAC,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;AACpE,CAAC;AAED;mDACmD;AACnD,SAAS,KAAK,CAAC,CAAU,EAAE,QAAgB;IACzC,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;QAAE,OAAO,GAAG,CAAC,IAAI,CAAC;IACjE,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,CAAC,CAAC;IACpD,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
|
@@ -13,6 +13,13 @@ export interface PrimitiveProps {
|
|
|
13
13
|
* element mounts in this state and animates to its rendered target on
|
|
14
14
|
* mount (mount-play). `undefined` → no `initial` (no mount-play). */
|
|
15
15
|
animateInitial?: Record<string, number | string>;
|
|
16
|
+
/** ADR 002 §3.1 (D1) — set by the Tree when this node has at least one
|
|
17
|
+
* absolutely positioned child. A layout container (`stack`/`grid`)
|
|
18
|
+
* flips to `position: relative` so its children's `left/top` resolve
|
|
19
|
+
* against it. `frame` is already `position: absolute` (a containing
|
|
20
|
+
* block) and ignores it ; leaf primitives have no children and ignore
|
|
21
|
+
* it too. `false`/absent → no change (pure auto-layout, RC#2). */
|
|
22
|
+
establishesContainingBlock?: boolean;
|
|
16
23
|
children?: ReactNode;
|
|
17
24
|
}
|
|
18
25
|
export declare const PRIMITIVES: Partial<Record<RenderKind, ComponentType<PrimitiveProps>>>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/render/primitives/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACtD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAa5D,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC;oEACgE;IAChE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,UAAU,GAAG,SAAS,CAAC;IACvD;;;;0EAIsE;IACtE,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;IACjD,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED,eAAO,MAAM,UAAU,EAAE,OAAO,CAAC,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,cAAc,CAAC,CAAC,CASjF,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/render/primitives/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACtD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAa5D,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC;oEACgE;IAChE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,UAAU,GAAG,SAAS,CAAC;IACvD;;;;0EAIsE;IACtE,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;IACjD;;;;;uEAKmE;IACnE,0BAA0B,CAAC,EAAE,OAAO,CAAC;IACrC,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED,eAAO,MAAM,UAAU,EAAE,OAAO,CAAC,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,cAAc,CAAC,CAAC,CASjF,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/render/primitives/index.ts"],"names":[],"mappings":"AAAA,oEAAoE;AACpE,uEAAuE;AACvE,0DAA0D;AAK1D,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/render/primitives/index.ts"],"names":[],"mappings":"AAAA,oEAAoE;AACpE,uEAAuE;AACvE,0DAA0D;AAK1D,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AA2BtC,MAAM,CAAC,MAAM,UAAU,GAA+D;IACpF,KAAK,EAAE,KAAK;IACZ,IAAI,EAAE,IAAI;IACV,KAAK,EAAE,KAAK;IACZ,IAAI,EAAE,IAAI;IACV,KAAK,EAAE,KAAK;IACZ,KAAK,EAAE,KAAK;IACZ,KAAK,EAAE,KAAK;IACZ,QAAQ,EAAE,QAAQ;CACnB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shape.d.ts","sourceRoot":"","sources":["../../../src/render/primitives/shape.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"shape.d.ts","sourceRoot":"","sources":["../../../src/render/primitives/shape.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAY9C;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,KAAK,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,cAAc,EAAE,EAAE,cAAc,2CAiHxF"}
|