@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.
- package/README.md +57 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/animate/frame-coalescer.d.ts +13 -0
- package/dist/animate/frame-coalescer.d.ts.map +1 -0
- package/dist/animate/frame-coalescer.js +46 -0
- package/dist/animate/frame-coalescer.js.map +1 -0
- package/dist/animate/keyframes.d.ts +1 -1
- package/dist/animate/keyframes.d.ts.map +1 -1
- package/dist/animate/keyframes.js +20 -6
- package/dist/animate/keyframes.js.map +1 -1
- package/dist/animate/transitions.d.ts +33 -1
- package/dist/animate/transitions.d.ts.map +1 -1
- package/dist/animate/transitions.js +78 -3
- package/dist/animate/transitions.js.map +1 -1
- package/dist/{broadcast-B82fQPph.js → broadcast-3vYij4k-.js} +3 -3
- package/dist/{broadcast-B82fQPph.js.map → broadcast-3vYij4k-.js.map} +1 -1
- package/dist/{control-DIfwMYRb.js → control-BFNkY7-6.js} +4 -4
- package/dist/{control-DIfwMYRb.js.map → control-BFNkY7-6.js.map} +1 -1
- package/dist/{index-BFZXQAD7.js → index-CyOlpZAL.js} +318 -145
- package/dist/index-CyOlpZAL.js.map +1 -0
- package/dist/index.d.ts +5 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.html +1 -1
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -1
- package/dist/lumencast.js +9 -2
- package/dist/mount.d.ts.map +1 -1
- package/dist/mount.js +11 -1
- package/dist/mount.js.map +1 -1
- package/dist/render/bind-animate.d.ts +40 -0
- package/dist/render/bind-animate.d.ts.map +1 -0
- package/dist/render/bind-animate.js +329 -0
- package/dist/render/bind-animate.js.map +1 -0
- package/dist/render/bundle.d.ts +48 -6
- package/dist/render/bundle.d.ts.map +1 -1
- package/dist/render/bundle.js +71 -4
- package/dist/render/bundle.js.map +1 -1
- package/dist/render/color-interp.d.ts +18 -0
- package/dist/render/color-interp.d.ts.map +1 -0
- package/dist/render/color-interp.js +303 -0
- package/dist/render/color-interp.js.map +1 -0
- package/dist/render/css-color.d.ts +16 -0
- package/dist/render/css-color.d.ts.map +1 -0
- package/dist/render/css-color.js +130 -0
- package/dist/render/css-color.js.map +1 -0
- package/dist/render/diagnostics.d.ts +26 -0
- package/dist/render/diagnostics.d.ts.map +1 -0
- package/dist/render/diagnostics.js +58 -0
- package/dist/render/diagnostics.js.map +1 -0
- package/dist/render/fill.d.ts +15 -3
- package/dist/render/fill.d.ts.map +1 -1
- package/dist/render/fill.js +81 -14
- package/dist/render/fill.js.map +1 -1
- package/dist/render/filter-clamp.d.ts +35 -0
- package/dist/render/filter-clamp.d.ts.map +1 -0
- package/dist/render/filter-clamp.js +90 -0
- package/dist/render/filter-clamp.js.map +1 -0
- package/dist/render/keyframe-player.d.ts +4 -1
- package/dist/render/keyframe-player.d.ts.map +1 -1
- package/dist/render/keyframe-player.js +2 -2
- package/dist/render/keyframe-player.js.map +1 -1
- package/dist/render/primitives/frame.d.ts +16 -1
- package/dist/render/primitives/frame.d.ts.map +1 -1
- package/dist/render/primitives/frame.js +44 -13
- package/dist/render/primitives/frame.js.map +1 -1
- package/dist/render/primitives/image.d.ts +1 -1
- package/dist/render/primitives/image.d.ts.map +1 -1
- package/dist/render/primitives/image.js +8 -5
- package/dist/render/primitives/image.js.map +1 -1
- package/dist/render/primitives/index.d.ts +3 -0
- package/dist/render/primitives/index.d.ts.map +1 -1
- package/dist/render/primitives/index.js.map +1 -1
- package/dist/render/primitives/instance.d.ts +1 -1
- package/dist/render/primitives/instance.d.ts.map +1 -1
- package/dist/render/primitives/instance.js +10 -13
- package/dist/render/primitives/instance.js.map +1 -1
- package/dist/render/primitives/shape.d.ts +9 -3
- package/dist/render/primitives/shape.d.ts.map +1 -1
- package/dist/render/primitives/shape.js +58 -14
- package/dist/render/primitives/shape.js.map +1 -1
- package/dist/render/primitives/text.d.ts +35 -4
- package/dist/render/primitives/text.d.ts.map +1 -1
- package/dist/render/primitives/text.js +181 -9
- package/dist/render/primitives/text.js.map +1 -1
- package/dist/render/prop-allowlist.d.ts +10 -0
- package/dist/render/prop-allowlist.d.ts.map +1 -0
- package/dist/render/prop-allowlist.js +112 -0
- package/dist/render/prop-allowlist.js.map +1 -0
- package/dist/render/svg-path.d.ts +35 -0
- package/dist/render/svg-path.d.ts.map +1 -0
- package/dist/render/svg-path.js +211 -0
- package/dist/render/svg-path.js.map +1 -0
- package/dist/render/tree.d.ts.map +1 -1
- package/dist/render/tree.js +30 -5
- package/dist/render/tree.js.map +1 -1
- package/dist/{status-pill-DNHbHdag.js → status-pill-DIpXc5du.js} +2 -2
- package/dist/{status-pill-DNHbHdag.js.map → status-pill-DIpXc5du.js.map} +1 -1
- package/dist/{test-Dp0QrKYM.js → test-ByRec1kd.js} +4 -4
- package/dist/{test-Dp0QrKYM.js.map → test-ByRec1kd.js.map} +1 -1
- package/dist/tree-D5wYHpPu.js +1230 -0
- package/dist/tree-D5wYHpPu.js.map +1 -0
- package/dist/types.d.ts +26 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +5 -4
- package/src/animate/frame-coalescer.ts +63 -0
- package/src/animate/keyframes.ts +24 -5
- package/src/animate/transitions.ts +85 -3
- package/src/index.ts +24 -0
- package/src/mount.ts +12 -1
- package/src/render/bind-animate.tsx +370 -0
- package/src/render/bundle.ts +102 -10
- package/src/render/color-interp.ts +303 -0
- package/src/render/css-color.ts +145 -0
- package/src/render/diagnostics.ts +75 -0
- package/src/render/fill.tsx +85 -14
- package/src/render/filter-clamp.ts +99 -0
- package/src/render/keyframe-player.tsx +10 -2
- package/src/render/primitives/frame.tsx +53 -14
- package/src/render/primitives/image.tsx +8 -4
- package/src/render/primitives/index.ts +3 -0
- package/src/render/primitives/instance.tsx +14 -15
- package/src/render/primitives/shape.tsx +78 -14
- package/src/render/primitives/text.tsx +226 -9
- package/src/render/prop-allowlist.ts +119 -0
- package/src/render/svg-path.ts +215 -0
- package/src/render/tree.tsx +41 -6
- package/src/types.ts +27 -0
- package/dist/index-BFZXQAD7.js.map +0 -1
- package/dist/tree-x5Qd9Kq0.js +0 -508
- package/dist/tree-x5Qd9Kq0.js.map +0 -1
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
// sRGB colour interpolation (LSML 1.1 §6.5) — issue #33.
|
|
2
|
+
//
|
|
3
|
+
// Both endpoints of a colour animation are first CANONICALISED through
|
|
4
|
+
// the strict shared parser (`parseCssColor`, css-color.ts — ADR 001
|
|
5
|
+
// RC#11/RC#12, never a raw string), then converted to RGBA channels in
|
|
6
|
+
// [0, 1] and interpolated component-wise :
|
|
7
|
+
//
|
|
8
|
+
// out_c = a_c + t * (b_c - a_c) for c ∈ {r, g, b, a}
|
|
9
|
+
//
|
|
10
|
+
// with `t` produced by the easing curve. The output is serialised back
|
|
11
|
+
// to `rgba()` form — which itself round-trips through `parseCssColor`
|
|
12
|
+
// at the consuming primitive (belt and braces).
|
|
13
|
+
//
|
|
14
|
+
// All conversions are constant-time per value (the parser already
|
|
15
|
+
// bounds inputs to 64 chars) ; the named-colour table is a flat map
|
|
16
|
+
// lookup.
|
|
17
|
+
import { parseCssColor } from "./css-color";
|
|
18
|
+
// CSS Color 4 §6.1 named colours → packed 0xRRGGBB. Kept numeric (not
|
|
19
|
+
// hex strings) to minimise bundle weight ; the set of NAMES here is
|
|
20
|
+
// exactly the set accepted by css-color.ts (`transparent` and
|
|
21
|
+
// `currentcolor` are handled separately — `currentcolor` cannot be
|
|
22
|
+
// interpolated without computed-style context and is rejected).
|
|
23
|
+
const NAMED_RGB = {
|
|
24
|
+
aliceblue: 0xf0f8ff,
|
|
25
|
+
antiquewhite: 0xfaebd7,
|
|
26
|
+
aqua: 0x00ffff,
|
|
27
|
+
aquamarine: 0x7fffd4,
|
|
28
|
+
azure: 0xf0ffff,
|
|
29
|
+
beige: 0xf5f5dc,
|
|
30
|
+
bisque: 0xffe4c4,
|
|
31
|
+
black: 0x000000,
|
|
32
|
+
blanchedalmond: 0xffebcd,
|
|
33
|
+
blue: 0x0000ff,
|
|
34
|
+
blueviolet: 0x8a2be2,
|
|
35
|
+
brown: 0xa52a2a,
|
|
36
|
+
burlywood: 0xdeb887,
|
|
37
|
+
cadetblue: 0x5f9ea0,
|
|
38
|
+
chartreuse: 0x7fff00,
|
|
39
|
+
chocolate: 0xd2691e,
|
|
40
|
+
coral: 0xff7f50,
|
|
41
|
+
cornflowerblue: 0x6495ed,
|
|
42
|
+
cornsilk: 0xfff8dc,
|
|
43
|
+
crimson: 0xdc143c,
|
|
44
|
+
cyan: 0x00ffff,
|
|
45
|
+
darkblue: 0x00008b,
|
|
46
|
+
darkcyan: 0x008b8b,
|
|
47
|
+
darkgoldenrod: 0xb8860b,
|
|
48
|
+
darkgray: 0xa9a9a9,
|
|
49
|
+
darkgreen: 0x006400,
|
|
50
|
+
darkgrey: 0xa9a9a9,
|
|
51
|
+
darkkhaki: 0xbdb76b,
|
|
52
|
+
darkmagenta: 0x8b008b,
|
|
53
|
+
darkolivegreen: 0x556b2f,
|
|
54
|
+
darkorange: 0xff8c00,
|
|
55
|
+
darkorchid: 0x9932cc,
|
|
56
|
+
darkred: 0x8b0000,
|
|
57
|
+
darksalmon: 0xe9967a,
|
|
58
|
+
darkseagreen: 0x8fbc8f,
|
|
59
|
+
darkslateblue: 0x483d8b,
|
|
60
|
+
darkslategray: 0x2f4f4f,
|
|
61
|
+
darkslategrey: 0x2f4f4f,
|
|
62
|
+
darkturquoise: 0x00ced1,
|
|
63
|
+
darkviolet: 0x9400d3,
|
|
64
|
+
deeppink: 0xff1493,
|
|
65
|
+
deepskyblue: 0x00bfff,
|
|
66
|
+
dimgray: 0x696969,
|
|
67
|
+
dimgrey: 0x696969,
|
|
68
|
+
dodgerblue: 0x1e90ff,
|
|
69
|
+
firebrick: 0xb22222,
|
|
70
|
+
floralwhite: 0xfffaf0,
|
|
71
|
+
forestgreen: 0x228b22,
|
|
72
|
+
fuchsia: 0xff00ff,
|
|
73
|
+
gainsboro: 0xdcdcdc,
|
|
74
|
+
ghostwhite: 0xf8f8ff,
|
|
75
|
+
gold: 0xffd700,
|
|
76
|
+
goldenrod: 0xdaa520,
|
|
77
|
+
gray: 0x808080,
|
|
78
|
+
green: 0x008000,
|
|
79
|
+
greenyellow: 0xadff2f,
|
|
80
|
+
grey: 0x808080,
|
|
81
|
+
honeydew: 0xf0fff0,
|
|
82
|
+
hotpink: 0xff69b4,
|
|
83
|
+
indianred: 0xcd5c5c,
|
|
84
|
+
indigo: 0x4b0082,
|
|
85
|
+
ivory: 0xfffff0,
|
|
86
|
+
khaki: 0xf0e68c,
|
|
87
|
+
lavender: 0xe6e6fa,
|
|
88
|
+
lavenderblush: 0xfff0f5,
|
|
89
|
+
lawngreen: 0x7cfc00,
|
|
90
|
+
lemonchiffon: 0xfffacd,
|
|
91
|
+
lightblue: 0xadd8e6,
|
|
92
|
+
lightcoral: 0xf08080,
|
|
93
|
+
lightcyan: 0xe0ffff,
|
|
94
|
+
lightgoldenrodyellow: 0xfafad2,
|
|
95
|
+
lightgray: 0xd3d3d3,
|
|
96
|
+
lightgreen: 0x90ee90,
|
|
97
|
+
lightgrey: 0xd3d3d3,
|
|
98
|
+
lightpink: 0xffb6c1,
|
|
99
|
+
lightsalmon: 0xffa07a,
|
|
100
|
+
lightseagreen: 0x20b2aa,
|
|
101
|
+
lightskyblue: 0x87cefa,
|
|
102
|
+
lightslategray: 0x778899,
|
|
103
|
+
lightslategrey: 0x778899,
|
|
104
|
+
lightsteelblue: 0xb0c4de,
|
|
105
|
+
lightyellow: 0xffffe0,
|
|
106
|
+
lime: 0x00ff00,
|
|
107
|
+
limegreen: 0x32cd32,
|
|
108
|
+
linen: 0xfaf0e6,
|
|
109
|
+
magenta: 0xff00ff,
|
|
110
|
+
maroon: 0x800000,
|
|
111
|
+
mediumaquamarine: 0x66cdaa,
|
|
112
|
+
mediumblue: 0x0000cd,
|
|
113
|
+
mediumorchid: 0xba55d3,
|
|
114
|
+
mediumpurple: 0x9370db,
|
|
115
|
+
mediumseagreen: 0x3cb371,
|
|
116
|
+
mediumslateblue: 0x7b68ee,
|
|
117
|
+
mediumspringgreen: 0x00fa9a,
|
|
118
|
+
mediumturquoise: 0x48d1cc,
|
|
119
|
+
mediumvioletred: 0xc71585,
|
|
120
|
+
midnightblue: 0x191970,
|
|
121
|
+
mintcream: 0xf5fffa,
|
|
122
|
+
mistyrose: 0xffe4e1,
|
|
123
|
+
moccasin: 0xffe4b5,
|
|
124
|
+
navajowhite: 0xffdead,
|
|
125
|
+
navy: 0x000080,
|
|
126
|
+
oldlace: 0xfdf5e6,
|
|
127
|
+
olive: 0x808000,
|
|
128
|
+
olivedrab: 0x6b8e23,
|
|
129
|
+
orange: 0xffa500,
|
|
130
|
+
orangered: 0xff4500,
|
|
131
|
+
orchid: 0xda70d6,
|
|
132
|
+
palegoldenrod: 0xeee8aa,
|
|
133
|
+
palegreen: 0x98fb98,
|
|
134
|
+
paleturquoise: 0xafeeee,
|
|
135
|
+
palevioletred: 0xdb7093,
|
|
136
|
+
papayawhip: 0xffefd5,
|
|
137
|
+
peachpuff: 0xffdab9,
|
|
138
|
+
peru: 0xcd853f,
|
|
139
|
+
pink: 0xffc0cb,
|
|
140
|
+
plum: 0xdda0dd,
|
|
141
|
+
powderblue: 0xb0e0e6,
|
|
142
|
+
purple: 0x800080,
|
|
143
|
+
rebeccapurple: 0x663399,
|
|
144
|
+
red: 0xff0000,
|
|
145
|
+
rosybrown: 0xbc8f8f,
|
|
146
|
+
royalblue: 0x4169e1,
|
|
147
|
+
saddlebrown: 0x8b4513,
|
|
148
|
+
salmon: 0xfa8072,
|
|
149
|
+
sandybrown: 0xf4a460,
|
|
150
|
+
seagreen: 0x2e8b57,
|
|
151
|
+
seashell: 0xfff5ee,
|
|
152
|
+
sienna: 0xa0522d,
|
|
153
|
+
silver: 0xc0c0c0,
|
|
154
|
+
skyblue: 0x87ceeb,
|
|
155
|
+
slateblue: 0x6a5acd,
|
|
156
|
+
slategray: 0x708090,
|
|
157
|
+
slategrey: 0x708090,
|
|
158
|
+
snow: 0xfffafa,
|
|
159
|
+
springgreen: 0x00ff7f,
|
|
160
|
+
steelblue: 0x4682b4,
|
|
161
|
+
tan: 0xd2b48c,
|
|
162
|
+
teal: 0x008080,
|
|
163
|
+
thistle: 0xd8bfd8,
|
|
164
|
+
tomato: 0xff6347,
|
|
165
|
+
turquoise: 0x40e0d0,
|
|
166
|
+
violet: 0xee82ee,
|
|
167
|
+
wheat: 0xf5deb3,
|
|
168
|
+
white: 0xffffff,
|
|
169
|
+
whitesmoke: 0xf5f5f5,
|
|
170
|
+
yellow: 0xffff00,
|
|
171
|
+
yellowgreen: 0x9acd32,
|
|
172
|
+
};
|
|
173
|
+
/**
|
|
174
|
+
* Canonicalise + convert an untrusted colour value to RGBA channels in
|
|
175
|
+
* [0, 1]. The value passes through `parseCssColor` FIRST — anything the
|
|
176
|
+
* strict parser rejects converts to `null` here (never interpolate a
|
|
177
|
+
* raw string, §6.5 step 1 / RC#11). `currentcolor` is also rejected :
|
|
178
|
+
* it has no concrete channels without computed-style context.
|
|
179
|
+
*/
|
|
180
|
+
export function cssColorToRgba(value) {
|
|
181
|
+
const v = parseCssColor(value);
|
|
182
|
+
if (v === null)
|
|
183
|
+
return null;
|
|
184
|
+
if (v.startsWith("#"))
|
|
185
|
+
return hexToRgba(v);
|
|
186
|
+
if (v.startsWith("rgb")) {
|
|
187
|
+
const body = v.slice(v.indexOf("(") + 1, -1);
|
|
188
|
+
const parts = body.split(",").map((p) => p.trim());
|
|
189
|
+
if (parts.length < 3)
|
|
190
|
+
return null;
|
|
191
|
+
const pct = parts[0].endsWith("%");
|
|
192
|
+
const scale = pct ? 100 : 255;
|
|
193
|
+
const r = channel(parts[0], scale);
|
|
194
|
+
const g = channel(parts[1], scale);
|
|
195
|
+
const b = channel(parts[2], scale);
|
|
196
|
+
const a = parts.length > 3 ? alphaChannel(parts[3]) : 1;
|
|
197
|
+
if (r === null || g === null || b === null || a === null)
|
|
198
|
+
return null;
|
|
199
|
+
return [r, g, b, a];
|
|
200
|
+
}
|
|
201
|
+
if (v.startsWith("hsl")) {
|
|
202
|
+
const body = v.slice(v.indexOf("(") + 1, -1);
|
|
203
|
+
const parts = body.split(",").map((p) => p.trim());
|
|
204
|
+
if (parts.length < 3)
|
|
205
|
+
return null;
|
|
206
|
+
const h = Number(parts[0].replace("deg", ""));
|
|
207
|
+
const s = Number(parts[1].replace("%", "")) / 100;
|
|
208
|
+
const l = Number(parts[2].replace("%", "")) / 100;
|
|
209
|
+
const a = parts.length > 3 ? alphaChannel(parts[3]) : 1;
|
|
210
|
+
if (![h, s, l].every(Number.isFinite) || a === null)
|
|
211
|
+
return null;
|
|
212
|
+
const [r, g, b] = hslToRgb(h, s, l);
|
|
213
|
+
return [r, g, b, a];
|
|
214
|
+
}
|
|
215
|
+
if (v === "transparent")
|
|
216
|
+
return [0, 0, 0, 0];
|
|
217
|
+
if (v === "currentcolor")
|
|
218
|
+
return null;
|
|
219
|
+
const packed = NAMED_RGB[v];
|
|
220
|
+
if (packed === undefined)
|
|
221
|
+
return null;
|
|
222
|
+
return [((packed >> 16) & 0xff) / 255, ((packed >> 8) & 0xff) / 255, (packed & 0xff) / 255, 1];
|
|
223
|
+
}
|
|
224
|
+
function hexToRgba(v) {
|
|
225
|
+
const h = v.slice(1);
|
|
226
|
+
if (h.length === 3 || h.length === 4) {
|
|
227
|
+
const r = parseInt(h[0] + h[0], 16);
|
|
228
|
+
const g = parseInt(h[1] + h[1], 16);
|
|
229
|
+
const b = parseInt(h[2] + h[2], 16);
|
|
230
|
+
const a = h.length === 4 ? parseInt(h[3] + h[3], 16) : 255;
|
|
231
|
+
return [r / 255, g / 255, b / 255, a / 255];
|
|
232
|
+
}
|
|
233
|
+
if (h.length === 6 || h.length === 8) {
|
|
234
|
+
const r = parseInt(h.slice(0, 2), 16);
|
|
235
|
+
const g = parseInt(h.slice(2, 4), 16);
|
|
236
|
+
const b = parseInt(h.slice(4, 6), 16);
|
|
237
|
+
const a = h.length === 8 ? parseInt(h.slice(6, 8), 16) : 255;
|
|
238
|
+
return [r / 255, g / 255, b / 255, a / 255];
|
|
239
|
+
}
|
|
240
|
+
return null;
|
|
241
|
+
}
|
|
242
|
+
function channel(token, scale) {
|
|
243
|
+
const n = Number(token.replace("%", ""));
|
|
244
|
+
if (!Number.isFinite(n))
|
|
245
|
+
return null;
|
|
246
|
+
return clamp01(n / scale);
|
|
247
|
+
}
|
|
248
|
+
function alphaChannel(token) {
|
|
249
|
+
const pct = token.endsWith("%");
|
|
250
|
+
const n = Number(token.replace("%", ""));
|
|
251
|
+
if (!Number.isFinite(n))
|
|
252
|
+
return null;
|
|
253
|
+
return clamp01(pct ? n / 100 : n);
|
|
254
|
+
}
|
|
255
|
+
/** Standard HSL → RGB (CSS Color 4 §7.1). h in degrees, s/l in [0,1]. */
|
|
256
|
+
function hslToRgb(h, s, l) {
|
|
257
|
+
const hue = ((h % 360) + 360) % 360;
|
|
258
|
+
const c = (1 - Math.abs(2 * l - 1)) * s;
|
|
259
|
+
const hp = hue / 60;
|
|
260
|
+
const x = c * (1 - Math.abs((hp % 2) - 1));
|
|
261
|
+
let r = 0;
|
|
262
|
+
let g = 0;
|
|
263
|
+
let b = 0;
|
|
264
|
+
if (hp < 1)
|
|
265
|
+
[r, g, b] = [c, x, 0];
|
|
266
|
+
else if (hp < 2)
|
|
267
|
+
[r, g, b] = [x, c, 0];
|
|
268
|
+
else if (hp < 3)
|
|
269
|
+
[r, g, b] = [0, c, x];
|
|
270
|
+
else if (hp < 4)
|
|
271
|
+
[r, g, b] = [0, x, c];
|
|
272
|
+
else if (hp < 5)
|
|
273
|
+
[r, g, b] = [x, 0, c];
|
|
274
|
+
else
|
|
275
|
+
[r, g, b] = [c, 0, x];
|
|
276
|
+
const m = l - c / 2;
|
|
277
|
+
return [clamp01(r + m), clamp01(g + m), clamp01(b + m)];
|
|
278
|
+
}
|
|
279
|
+
/** Component-wise sRGB lerp (§6.5 step 2). `t` may overshoot (springs) ;
|
|
280
|
+
* channels clamp back into [0, 1] after mixing. */
|
|
281
|
+
export function mixRgba(a, b, t) {
|
|
282
|
+
return [
|
|
283
|
+
clamp01(a[0] + t * (b[0] - a[0])),
|
|
284
|
+
clamp01(a[1] + t * (b[1] - a[1])),
|
|
285
|
+
clamp01(a[2] + t * (b[2] - a[2])),
|
|
286
|
+
clamp01(a[3] + t * (b[3] - a[3])),
|
|
287
|
+
];
|
|
288
|
+
}
|
|
289
|
+
/** Serialise RGBA back to `rgba()` form (§6.5 step 3). The output is
|
|
290
|
+
* always re-accepted by `parseCssColor` (integer channels, alpha with
|
|
291
|
+
* at most 4 decimals). */
|
|
292
|
+
export function serializeRgba(rgba) {
|
|
293
|
+
const r = Math.round(clamp01(rgba[0]) * 255);
|
|
294
|
+
const g = Math.round(clamp01(rgba[1]) * 255);
|
|
295
|
+
const b = Math.round(clamp01(rgba[2]) * 255);
|
|
296
|
+
// 4 decimals max so the alpha token matches the strict grammar.
|
|
297
|
+
const a = Math.round(clamp01(rgba[3]) * 10000) / 10000;
|
|
298
|
+
return `rgba(${r}, ${g}, ${b}, ${a})`;
|
|
299
|
+
}
|
|
300
|
+
function clamp01(n) {
|
|
301
|
+
return n < 0 ? 0 : n > 1 ? 1 : n;
|
|
302
|
+
}
|
|
303
|
+
//# sourceMappingURL=color-interp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"color-interp.js","sourceRoot":"","sources":["../../src/render/color-interp.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validate an untrusted colour value against the strict grammar above.
|
|
3
|
+
*
|
|
4
|
+
* Returns the validated string (trimmed ; named colours lowercased) or
|
|
5
|
+
* `null` on rejection. A `null` MUST be handled as "omit the style /
|
|
6
|
+
* use the primitive's safe default" — never interpolate the raw input.
|
|
7
|
+
*/
|
|
8
|
+
export declare function parseCssColor(value: unknown): string | null;
|
|
9
|
+
/**
|
|
10
|
+
* Diagnostic for a rejected value. Bastion R9 (ADR 001 §5.1) : the
|
|
11
|
+
* rejected VALUE is never logged nor forwarded — only `node.id` (RC#7,
|
|
12
|
+
* issue #34), the field name and a static reason. Routed through the
|
|
13
|
+
* structured diagnostics channel (events, no logs in `broadcast`).
|
|
14
|
+
*/
|
|
15
|
+
export declare function warnRejectedColor(field: string, nodeId?: string): void;
|
|
16
|
+
//# sourceMappingURL=css-color.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"css-color.d.ts","sourceRoot":"","sources":["../../src/render/css-color.ts"],"names":[],"mappings":"AAwFA;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAmC3D;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAMtE"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
// Strict CSS colour parser — the ONLY gate through which untrusted
|
|
2
|
+
// colour values (bundle props AND live LSDP deltas, see `resolveProps`
|
|
3
|
+
// in tree.tsx) may reach an inline CSS style.
|
|
4
|
+
//
|
|
5
|
+
// ADR 001 §6 RC#11 (CSS strict) + RC#12 (anti-ReDoS), threat model
|
|
6
|
+
// Bastion 2026-06-10, issue #35. Sites #30/#31/#33 must reuse this
|
|
7
|
+
// module — never re-implement colour validation locally.
|
|
8
|
+
//
|
|
9
|
+
// Accepted grammar (LSML 1.1 §6.5 colour forms, nothing more) :
|
|
10
|
+
// - hex : #RGB | #RGBA | #RRGGBB | #RRGGBBAA
|
|
11
|
+
// - rgb() : rgb(R, G, B) | rgba(R, G, B, A) — 0-255 or percentages
|
|
12
|
+
// - hsl() : hsl(H, S%, L%) | hsla(H, S%, L%, A)
|
|
13
|
+
// - named : canonical CSS named colours + `transparent` + `currentcolor`
|
|
14
|
+
// Anything else — including `url(`, `;`, `}`, `expression(`, var(),
|
|
15
|
+
// calc(), whitespace tricks — is REJECTED (null). Never passthrough.
|
|
16
|
+
//
|
|
17
|
+
// ── Linear-time justification (RC#12, written per Bastion) ──────────
|
|
18
|
+
// 1. Inputs longer than MAX_LEN (64) are rejected before any regex
|
|
19
|
+
// runs, so every step below operates on a bounded string.
|
|
20
|
+
// 2. The charset pre-scan is a single O(n) pass over one character
|
|
21
|
+
// class — it rejects `;`, `}`, `:`, `/`, quotes, backslashes and
|
|
22
|
+
// control characters outright, so no later step ever sees them.
|
|
23
|
+
// 3. Every regex is anchored (`^…$`) and built exclusively from
|
|
24
|
+
// literals, character classes and BOUNDED quantifiers ({m,n}, ?).
|
|
25
|
+
// There are no nested unbounded quantifiers ((a+)+ style), no
|
|
26
|
+
// overlapping alternations under a quantifier — i.e. no input can
|
|
27
|
+
// trigger super-linear backtracking. Combined with the 64-char cap,
|
|
28
|
+
// total work is O(64) per value regardless of payload shape.
|
|
29
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
30
|
+
import { emitDiagnostic } from "./diagnostics";
|
|
31
|
+
const MAX_LEN = 64;
|
|
32
|
+
// Single-pass charset allowlist. Only characters that can appear in
|
|
33
|
+
// the accepted grammar. Notably ABSENT : `;` `}` `{` `:` `/` `"` `'`
|
|
34
|
+
// `\` `<` `>` `-` and all control chars — the injection metacharacters.
|
|
35
|
+
const CHARSET_RE = /^[#a-zA-Z0-9(),.% ]{1,64}$/;
|
|
36
|
+
// hex — 3/4/6/8 hex digits. Alternation of fixed-width character-class
|
|
37
|
+
// runs : strictly linear.
|
|
38
|
+
const HEX_RE = /^#(?:[0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/;
|
|
39
|
+
// Number tokens. All quantifiers bounded ; `(?:\.\d{1,4})?` is an
|
|
40
|
+
// optional bounded group — one possible match per position, no
|
|
41
|
+
// ambiguity, no backtracking blow-up.
|
|
42
|
+
const NUM = String.raw `\d{1,3}(?:\.\d{1,4})?`; // 0 … 999.9999
|
|
43
|
+
const ALPHA = String.raw `(?:0|1|0?\.\d{1,4}|${NUM}%)`; // 0-1 or %
|
|
44
|
+
const SP = String.raw `[ ]{0,4}`; // bounded optional spaces
|
|
45
|
+
// rgb(R, G, B[, A]) — channels all plain numbers or all percentages
|
|
46
|
+
// are both accepted (range-checked numerically after the match).
|
|
47
|
+
const RGB_RE = new RegExp(`^rgba?\\(${SP}(${NUM})(%?)${SP},${SP}(${NUM})(%?)${SP},${SP}(${NUM})(%?)${SP}` +
|
|
48
|
+
`(?:,${SP}${ALPHA}${SP})?\\)$`);
|
|
49
|
+
// hsl(H[deg], S%, L%[, A])
|
|
50
|
+
const HSL_RE = new RegExp(`^hsla?\\(${SP}(${NUM})(?:deg)?${SP},${SP}(${NUM})%${SP},${SP}(${NUM})%${SP}` +
|
|
51
|
+
`(?:,${SP}${ALPHA}${SP})?\\)$`);
|
|
52
|
+
// Canonical CSS named colours (CSS Color 4 §6.1) + the two keywords
|
|
53
|
+
// that behave like colours in every site we render.
|
|
54
|
+
const NAMED = new Set(("aliceblue antiquewhite aqua aquamarine azure beige bisque black blanchedalmond blue " +
|
|
55
|
+
"blueviolet brown burlywood cadetblue chartreuse chocolate coral cornflowerblue cornsilk " +
|
|
56
|
+
"crimson cyan darkblue darkcyan darkgoldenrod darkgray darkgreen darkgrey darkkhaki " +
|
|
57
|
+
"darkmagenta darkolivegreen darkorange darkorchid darkred darksalmon darkseagreen " +
|
|
58
|
+
"darkslateblue darkslategray darkslategrey darkturquoise darkviolet deeppink deepskyblue " +
|
|
59
|
+
"dimgray dimgrey dodgerblue firebrick floralwhite forestgreen fuchsia gainsboro ghostwhite " +
|
|
60
|
+
"gold goldenrod gray green greenyellow grey honeydew hotpink indianred indigo ivory khaki " +
|
|
61
|
+
"lavender lavenderblush lawngreen lemonchiffon lightblue lightcoral lightcyan " +
|
|
62
|
+
"lightgoldenrodyellow lightgray lightgreen lightgrey lightpink lightsalmon lightseagreen " +
|
|
63
|
+
"lightskyblue lightslategray lightslategrey lightsteelblue lightyellow lime limegreen " +
|
|
64
|
+
"linen magenta maroon mediumaquamarine mediumblue mediumorchid mediumpurple " +
|
|
65
|
+
"mediumseagreen mediumslateblue mediumspringgreen mediumturquoise mediumvioletred " +
|
|
66
|
+
"midnightblue mintcream mistyrose moccasin navajowhite navy oldlace olive olivedrab " +
|
|
67
|
+
"orange orangered orchid palegoldenrod palegreen paleturquoise palevioletred papayawhip " +
|
|
68
|
+
"peachpuff peru pink plum powderblue purple rebeccapurple red rosybrown royalblue " +
|
|
69
|
+
"saddlebrown salmon sandybrown seagreen seashell sienna silver skyblue slateblue " +
|
|
70
|
+
"slategray slategrey snow springgreen steelblue tan teal thistle tomato turquoise violet " +
|
|
71
|
+
"wheat white whitesmoke yellow yellowgreen transparent currentcolor").split(" "));
|
|
72
|
+
/**
|
|
73
|
+
* Validate an untrusted colour value against the strict grammar above.
|
|
74
|
+
*
|
|
75
|
+
* Returns the validated string (trimmed ; named colours lowercased) or
|
|
76
|
+
* `null` on rejection. A `null` MUST be handled as "omit the style /
|
|
77
|
+
* use the primitive's safe default" — never interpolate the raw input.
|
|
78
|
+
*/
|
|
79
|
+
export function parseCssColor(value) {
|
|
80
|
+
if (typeof value !== "string")
|
|
81
|
+
return null;
|
|
82
|
+
const v = value.trim();
|
|
83
|
+
if (v.length === 0 || v.length > MAX_LEN)
|
|
84
|
+
return null;
|
|
85
|
+
// Contractual explicit rejects (Bastion RC#11) — redundant with the
|
|
86
|
+
// charset scan below, kept as belt-and-braces so the contract holds
|
|
87
|
+
// even if the grammar is ever extended.
|
|
88
|
+
const lower = v.toLowerCase();
|
|
89
|
+
if (lower.includes("url(") || v.includes(";") || v.includes("}"))
|
|
90
|
+
return null;
|
|
91
|
+
// Single-pass charset allowlist (kills every CSS metacharacter).
|
|
92
|
+
if (!CHARSET_RE.test(v))
|
|
93
|
+
return null;
|
|
94
|
+
if (v.startsWith("#"))
|
|
95
|
+
return HEX_RE.test(v) ? v : null;
|
|
96
|
+
if (lower.startsWith("rgb")) {
|
|
97
|
+
const m = RGB_RE.exec(lower);
|
|
98
|
+
if (!m)
|
|
99
|
+
return null;
|
|
100
|
+
// Range check : percent channels ≤ 100, plain channels ≤ 255, no mixing.
|
|
101
|
+
const pct = [m[2], m[4], m[6]];
|
|
102
|
+
if (!(pct.every((p) => p === "%") || pct.every((p) => p === "")))
|
|
103
|
+
return null;
|
|
104
|
+
const max = pct[0] === "%" ? 100 : 255;
|
|
105
|
+
for (const ch of [m[1], m[3], m[5]]) {
|
|
106
|
+
if (Number(ch) > max)
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
return lower;
|
|
110
|
+
}
|
|
111
|
+
if (lower.startsWith("hsl")) {
|
|
112
|
+
const m = HSL_RE.exec(lower);
|
|
113
|
+
if (!m)
|
|
114
|
+
return null;
|
|
115
|
+
if (Number(m[1]) > 360 || Number(m[2]) > 100 || Number(m[3]) > 100)
|
|
116
|
+
return null;
|
|
117
|
+
return lower;
|
|
118
|
+
}
|
|
119
|
+
return NAMED.has(lower) ? lower : null;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Diagnostic for a rejected value. Bastion R9 (ADR 001 §5.1) : the
|
|
123
|
+
* rejected VALUE is never logged nor forwarded — only `node.id` (RC#7,
|
|
124
|
+
* issue #34), the field name and a static reason. Routed through the
|
|
125
|
+
* structured diagnostics channel (events, no logs in `broadcast`).
|
|
126
|
+
*/
|
|
127
|
+
export function warnRejectedColor(field, nodeId) {
|
|
128
|
+
emitDiagnostic(nodeId, field, "rejected unsafe colour : not a strict hex/rgb()/hsl()/named colour");
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=css-color.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"css-color.js","sourceRoot":"","sources":["../../src/render/css-color.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/** Placeholder id for nodes that don't declare an `id`. */
|
|
2
|
+
export declare const ANON_NODE_ID = "<anon>";
|
|
3
|
+
export interface RenderDiagnostic {
|
|
4
|
+
/** `RenderNode.id` of the node the field belongs to (RC#7), or
|
|
5
|
+
* `ANON_NODE_ID` when the node has none. */
|
|
6
|
+
nodeId: string;
|
|
7
|
+
/** Name of the field/prop concerned (e.g. `text.colour`,
|
|
8
|
+
* `shape.paths.data`, `bindAnimate.opacity`). Never its value (R9). */
|
|
9
|
+
field: string;
|
|
10
|
+
/** Static reason — why the field was rejected or not rendered. */
|
|
11
|
+
reason: string;
|
|
12
|
+
}
|
|
13
|
+
export type DiagnosticHandler = (diagnostic: RenderDiagnostic) => void;
|
|
14
|
+
/**
|
|
15
|
+
* Register a diagnostics handler (one per `mount()`, plus tests).
|
|
16
|
+
* Returns the unregister function. Multiple concurrent mounts each
|
|
17
|
+
* receive every diagnostic — node ids are bundle-scoped, so a host
|
|
18
|
+
* running several mounts should disambiguate on its side.
|
|
19
|
+
*/
|
|
20
|
+
export declare function addDiagnosticsHandler(handler: DiagnosticHandler): () => void;
|
|
21
|
+
/**
|
|
22
|
+
* Emit one anti-drop diagnostic. `field` and `reason` MUST be static
|
|
23
|
+
* strings / field names — never interpolate a prop or leaf value (R9).
|
|
24
|
+
*/
|
|
25
|
+
export declare function emitDiagnostic(nodeId: string | undefined, field: string, reason: string): void;
|
|
26
|
+
//# sourceMappingURL=diagnostics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diagnostics.d.ts","sourceRoot":"","sources":["../../src/render/diagnostics.ts"],"names":[],"mappings":"AAqBA,2DAA2D;AAC3D,eAAO,MAAM,YAAY,WAAW,CAAC;AAErC,MAAM,WAAW,gBAAgB;IAC/B;iDAC6C;IAC7C,MAAM,EAAE,MAAM,CAAC;IACf;4EACwE;IACxE,KAAK,EAAE,MAAM,CAAC;IACd,kEAAkE;IAClE,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,iBAAiB,GAAG,CAAC,UAAU,EAAE,gBAAgB,KAAK,IAAI,CAAC;AAIvE;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,iBAAiB,GAAG,MAAM,IAAI,CAK5E;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAkB9F"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// Anti-silent-drop diagnostics channel (ADR 001 §3.4 D4, issue #34).
|
|
2
|
+
//
|
|
3
|
+
// Every render-side diagnostic — rejected colour/filter/path/typography
|
|
4
|
+
// value, unknown prop, unrendered spec'd field — flows through
|
|
5
|
+
// `emitDiagnostic`. The diagnostic is an EVENT, not a console.log :
|
|
6
|
+
// hosts subscribe via `MountOptions.onDiagnostic` (wired by `mount()`)
|
|
7
|
+
// and receive a structured `{ nodeId, field, reason }`. When no handler
|
|
8
|
+
// is registered, the runtime falls back to a DEV-only `console.warn`
|
|
9
|
+
// so authors still see drops during development — and `broadcast`
|
|
10
|
+
// builds stay silent on the console, per the CLAUDE.md "no logs in
|
|
11
|
+
// broadcast" rule.
|
|
12
|
+
//
|
|
13
|
+
// ── Hygiene contract (Bastion R9, ADR 001 §5.1) ─────────────────────
|
|
14
|
+
// A diagnostic NEVER carries the value of a leaf or a prop — only the
|
|
15
|
+
// node id, the field name and a STATIC reason string. Leaf values can
|
|
16
|
+
// hold sensitive on-air content ; they must not transit any diagnostic
|
|
17
|
+
// channel. Callers pass field names and literal reasons exclusively.
|
|
18
|
+
// The R9 sentinel test (r9-sentinel.test.tsx) enforces this end to end,
|
|
19
|
+
// and statically checks that `console.warn` only exists in this module.
|
|
20
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
21
|
+
/** Placeholder id for nodes that don't declare an `id`. */
|
|
22
|
+
export const ANON_NODE_ID = "<anon>";
|
|
23
|
+
const handlers = new Set();
|
|
24
|
+
/**
|
|
25
|
+
* Register a diagnostics handler (one per `mount()`, plus tests).
|
|
26
|
+
* Returns the unregister function. Multiple concurrent mounts each
|
|
27
|
+
* receive every diagnostic — node ids are bundle-scoped, so a host
|
|
28
|
+
* running several mounts should disambiguate on its side.
|
|
29
|
+
*/
|
|
30
|
+
export function addDiagnosticsHandler(handler) {
|
|
31
|
+
handlers.add(handler);
|
|
32
|
+
return () => {
|
|
33
|
+
handlers.delete(handler);
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Emit one anti-drop diagnostic. `field` and `reason` MUST be static
|
|
38
|
+
* strings / field names — never interpolate a prop or leaf value (R9).
|
|
39
|
+
*/
|
|
40
|
+
export function emitDiagnostic(nodeId, field, reason) {
|
|
41
|
+
const diagnostic = { nodeId: nodeId ?? ANON_NODE_ID, field, reason };
|
|
42
|
+
if (handlers.size > 0) {
|
|
43
|
+
for (const handler of handlers) {
|
|
44
|
+
try {
|
|
45
|
+
handler(diagnostic);
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
// A host handler that throws must never break the render path.
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
// DEV-only console fallback — broadcast builds log nothing.
|
|
54
|
+
if (import.meta.env.DEV) {
|
|
55
|
+
console.warn(`[lumencast] node "${diagnostic.nodeId}": field "${field}" ${reason} (value withheld per R9)`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=diagnostics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diagnostics.js","sourceRoot":"","sources":["../../src/render/diagnostics.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,EAAE;AACF,wEAAwE;AACxE,+DAA+D;AAC/D,oEAAoE;AACpE,uEAAuE;AACvE,wEAAwE;AACxE,qEAAqE;AACrE,kEAAkE;AAClE,mEAAmE;AACnE,mBAAmB;AACnB,EAAE;AACF,uEAAuE;AACvE,sEAAsE;AACtE,sEAAsE;AACtE,uEAAuE;AACvE,qEAAqE;AACrE,wEAAwE;AACxE,wEAAwE;AACxE,wEAAwE;AAExE,2DAA2D;AAC3D,MAAM,CAAC,MAAM,YAAY,GAAG,QAAQ,CAAC;AAerC,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAqB,CAAC;AAE9C;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB,CAAC,OAA0B;IAC9D,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACtB,OAAO,GAAG,EAAE;QACV,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC3B,CAAC,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,MAA0B,EAAE,KAAa,EAAE,MAAc;IACtF,MAAM,UAAU,GAAqB,EAAE,MAAM,EAAE,MAAM,IAAI,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IACvF,IAAI,QAAQ,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;QACtB,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,IAAI,CAAC;gBACH,OAAO,CAAC,UAAU,CAAC,CAAC;YACtB,CAAC;YAAC,MAAM,CAAC;gBACP,+DAA+D;YACjE,CAAC;QACH,CAAC;QACD,OAAO;IACT,CAAC;IACD,4DAA4D;IAC5D,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC;QACxB,OAAO,CAAC,IAAI,CACV,qBAAqB,UAAU,CAAC,MAAM,aAAa,KAAK,KAAK,MAAM,0BAA0B,CAC9F,CAAC;IACJ,CAAC;AACH,CAAC"}
|
package/dist/render/fill.d.ts
CHANGED
|
@@ -35,7 +35,19 @@ export declare function renderFill(fill: Fill): FillRenderResult;
|
|
|
35
35
|
/** Compile an array of Fill into a CSS `background-image` value usable
|
|
36
36
|
* on a `<div>` (frame backgrounds — non-SVG context). Returns the CSS
|
|
37
37
|
* string + opacity. Stops use percentages in CSS gradient syntax. */
|
|
38
|
-
export declare function backgroundsToCss(fills: Fill[]): CSSProperties;
|
|
39
|
-
/**
|
|
40
|
-
|
|
38
|
+
export declare function backgroundsToCss(fills: Fill[], nodeId?: string): CSSProperties;
|
|
39
|
+
/** Validate every colour carried by a Fill array through the strict
|
|
40
|
+
* parser (RC#11 — issue #30 contractual comment : SVG `fill`/`stroke`
|
|
41
|
+
* attributes and `<stop stop-color>` are injection sites too, since
|
|
42
|
+
* fills arrive from untrusted bundles AND live LSDP deltas). A fill
|
|
43
|
+
* whose solid colour — or ANY gradient stop colour — is rejected drops
|
|
44
|
+
* the whole layer with a diagnostic : never passthrough, never a
|
|
45
|
+
* half-built gradient. Returned fills carry canonicalised colours. */
|
|
46
|
+
export declare function sanitizeFills(fills: Fill[], field: string, nodeId?: string): Fill[];
|
|
47
|
+
/** Coerce loose JSON into a Fill array. Returns [] for non-arrays.
|
|
48
|
+
* A structurally-valid fill entry whose `kind` is not renderable by
|
|
49
|
+
* this runtime (e.g. `angular-gradient` / `diamond-gradient`, promoted
|
|
50
|
+
* to core by the LSML 1.2 RFC) is dropped WITH a diagnostic — never
|
|
51
|
+
* silently (ADR 001 §3.4, issue #34). */
|
|
52
|
+
export declare function parseFills(value: unknown, field?: string, nodeId?: string): Fill[];
|
|
41
53
|
//# sourceMappingURL=fill.d.ts.map
|
|
@@ -1 +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;
|
|
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;AAIzD,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,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,aAAa,CAM9E;AAsDD;;;;;;sEAMsE;AACtE,wBAAgB,aAAa,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,EAAE,CA2BnF;AAED;;;;yCAIyC;AACzC,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,EAAE,CAclF"}
|