@pixodesk/svg-animator-core 1.0.40 → 1.0.41
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 +58 -13
- package/dist/{internal-BZSJtt_h.d.ts → PxDocumentDiagnostic-COGEjBbg.d.cts} +74 -448
- package/dist/{internal-BZSJtt_h.d.cts → PxDocumentDiagnostic-COGEjBbg.d.ts} +74 -448
- package/dist/chunk-7ZO7PQKZ.min.js +1 -0
- package/dist/{chunk-PAE3NF2U.js → chunk-L6GJ6Y2M.js} +168 -567
- package/dist/chunk-L6GJ6Y2M.js.map +1 -0
- package/dist/index.cjs +206 -926
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +15 -15
- package/dist/index.d.ts +15 -15
- package/dist/index.js +84 -175
- package/dist/index.js.map +1 -1
- package/dist/index.min.cjs +1 -1
- package/dist/index.min.js +1 -1
- package/dist/internal.cjs +78 -78
- package/dist/internal.cjs.map +1 -1
- package/dist/internal.d.cts +378 -1
- package/dist/internal.d.ts +378 -1
- package/dist/internal.js +413 -34
- package/dist/internal.js.map +1 -1
- package/dist/internal.min.cjs +1 -1
- package/dist/internal.min.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-PAE3NF2U.js.map +0 -1
- package/dist/chunk-WIVGJ5YO.min.js +0 -1
package/dist/internal.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
|
-
COLOR_ATTR_NAMES,
|
|
3
|
-
CSS_ONLY_STYLE_PROPS,
|
|
4
|
-
DEFAULT_DURATION_MS,
|
|
5
|
-
DISALLOWED_SVG_TAGS_LOWER,
|
|
6
|
-
LOOP_JUMP_SHIFT_MS,
|
|
7
|
-
PCT_BASED_ATTR_NAMES,
|
|
8
2
|
PX_ANIM_ATTR_NAME,
|
|
9
3
|
PX_ANIM_SRC_ATTR_NAME,
|
|
4
|
+
PX_COLOR_ATTR_NAMES,
|
|
5
|
+
PX_CSS_ONLY_STYLE_PROPS,
|
|
6
|
+
PX_DEFAULT_DURATION_MS,
|
|
7
|
+
PX_DISALLOWED_SVG_TAGS_LOWER,
|
|
8
|
+
PX_LOOP_JUMP_SHIFT_MS,
|
|
9
|
+
PX_PCT_BASED_ATTR_NAMES,
|
|
10
|
+
PX_STYLE_ATTR_NAMES,
|
|
11
|
+
PX_TEXT_CONTENT_ATTR,
|
|
12
|
+
PX_TRANSFORM_FN_NAMES,
|
|
10
13
|
PX_UNKNOWN_KEY_ERROR,
|
|
11
|
-
STYLE_ATTR_NAMES,
|
|
12
|
-
TEXT_CONTENT_ATTR,
|
|
13
|
-
TRANSFORM_FN_NAMES,
|
|
14
14
|
bezierToSvgPath,
|
|
15
15
|
camelCaseToKebabWordIfNeeded,
|
|
16
16
|
clamp,
|
|
@@ -19,48 +19,427 @@ import {
|
|
|
19
19
|
createPathSampler,
|
|
20
20
|
cubicBezier,
|
|
21
21
|
deepClone,
|
|
22
|
-
|
|
23
|
-
diffInEffect,
|
|
22
|
+
describeSchema,
|
|
24
23
|
extendedPathForBrowser,
|
|
25
24
|
generateUniqueId,
|
|
26
25
|
interpolateValue,
|
|
27
|
-
isScrollTimeline,
|
|
28
26
|
kebabToCamelCaseWord,
|
|
29
|
-
|
|
30
|
-
|
|
27
|
+
keyframeEasing,
|
|
28
|
+
keyframeValue,
|
|
31
29
|
layoutGlyphTextChars,
|
|
32
30
|
materializeGlyphText,
|
|
33
31
|
materializeGlyphTextAlongPath,
|
|
34
32
|
materializeMotionPathInPropAnim,
|
|
35
33
|
mergeStaticTransformIntoAnimDef,
|
|
36
|
-
|
|
37
|
-
releaseLogProblems,
|
|
34
|
+
parseWireVersion,
|
|
38
35
|
reportDocumentDiagnostics,
|
|
39
36
|
reverseEasing,
|
|
40
37
|
sanitizeAttributeValue,
|
|
41
|
-
schemaFieldUniverse,
|
|
42
|
-
scrollOffsetProgress,
|
|
43
|
-
scrollPhaseInterval,
|
|
44
|
-
scrollResolveAxis,
|
|
45
|
-
scrollTotalDurationMs,
|
|
46
|
-
scrollViewProgress,
|
|
47
38
|
splitEasing,
|
|
48
39
|
subdivideCubicBezier,
|
|
49
40
|
toRGBA
|
|
50
|
-
} from "./chunk-
|
|
41
|
+
} from "./chunk-L6GJ6Y2M.js";
|
|
42
|
+
|
|
43
|
+
// src/effects/PlayerEffectsUtil.visualModel.ts
|
|
44
|
+
var IDENTITY = [1, 0, 0, 1, 0, 0];
|
|
45
|
+
function mul(m, n) {
|
|
46
|
+
return [
|
|
47
|
+
m[0] * n[0] + m[2] * n[1],
|
|
48
|
+
m[1] * n[0] + m[3] * n[1],
|
|
49
|
+
m[0] * n[2] + m[2] * n[3],
|
|
50
|
+
m[1] * n[2] + m[3] * n[3],
|
|
51
|
+
m[0] * n[4] + m[2] * n[5] + m[4],
|
|
52
|
+
m[1] * n[4] + m[3] * n[5] + m[5]
|
|
53
|
+
];
|
|
54
|
+
}
|
|
55
|
+
var translateM = (x, y) => [1, 0, 0, 1, x, y];
|
|
56
|
+
var scaleM = (sx, sy) => [sx, 0, 0, sy, 0, 0];
|
|
57
|
+
function rotateM(deg) {
|
|
58
|
+
const r = deg * Math.PI / 180;
|
|
59
|
+
return [Math.cos(r), Math.sin(r), -Math.sin(r), Math.cos(r), 0, 0];
|
|
60
|
+
}
|
|
61
|
+
var skewXM = (deg) => [1, 0, Math.tan(deg * Math.PI / 180), 1, 0, 0];
|
|
62
|
+
var skewYM = (deg) => [1, Math.tan(deg * Math.PI / 180), 0, 1, 0, 0];
|
|
63
|
+
function parseTransformString(s) {
|
|
64
|
+
let m = IDENTITY;
|
|
65
|
+
const re = /(translate|rotate|scale|matrix|skewX|skewY)\(([^)]*)\)/g;
|
|
66
|
+
let hit;
|
|
67
|
+
while (hit = re.exec(s)) {
|
|
68
|
+
const fn = hit[1];
|
|
69
|
+
const a = hit[2].split(/[\s,]+/).filter(Boolean).map(Number);
|
|
70
|
+
if (fn === "translate") m = mul(m, translateM(a[0] || 0, a[1] || 0));
|
|
71
|
+
else if (fn === "scale") m = mul(m, scaleM(a[0], a.length > 1 ? a[1] : a[0]));
|
|
72
|
+
else if (fn === "rotate") m = mul(m, rotateM(a[0]));
|
|
73
|
+
else if (fn === "skewX") m = mul(m, skewXM(a[0]));
|
|
74
|
+
else if (fn === "skewY") m = mul(m, skewYM(a[0]));
|
|
75
|
+
else if (fn === "matrix") m = mul(m, [a[0], a[1], a[2], a[3], a[4], a[5]]);
|
|
76
|
+
}
|
|
77
|
+
return m;
|
|
78
|
+
}
|
|
79
|
+
function partsToMatrix(p) {
|
|
80
|
+
let m = IDENTITY;
|
|
81
|
+
if (p.translate) m = mul(m, translateM(p.translate[0], p.translate[1]));
|
|
82
|
+
const pivot = p.origin && (p.rotate !== void 0 || p.scale);
|
|
83
|
+
if (pivot) m = mul(m, translateM(p.origin[0], p.origin[1]));
|
|
84
|
+
if (p.rotate !== void 0) m = mul(m, rotateM(p.rotate));
|
|
85
|
+
if (p.scale) m = mul(m, scaleM(p.scale[0], p.scale[1]));
|
|
86
|
+
if (pivot) m = mul(m, translateM(-p.origin[0], -p.origin[1]));
|
|
87
|
+
return m;
|
|
88
|
+
}
|
|
89
|
+
function lerp(a, b, f) {
|
|
90
|
+
return a + (b - a) * f;
|
|
91
|
+
}
|
|
92
|
+
function interpParts(kfs, t) {
|
|
93
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
94
|
+
if (!kfs.length) return {};
|
|
95
|
+
if (t <= ((_a = kfs[0].time) != null ? _a : 0)) return kfs[0].value || {};
|
|
96
|
+
if (t >= ((_b = kfs[kfs.length - 1].time) != null ? _b : 0)) return kfs[kfs.length - 1].value || {};
|
|
97
|
+
let i = 0;
|
|
98
|
+
while (i < kfs.length - 1 && ((_c = kfs[i + 1].time) != null ? _c : 0) < t) i++;
|
|
99
|
+
const a = kfs[i], b = kfs[i + 1];
|
|
100
|
+
const f = (t - ((_d = a.time) != null ? _d : 0)) / (((_e = b.time) != null ? _e : 0) - ((_f = a.time) != null ? _f : 0) || 1);
|
|
101
|
+
const va = a.value || {}, vb = b.value || {};
|
|
102
|
+
const out = {};
|
|
103
|
+
if (va.translate && vb.translate) out.translate = [lerp(va.translate[0], vb.translate[0], f), lerp(va.translate[1], vb.translate[1], f)];
|
|
104
|
+
else out.translate = va.translate || vb.translate;
|
|
105
|
+
if (va.rotate !== void 0 && vb.rotate !== void 0) out.rotate = lerp(va.rotate, vb.rotate, f);
|
|
106
|
+
else out.rotate = (_g = va.rotate) != null ? _g : vb.rotate;
|
|
107
|
+
if (va.scale && vb.scale) out.scale = [lerp(va.scale[0], vb.scale[0], f), lerp(va.scale[1], vb.scale[1], f)];
|
|
108
|
+
else out.scale = va.scale || vb.scale;
|
|
109
|
+
out.origin = va.origin || vb.origin;
|
|
110
|
+
return out;
|
|
111
|
+
}
|
|
112
|
+
function evalTransformValue(v, t) {
|
|
113
|
+
if (v === void 0 || v === null) return IDENTITY;
|
|
114
|
+
if (typeof v === "string") return parseTransformString(v);
|
|
115
|
+
if (v.keyframes) return partsToMatrix(interpParts(v.keyframes, t));
|
|
116
|
+
if (v.value) return partsToMatrix(v.value);
|
|
117
|
+
if (typeof v === "object" && !Array.isArray(v)) return partsToMatrix(v);
|
|
118
|
+
return IDENTITY;
|
|
119
|
+
}
|
|
120
|
+
function nodeMatrix(node, t) {
|
|
121
|
+
if (node.animate && node.animate.transform) return evalTransformValue(node.animate.transform, t);
|
|
122
|
+
if (node.transform !== void 0) return evalTransformValue(node.transform, t);
|
|
123
|
+
return IDENTITY;
|
|
124
|
+
}
|
|
125
|
+
function evalScalar(animated, staticVal, fallback, t) {
|
|
126
|
+
var _a, _b, _c, _d, _e, _f;
|
|
127
|
+
if (animated && animated.keyframes && animated.keyframes.length) {
|
|
128
|
+
const kfs = animated.keyframes;
|
|
129
|
+
if (t <= ((_a = kfs[0].time) != null ? _a : 0)) return kfs[0].value;
|
|
130
|
+
if (t >= ((_b = kfs[kfs.length - 1].time) != null ? _b : 0)) return kfs[kfs.length - 1].value;
|
|
131
|
+
let i = 0;
|
|
132
|
+
while (i < kfs.length - 1 && ((_c = kfs[i + 1].time) != null ? _c : 0) < t) i++;
|
|
133
|
+
const a = kfs[i], b = kfs[i + 1];
|
|
134
|
+
const f = (t - ((_d = a.time) != null ? _d : 0)) / (((_e = b.time) != null ? _e : 0) - ((_f = a.time) != null ? _f : 0) || 1);
|
|
135
|
+
return lerp(a.value, b.value, f);
|
|
136
|
+
}
|
|
137
|
+
return staticVal !== void 0 ? Number(staticVal) : fallback;
|
|
138
|
+
}
|
|
139
|
+
var CONTAINER_TYPES = /* @__PURE__ */ new Set(["svg", "g", "symbol"]);
|
|
140
|
+
var SKIP_TYPES = /* @__PURE__ */ new Set(["defs", "mask", "clipPath", "title"]);
|
|
141
|
+
function buildIdMap(node, map) {
|
|
142
|
+
var _a;
|
|
143
|
+
if (typeof node.id === "string") map.set(node.id, node);
|
|
144
|
+
(_a = node.children) == null ? void 0 : _a.forEach((c) => buildIdMap(c, map));
|
|
145
|
+
}
|
|
146
|
+
function num(v) {
|
|
147
|
+
return v === void 0 || v === null ? 0 : Number(v);
|
|
148
|
+
}
|
|
149
|
+
function round(n) {
|
|
150
|
+
return Math.round(n * 100) / 100 + 0;
|
|
151
|
+
}
|
|
152
|
+
function geomKey(node) {
|
|
153
|
+
var _a;
|
|
154
|
+
switch (node.type) {
|
|
155
|
+
case "rect":
|
|
156
|
+
return num(node.width) + "," + num(node.height) + "," + num(node.x) + "," + num(node.y);
|
|
157
|
+
case "ellipse":
|
|
158
|
+
return num(node.rx) + "," + num(node.ry) + "," + num(node.cx) + "," + num(node.cy);
|
|
159
|
+
case "circle":
|
|
160
|
+
return num(node.r) + "," + num(node.cx) + "," + num(node.cy);
|
|
161
|
+
case "path":
|
|
162
|
+
return String((_a = node.d) != null ? _a : "");
|
|
163
|
+
default:
|
|
164
|
+
return "";
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
function describePrimitive(node, m, t) {
|
|
168
|
+
var _a, _b, _c, _d, _e;
|
|
169
|
+
const fill = (_a = node.fill) != null ? _a : "";
|
|
170
|
+
const stroke = (_b = node.stroke) != null ? _b : "";
|
|
171
|
+
const sw = (_d = (_c = node["stroke-width"]) != null ? _c : node.strokeWidth) != null ? _d : "";
|
|
172
|
+
const opacity = round(evalScalar((_e = node.animate) == null ? void 0 : _e.opacity, node.opacity, 1, t));
|
|
173
|
+
const masked = node.mask ? 1 : 0;
|
|
174
|
+
const mat = m.map(round).join(",");
|
|
175
|
+
return node.type + "|" + geomKey(node) + "|[" + mat + "]|f:" + fill + "|s:" + stroke + "|sw:" + (num(sw) || "") + "|o:" + opacity + "|m:" + masked;
|
|
176
|
+
}
|
|
177
|
+
function flatten(node, parent, t, idMap, out) {
|
|
178
|
+
var _a;
|
|
179
|
+
const type = node.type || "";
|
|
180
|
+
if (SKIP_TYPES.has(type)) return;
|
|
181
|
+
const m = mul(parent, nodeMatrix(node, t));
|
|
182
|
+
if (type === "use") {
|
|
183
|
+
const targetId = typeof node.href === "string" ? node.href.replace(/^#/, "") : "";
|
|
184
|
+
const target = idMap.get(targetId);
|
|
185
|
+
const useM = mul(m, translateM(num(node.x), num(node.y)));
|
|
186
|
+
if (target) flatten(target, useM, t, idMap, out);
|
|
187
|
+
else out.push("UNRESOLVED_USE:#" + targetId);
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
if (CONTAINER_TYPES.has(type)) {
|
|
191
|
+
(_a = node.children) == null ? void 0 : _a.forEach((c) => flatten(c, m, t, idMap, out));
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
out.push(describePrimitive(node, m, t));
|
|
195
|
+
}
|
|
196
|
+
function collectSampleTimes(node, into) {
|
|
197
|
+
var _a;
|
|
198
|
+
into.add(0);
|
|
199
|
+
const scanAnim = (anim) => {
|
|
200
|
+
var _a2;
|
|
201
|
+
if (!anim || typeof anim !== "object") return;
|
|
202
|
+
for (const key of Object.keys(anim)) {
|
|
203
|
+
const kfs = (_a2 = anim[key]) == null ? void 0 : _a2.keyframes;
|
|
204
|
+
if (Array.isArray(kfs)) kfs.forEach((kf) => {
|
|
205
|
+
var _a3;
|
|
206
|
+
return into.add((_a3 = kf.time) != null ? _a3 : 0);
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
};
|
|
210
|
+
scanAnim(node.animate);
|
|
211
|
+
if (node.transform && typeof node.transform === "object" && node.transform.keyframes) {
|
|
212
|
+
node.transform.keyframes.forEach((kf) => {
|
|
213
|
+
var _a2;
|
|
214
|
+
return into.add((_a2 = kf.time) != null ? _a2 : 0);
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
(_a = node.children) == null ? void 0 : _a.forEach((c) => collectSampleTimes(c, into));
|
|
218
|
+
}
|
|
219
|
+
function visualModelAt(root, t) {
|
|
220
|
+
const idMap = /* @__PURE__ */ new Map();
|
|
221
|
+
buildIdMap(root, idMap);
|
|
222
|
+
const out = [];
|
|
223
|
+
flatten(root, IDENTITY, t, idMap, out);
|
|
224
|
+
return out.sort();
|
|
225
|
+
}
|
|
226
|
+
function diffInEffect(a, b) {
|
|
227
|
+
const times = /* @__PURE__ */ new Set();
|
|
228
|
+
collectSampleTimes(a, times);
|
|
229
|
+
collectSampleTimes(b, times);
|
|
230
|
+
const diffs = [];
|
|
231
|
+
for (const t of Array.from(times).sort((x, y) => x - y)) {
|
|
232
|
+
const ma = visualModelAt(a, t);
|
|
233
|
+
const mb = visualModelAt(b, t);
|
|
234
|
+
const onlyInA = subtractMultiset(ma, mb);
|
|
235
|
+
const onlyInB = subtractMultiset(mb, ma);
|
|
236
|
+
if (onlyInA.length || onlyInB.length) diffs.push({ time: t, onlyInA, onlyInB });
|
|
237
|
+
}
|
|
238
|
+
return diffs;
|
|
239
|
+
}
|
|
240
|
+
function subtractMultiset(a, b) {
|
|
241
|
+
const counts = /* @__PURE__ */ new Map();
|
|
242
|
+
for (const x of b) counts.set(x, (counts.get(x) || 0) + 1);
|
|
243
|
+
const extra = [];
|
|
244
|
+
for (const x of a) {
|
|
245
|
+
const c = counts.get(x) || 0;
|
|
246
|
+
if (c > 0) counts.set(x, c - 1);
|
|
247
|
+
else extra.push(x);
|
|
248
|
+
}
|
|
249
|
+
return extra;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// src/playback/PxScrollMath.ts
|
|
253
|
+
function isScrollTimeline(config) {
|
|
254
|
+
return (config == null ? void 0 : config.timelineSource) === "scroll";
|
|
255
|
+
}
|
|
256
|
+
function scrollTotalDurationMs(config) {
|
|
257
|
+
const duration = typeof (config == null ? void 0 : config.duration) === "number" && config.duration > 0 ? config.duration : PX_DEFAULT_DURATION_MS;
|
|
258
|
+
const iterations = typeof (config == null ? void 0 : config.iterations) === "number" && config.iterations > 0 ? config.iterations : 1;
|
|
259
|
+
return duration * iterations;
|
|
260
|
+
}
|
|
261
|
+
function scrollPhaseInterval(phase, subjectSize, scrollportSize) {
|
|
262
|
+
const s = subjectSize, vp = scrollportSize;
|
|
263
|
+
switch (phase) {
|
|
264
|
+
case "cover":
|
|
265
|
+
return [0, s + vp];
|
|
266
|
+
case "entry":
|
|
267
|
+
return [0, Math.min(s, vp)];
|
|
268
|
+
case "contain":
|
|
269
|
+
return [Math.min(s, vp), Math.max(s, vp)];
|
|
270
|
+
case "exit":
|
|
271
|
+
return [Math.max(s, vp), s + vp];
|
|
272
|
+
case "entry-crossing":
|
|
273
|
+
return [0, s];
|
|
274
|
+
case "exit-crossing":
|
|
275
|
+
return [vp, s + vp];
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
var DEFAULT_PHASE = "cover";
|
|
279
|
+
function resolveRangePointU(point, defaultFraction, subjectSize, scrollportSize) {
|
|
280
|
+
var _a;
|
|
281
|
+
const [u0, u1] = scrollPhaseInterval((_a = point == null ? void 0 : point.phase) != null ? _a : DEFAULT_PHASE, subjectSize, scrollportSize);
|
|
282
|
+
const fraction = typeof (point == null ? void 0 : point.fraction) === "number" ? point.fraction : defaultFraction;
|
|
283
|
+
return u0 + fraction * (u1 - u0);
|
|
284
|
+
}
|
|
285
|
+
function scrollViewProgress(subjectStart, subjectSize, scrollportSize, range) {
|
|
286
|
+
const u = scrollportSize - subjectStart;
|
|
287
|
+
const uStart = resolveRangePointU(range == null ? void 0 : range.start, 0, subjectSize, scrollportSize);
|
|
288
|
+
const uEnd = resolveRangePointU(range == null ? void 0 : range.end, 1, subjectSize, scrollportSize);
|
|
289
|
+
if (uEnd <= uStart) return u >= uEnd ? 1 : 0;
|
|
290
|
+
return clamp((u - uStart) / (uEnd - uStart), 0, 1);
|
|
291
|
+
}
|
|
292
|
+
function scrollOffsetProgress(offset, maxOffset, range) {
|
|
293
|
+
var _a, _b;
|
|
294
|
+
const raw = maxOffset > 0 ? clamp(offset / maxOffset, 0, 1) : 1;
|
|
295
|
+
const start = typeof ((_a = range == null ? void 0 : range.start) == null ? void 0 : _a.fraction) === "number" ? range.start.fraction : 0;
|
|
296
|
+
const end = typeof ((_b = range == null ? void 0 : range.end) == null ? void 0 : _b.fraction) === "number" ? range.end.fraction : 1;
|
|
297
|
+
if (end <= start) return raw >= end ? 1 : 0;
|
|
298
|
+
return clamp((raw - start) / (end - start), 0, 1);
|
|
299
|
+
}
|
|
300
|
+
function scrollResolveAxis(axis, writingMode) {
|
|
301
|
+
const a = axis != null ? axis : "block";
|
|
302
|
+
if (a === "x" || a === "y") return a;
|
|
303
|
+
const vertical = !!writingMode && writingMode.startsWith("vertical");
|
|
304
|
+
if (a === "inline") return vertical ? "y" : "x";
|
|
305
|
+
return vertical ? "x" : "y";
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// src/version/PxSchemaFieldUniverse.ts
|
|
309
|
+
function schemaFieldUniverse(root) {
|
|
310
|
+
const fields = /* @__PURE__ */ new Set();
|
|
311
|
+
const enumerated = /* @__PURE__ */ new Set();
|
|
312
|
+
const queue = [{ schema: root, path: "" }];
|
|
313
|
+
while (queue.length) {
|
|
314
|
+
const { schema, path } = queue.shift();
|
|
315
|
+
const d = describeSchema(schema);
|
|
316
|
+
switch (d.kind) {
|
|
317
|
+
case "shape": {
|
|
318
|
+
if (enumerated.has(schema)) break;
|
|
319
|
+
enumerated.add(schema);
|
|
320
|
+
for (const key of Object.keys(d.shape)) {
|
|
321
|
+
const id = path ? path + "." + key : key;
|
|
322
|
+
fields.add(id);
|
|
323
|
+
queue.push({ schema: d.shape[key], path: id });
|
|
324
|
+
}
|
|
325
|
+
if (d.openValue) queue.push({ schema: d.openValue, path: path + "{*}" });
|
|
326
|
+
break;
|
|
327
|
+
}
|
|
328
|
+
case "optional":
|
|
329
|
+
queue.push({ schema: d.inner, path });
|
|
330
|
+
break;
|
|
331
|
+
case "array":
|
|
332
|
+
queue.push({ schema: d.item, path: path + "[]" });
|
|
333
|
+
break;
|
|
334
|
+
case "lazy":
|
|
335
|
+
queue.push({ schema: d.resolved, path });
|
|
336
|
+
break;
|
|
337
|
+
case "record":
|
|
338
|
+
queue.push({ schema: d.value, path: path + "{*}" });
|
|
339
|
+
break;
|
|
340
|
+
case "union":
|
|
341
|
+
d.members.forEach((member, i) => queue.push({ schema: member, path: path + "|" + i }));
|
|
342
|
+
break;
|
|
343
|
+
case "discriminatedUnion":
|
|
344
|
+
for (const member of d.members) queue.push({ schema: member, path: path + "|" + discriminantOf(member, d.key) });
|
|
345
|
+
break;
|
|
346
|
+
default:
|
|
347
|
+
break;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
return [...fields].sort();
|
|
351
|
+
}
|
|
352
|
+
function discriminantOf(member, key) {
|
|
353
|
+
const d = describeSchema(member);
|
|
354
|
+
if (d.kind !== "shape") return "?";
|
|
355
|
+
const keySchema = d.shape[key];
|
|
356
|
+
if (keySchema === void 0) return "?";
|
|
357
|
+
const kd = describeSchema(keySchema);
|
|
358
|
+
return String((kd.kind === "optional" ? kd.inner : keySchema)._default);
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// src/version/PxSchemaRelease.ts
|
|
362
|
+
function diffFieldUniverse(previous, current) {
|
|
363
|
+
const prev = new Set(previous);
|
|
364
|
+
const cur = new Set(current);
|
|
365
|
+
return {
|
|
366
|
+
added: current.filter((k) => !prev.has(k)).sort(),
|
|
367
|
+
removed: previous.filter((k) => !cur.has(k)).sort()
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
function planSchemaRelease(p) {
|
|
371
|
+
const changed = p.added.length > 0 || p.removed.length > 0;
|
|
372
|
+
const last = parseWireVersion(p.lastReleased);
|
|
373
|
+
const declared = parseWireVersion(p.declared);
|
|
374
|
+
if (!last || !declared) return { changed, refuse: "Unparseable version: " + p.lastReleased + " / " + p.declared + "." };
|
|
375
|
+
const requiredVersion = last.a + "." + (last.b + 1);
|
|
376
|
+
if (!changed) {
|
|
377
|
+
if (declared.b === last.b && declared.a === last.a) return { changed };
|
|
378
|
+
const step2 = p.steps.find((s) => s.to === p.declared);
|
|
379
|
+
return step2 ? { changed, requiredVersion: p.declared } : { changed, refuse: "The version moved to " + p.declared + " with no key change and no step explaining it." };
|
|
380
|
+
}
|
|
381
|
+
const requiredKind = p.removed.length ? "converted" /* converted */ : "additive" /* additive */;
|
|
382
|
+
const summary = p.added.length + " key(s) added, " + p.removed.length + " removed";
|
|
383
|
+
if (declared.a !== last.a || declared.b !== last.b + 1) {
|
|
384
|
+
return {
|
|
385
|
+
changed,
|
|
386
|
+
requiredKind,
|
|
387
|
+
requiredVersion,
|
|
388
|
+
refuse: "The player schema changed (" + summary + ") but PX_WIRE_SCHEMA_VERSION is " + p.declared + ". Set it to " + requiredVersion + " and add the PX_WIRE_STEPS entry."
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
const step = p.steps.find((s) => s.to === p.declared);
|
|
392
|
+
if (!step) {
|
|
393
|
+
return { changed, requiredKind, requiredVersion, refuse: "No PX_WIRE_STEPS entry reaches " + p.declared + "." };
|
|
394
|
+
}
|
|
395
|
+
if (requiredKind === "converted" /* converted */ && step.kind !== "converted" /* converted */) {
|
|
396
|
+
return {
|
|
397
|
+
changed,
|
|
398
|
+
requiredKind,
|
|
399
|
+
requiredVersion,
|
|
400
|
+
refuse: "Keys were REMOVED (" + p.removed.join(", ") + "), which is never additive \u2014 the " + p.declared + " step must be `converted`, with an up()."
|
|
401
|
+
};
|
|
402
|
+
}
|
|
403
|
+
return { changed, requiredKind, requiredVersion };
|
|
404
|
+
}
|
|
405
|
+
function releaseLogProblems(releases, steps, declared, baseline) {
|
|
406
|
+
const problems = [];
|
|
407
|
+
if (!releases.length) return ["The release log is empty."];
|
|
408
|
+
if (!releases[0].baseline || releases[0].version !== baseline) {
|
|
409
|
+
problems.push("The first release must be the baseline " + baseline + ".");
|
|
410
|
+
}
|
|
411
|
+
for (let i = 1; i < releases.length; i++) {
|
|
412
|
+
const prev = parseWireVersion(releases[i - 1].version);
|
|
413
|
+
const cur = parseWireVersion(releases[i].version);
|
|
414
|
+
if (!prev || !cur || cur.a !== prev.a || cur.b !== prev.b + 1) {
|
|
415
|
+
problems.push("Release " + releases[i].version + " does not follow " + releases[i - 1].version + " by one `b` step.");
|
|
416
|
+
}
|
|
417
|
+
if (releases[i].date < releases[i - 1].date) problems.push("Release " + releases[i].version + " is dated before its predecessor.");
|
|
418
|
+
const step = steps.find((s) => s.to === releases[i].version);
|
|
419
|
+
if (!step) problems.push("Release " + releases[i].version + " has no PX_WIRE_STEPS entry.");
|
|
420
|
+
else if (releases[i].removed.length && step.kind !== "converted" /* converted */) {
|
|
421
|
+
problems.push("Release " + releases[i].version + " removed keys, but its step is not `converted`.");
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
const latest = releases[releases.length - 1].version;
|
|
425
|
+
if (latest !== declared) {
|
|
426
|
+
problems.push("PX_WIRE_SCHEMA_VERSION is " + declared + " but the last release record is " + latest + " \u2014 a bump needs its changelog entry (run scripts/schema-release.mjs --apply).");
|
|
427
|
+
}
|
|
428
|
+
return problems;
|
|
429
|
+
}
|
|
51
430
|
export {
|
|
52
|
-
COLOR_ATTR_NAMES,
|
|
53
|
-
CSS_ONLY_STYLE_PROPS,
|
|
54
|
-
DEFAULT_DURATION_MS,
|
|
55
|
-
DISALLOWED_SVG_TAGS_LOWER,
|
|
56
|
-
LOOP_JUMP_SHIFT_MS,
|
|
57
|
-
PCT_BASED_ATTR_NAMES,
|
|
58
431
|
PX_ANIM_ATTR_NAME,
|
|
59
432
|
PX_ANIM_SRC_ATTR_NAME,
|
|
433
|
+
PX_COLOR_ATTR_NAMES,
|
|
434
|
+
PX_CSS_ONLY_STYLE_PROPS,
|
|
435
|
+
PX_DEFAULT_DURATION_MS,
|
|
436
|
+
PX_DISALLOWED_SVG_TAGS_LOWER,
|
|
437
|
+
PX_LOOP_JUMP_SHIFT_MS,
|
|
438
|
+
PX_PCT_BASED_ATTR_NAMES,
|
|
439
|
+
PX_STYLE_ATTR_NAMES,
|
|
440
|
+
PX_TEXT_CONTENT_ATTR,
|
|
441
|
+
PX_TRANSFORM_FN_NAMES,
|
|
60
442
|
PX_UNKNOWN_KEY_ERROR,
|
|
61
|
-
STYLE_ATTR_NAMES,
|
|
62
|
-
TEXT_CONTENT_ATTR,
|
|
63
|
-
TRANSFORM_FN_NAMES,
|
|
64
443
|
bezierToSvgPath,
|
|
65
444
|
camelCaseToKebabWordIfNeeded,
|
|
66
445
|
clamp,
|
|
@@ -76,8 +455,8 @@ export {
|
|
|
76
455
|
interpolateValue,
|
|
77
456
|
isScrollTimeline,
|
|
78
457
|
kebabToCamelCaseWord,
|
|
79
|
-
|
|
80
|
-
|
|
458
|
+
keyframeEasing,
|
|
459
|
+
keyframeValue,
|
|
81
460
|
layoutGlyphTextChars,
|
|
82
461
|
materializeGlyphText,
|
|
83
462
|
materializeGlyphTextAlongPath,
|
package/dist/internal.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/effects/PlayerEffectsUtil.visualModel.ts","../src/playback/PxScrollMath.ts","../src/version/PxSchemaFieldUniverse.ts","../src/version/PxSchemaRelease.ts"],"sourcesContent":["/*---------------------------------------------------------------------------------------\n * Copyright (c) Pixodesk LTD.\n * Licensed under the MIT License. See the LICENSE file in the project root for details.\n *---------------------------------------------------------------------------------------*/\n\n\n/**\n * \"Equal-in-effect\" comparator for SVGA node trees.\n *\n * Two trees can render identically while differing structurally — extra `<g>`\n * wrappers, different ids, `<use>` clones vs inline copies, a transform expressed\n * as a baked string vs a parts record. This module reduces a tree to what is\n * actually painted: every drawable leaf, with its CUMULATIVE transform matrix\n * (resolved at a given time) and key visual attributes. Comparing those leaf\n * sets ignores representation and catches genuine visual differences.\n *\n * It is a deterministic function applied identically to both trees, so equal\n * inputs (in effect) yield equal output regardless of how each was encoded.\n *\n * Dependency-free on purpose (mirrors the applier's isolation). Scope: the node\n * types and transform forms the player-effects / heavy serializers emit. Color\n * animation is not interpolated — leaves are compared at keyframe instants where\n * sampled values are exact.\n */\n\ntype Mat = [number, number, number, number, number, number];\n\ninterface VmNode {\n type?: string;\n children?: Array<VmNode>;\n [attr: string]: any;\n}\n\n\n// ─────────────────────────────────────────────────────────────────────────────\n// MATRIX MATH (2x3 affine, SVG order: [a b c d e f])\n// ─────────────────────────────────────────────────────────────────────────────\n\nconst IDENTITY: Mat = [1, 0, 0, 1, 0, 0];\n\nfunction mul(m: Mat, n: Mat): Mat {\n return [\n m[0] * n[0] + m[2] * n[1],\n m[1] * n[0] + m[3] * n[1],\n m[0] * n[2] + m[2] * n[3],\n m[1] * n[2] + m[3] * n[3],\n m[0] * n[4] + m[2] * n[5] + m[4],\n m[1] * n[4] + m[3] * n[5] + m[5],\n ];\n}\n\nconst translateM = (x: number, y: number): Mat => [1, 0, 0, 1, x, y];\nconst scaleM = (sx: number, sy: number): Mat => [sx, 0, 0, sy, 0, 0];\nfunction rotateM(deg: number): Mat {\n const r = (deg * Math.PI) / 180;\n return [Math.cos(r), Math.sin(r), -Math.sin(r), Math.cos(r), 0, 0];\n}\nconst skewXM = (deg: number): Mat => [1, 0, Math.tan((deg * Math.PI) / 180), 1, 0, 0];\nconst skewYM = (deg: number): Mat => [1, Math.tan((deg * Math.PI) / 180), 0, 1, 0, 0];\n\n\n// ─────────────────────────────────────────────────────────────────────────────\n// TRANSFORM EVALUATION\n// ─────────────────────────────────────────────────────────────────────────────\n\n/** Parses an SVG transform string (\"translate(..)rotate(..)…\") into a matrix. */\nfunction parseTransformString(s: string): Mat {\n let m = IDENTITY;\n const re = /(translate|rotate|scale|matrix|skewX|skewY)\\(([^)]*)\\)/g;\n let hit: RegExpExecArray | null;\n while ((hit = re.exec(s))) {\n const fn = hit[1];\n const a = hit[2].split(/[\\s,]+/).filter(Boolean).map(Number);\n if (fn === 'translate') m = mul(m, translateM(a[0] || 0, a[1] || 0));\n else if (fn === 'scale') m = mul(m, scaleM(a[0], a.length > 1 ? a[1] : a[0]));\n else if (fn === 'rotate') m = mul(m, rotateM(a[0]));\n else if (fn === 'skewX') m = mul(m, skewXM(a[0]));\n else if (fn === 'skewY') m = mul(m, skewYM(a[0]));\n else if (fn === 'matrix') m = mul(m, [a[0], a[1], a[2], a[3], a[4], a[5]]);\n }\n return m;\n}\n\ninterface Parts { translate?: [number, number]; rotate?: number; scale?: [number, number]; origin?: [number, number]; }\n\n/** Composes a `PxTransformParts` record (player canonical order, origin-pivoted). */\nfunction partsToMatrix(p: Parts): Mat {\n let m = IDENTITY;\n if (p.translate) m = mul(m, translateM(p.translate[0], p.translate[1]));\n const pivot = p.origin && (p.rotate !== undefined || p.scale);\n if (pivot) m = mul(m, translateM(p.origin![0], p.origin![1]));\n if (p.rotate !== undefined) m = mul(m, rotateM(p.rotate));\n if (p.scale) m = mul(m, scaleM(p.scale[0], p.scale[1]));\n if (pivot) m = mul(m, translateM(-p.origin![0], -p.origin![1]));\n return m;\n}\n\nfunction lerp(a: number, b: number, f: number): number { return a + (b - a) * f; }\n\n/** Linear-interpolates a parts record between keyframes at time `t` (ms). */\nfunction interpParts(kfs: Array<any>, t: number): Parts {\n if (!kfs.length) return {};\n if (t <= (kfs[0].time ?? 0)) return kfs[0].value || {};\n if (t >= (kfs[kfs.length - 1].time ?? 0)) return kfs[kfs.length - 1].value || {};\n\n let i = 0;\n while (i < kfs.length - 1 && (kfs[i + 1].time ?? 0) < t) i++;\n const a = kfs[i], b = kfs[i + 1];\n const f = (t - (a.time ?? 0)) / ((b.time ?? 0) - (a.time ?? 0) || 1);\n const va: Parts = a.value || {}, vb: Parts = b.value || {};\n\n const out: Parts = {};\n if (va.translate && vb.translate) out.translate = [lerp(va.translate[0], vb.translate[0], f), lerp(va.translate[1], vb.translate[1], f)];\n else out.translate = va.translate || vb.translate;\n if (va.rotate !== undefined && vb.rotate !== undefined) out.rotate = lerp(va.rotate, vb.rotate, f);\n else out.rotate = va.rotate ?? vb.rotate;\n if (va.scale && vb.scale) out.scale = [lerp(va.scale[0], vb.scale[0], f), lerp(va.scale[1], vb.scale[1], f)];\n else out.scale = va.scale || vb.scale;\n out.origin = va.origin || vb.origin;\n return out;\n}\n\n/** Resolves any transform-slot form (string | bare record | {value} | {keyframes}) to a matrix at `t`. */\nfunction evalTransformValue(v: any, t: number): Mat {\n if (v === undefined || v === null) return IDENTITY;\n if (typeof v === 'string') return parseTransformString(v);\n if (v.keyframes) return partsToMatrix(interpParts(v.keyframes, t));\n if (v.value) return partsToMatrix(v.value);\n if (typeof v === 'object' && !Array.isArray(v)) return partsToMatrix(v); // bare parts record\n return IDENTITY;\n}\n\n/** The node's own transform at `t`: animated slot wins over the static baseline. */\nfunction nodeMatrix(node: VmNode, t: number): Mat {\n if (node.animate && node.animate.transform) return evalTransformValue(node.animate.transform, t);\n if (node.transform !== undefined) return evalTransformValue(node.transform, t);\n return IDENTITY;\n}\n\n/** Linear-interpolates a scalar animation (e.g. opacity); falls back to static / default. */\nfunction evalScalar(animated: any, staticVal: any, fallback: number, t: number): number {\n if (animated && animated.keyframes && animated.keyframes.length) {\n const kfs = animated.keyframes;\n if (t <= (kfs[0].time ?? 0)) return kfs[0].value;\n if (t >= (kfs[kfs.length - 1].time ?? 0)) return kfs[kfs.length - 1].value;\n let i = 0;\n while (i < kfs.length - 1 && (kfs[i + 1].time ?? 0) < t) i++;\n const a = kfs[i], b = kfs[i + 1];\n const f = (t - (a.time ?? 0)) / ((b.time ?? 0) - (a.time ?? 0) || 1);\n return lerp(a.value, b.value, f);\n }\n return staticVal !== undefined ? Number(staticVal) : fallback;\n}\n\n\n// ─────────────────────────────────────────────────────────────────────────────\n// FLATTEN → multiset of painted primitives\n// ─────────────────────────────────────────────────────────────────────────────\n\nconst CONTAINER_TYPES = new Set(['svg', 'g', 'symbol']);\nconst SKIP_TYPES = new Set(['defs', 'mask', 'clipPath', 'title']);\n\nfunction buildIdMap(node: VmNode, map: Map<string, VmNode>): void {\n if (typeof node.id === 'string') map.set(node.id, node);\n node.children?.forEach(c => buildIdMap(c, map));\n}\n\nfunction num(v: any): number { return v === undefined || v === null ? 0 : Number(v); }\n\n// 2-decimal rounding (sub-pixel). The heavy path bakes matrices into strings\n// rounded to ~4 decimals; comparing at 2 decimals avoids straddling a rounding\n// boundary against the applier's full-precision values, while staying visually exact.\nfunction round(n: number): number { return Math.round(n * 100) / 100 + 0; }\n\nfunction geomKey(node: VmNode): string {\n switch (node.type) {\n case 'rect': return num(node.width) + ',' + num(node.height) + ',' + num(node.x) + ',' + num(node.y);\n case 'ellipse': return num(node.rx) + ',' + num(node.ry) + ',' + num(node.cx) + ',' + num(node.cy);\n case 'circle': return num(node.r) + ',' + num(node.cx) + ',' + num(node.cy);\n case 'path': return String(node.d ?? '');\n default: return '';\n }\n}\n\nfunction describePrimitive(node: VmNode, m: Mat, t: number): string {\n const fill = node.fill ?? '';\n const stroke = node.stroke ?? '';\n const sw = node['stroke-width'] ?? node.strokeWidth ?? '';\n const opacity = round(evalScalar(node.animate?.opacity, node.opacity, 1, t));\n const masked = node.mask ? 1 : 0;\n const mat = m.map(round).join(',');\n return node.type + '|' + geomKey(node) + '|[' + mat + ']|f:' + fill + '|s:' + stroke + '|sw:' + (num(sw) || '') + '|o:' + opacity + '|m:' + masked;\n}\n\nfunction flatten(node: VmNode, parent: Mat, t: number, idMap: Map<string, VmNode>, out: Array<string>): void {\n const type = node.type || '';\n if (SKIP_TYPES.has(type)) return;\n\n const m = mul(parent, nodeMatrix(node, t));\n\n if (type === 'use') {\n const targetId = typeof node.href === 'string' ? node.href.replace(/^#/, '') : '';\n const target = idMap.get(targetId);\n const useM = mul(m, translateM(num(node.x), num(node.y)));\n if (target) flatten(target, useM, t, idMap, out);\n else out.push('UNRESOLVED_USE:#' + targetId);\n return;\n }\n\n if (CONTAINER_TYPES.has(type)) {\n node.children?.forEach(c => flatten(c, m, t, idMap, out));\n return;\n }\n\n out.push(describePrimitive(node, m, t));\n}\n\n\n// ─────────────────────────────────────────────────────────────────────────────\n// PUBLIC: sample times + visual model + comparison\n// ─────────────────────────────────────────────────────────────────────────────\n\n/** Every keyframe `time` found anywhere in the tree, plus 0. @internal */\nexport function collectSampleTimes(node: VmNode, into: Set<number>): void {\n into.add(0);\n const scanAnim = (anim: any) => {\n if (!anim || typeof anim !== 'object') return;\n for (const key of Object.keys(anim)) {\n const kfs = anim[key]?.keyframes;\n if (Array.isArray(kfs)) kfs.forEach(kf => into.add(kf.time ?? 0));\n }\n };\n scanAnim(node.animate);\n if (node.transform && typeof node.transform === 'object' && (node.transform as any).keyframes) {\n (node.transform as any).keyframes.forEach((kf: any) => into.add(kf.time ?? 0));\n }\n node.children?.forEach(c => collectSampleTimes(c, into));\n}\n\n/** Sorted, painted-primitive multiset for the tree at time `t`. @internal */\nexport function visualModelAt(root: VmNode, t: number): Array<string> {\n const idMap = new Map<string, VmNode>();\n buildIdMap(root, idMap);\n const out: Array<string> = [];\n flatten(root, IDENTITY, t, idMap, out);\n return out.sort();\n}\n\nexport interface EffectDiff {\n time: number;\n onlyInA: Array<string>;\n onlyInB: Array<string>;\n}\n\n/**\n * Compares two trees \"in effect\" across all keyframe instants found in either.\n * Returns one entry per time where the painted-primitive multisets differ.\n * @internal\n */\nexport function diffInEffect(a: VmNode, b: VmNode): Array<EffectDiff> {\n const times = new Set<number>();\n collectSampleTimes(a, times);\n collectSampleTimes(b, times);\n\n const diffs: Array<EffectDiff> = [];\n for (const t of Array.from(times).sort((x, y) => x - y)) {\n const ma = visualModelAt(a, t);\n const mb = visualModelAt(b, t);\n const onlyInA = subtractMultiset(ma, mb);\n const onlyInB = subtractMultiset(mb, ma);\n if (onlyInA.length || onlyInB.length) diffs.push({ time: t, onlyInA, onlyInB });\n }\n return diffs;\n}\n\n/** Items in `a` not matched one-for-one in `b` (multiset difference). */\nfunction subtractMultiset(a: Array<string>, b: Array<string>): Array<string> {\n const counts = new Map<string, number>();\n for (const x of b) counts.set(x, (counts.get(x) || 0) + 1);\n const extra: Array<string> = [];\n for (const x of a) {\n const c = counts.get(x) || 0;\n if (c > 0) counts.set(x, c - 1);\n else extra.push(x);\n }\n return extra;\n}\n","/*---------------------------------------------------------------------------------------\n * Copyright (c) Pixodesk LTD.\n * Licensed under the MIT License. See the LICENSE file in the project root for details.\n *---------------------------------------------------------------------------------------*/\n\n// Scroll-timeline PROGRESS MATH — pure functions, no DOM. This is the reference\n// implementation for `animator.timelineSource: 'scroll'` (the player-measured path — `timeline.engine: 'js'`, and the fallback of `auto`,\n// both engines): the DOM driver in svg-animator-web measures rects/offsets and calls in\n// here; the editor's design doc (`app/src/svgeditor/animation/scroll-timeline.design.md`\n// §4) documents the same formulas — keep them in sync.\n\nimport { clamp, PX_DEFAULT_DURATION_MS } from '../util/PxAnimatorUtil';\nimport type { PxAnimatorConfig, PxScroll, PxScrollPhase, PxScrollRangePoint } from '../format/PxAnimatorTypes';\n\n\n/** Is this document scroll-driven? (`animator.timelineSource === 'scroll'`) @internal */\nexport function isScrollTimeline(config: PxAnimatorConfig | undefined): boolean {\n return config?.timelineSource === 'scroll';\n}\n\n/**\n * The seek-space length (ms) a scroll progress of 1 maps to: duration × finite\n * iterations. `'infinite'` is meaningless on a finite progress timeline (see design doc\n * D4) — treated as 1 with the read-side warning left to the consumer.\n * @internal\n */\nexport function scrollTotalDurationMs(config: PxAnimatorConfig | undefined): number {\n const duration = (typeof config?.duration === 'number' && config.duration > 0)\n ? config.duration : PX_DEFAULT_DURATION_MS;\n const iterations = (typeof config?.iterations === 'number' && config.iterations > 0)\n ? config.iterations : 1;\n return duration * iterations;\n}\n\n/**\n * A named phase's interval in `u`-space.\n *\n * `u` is the subject's \"journey distance\": with `sTop` = subject's leading edge in\n * scrollport coordinates, `u = vpSize − sTop` — 0 exactly when the subject is about to\n * enter (leading edge at the scrollport's trailing edge), growing as the user scrolls.\n * The `min`/`max` pairs make every formula valid BOTH for a subject smaller than the\n * scrollport and one larger than it (where \"fully visible\" flips to \"covers the\n * scrollport\") — the same case split CSS specifies for its named timeline ranges.\n * @internal\n */\nexport function scrollPhaseInterval(\n phase: PxScrollPhase, subjectSize: number, scrollportSize: number\n): [number, number] {\n const s = subjectSize, vp = scrollportSize;\n switch (phase) {\n case 'cover': return [0, s + vp];\n case 'entry': return [0, Math.min(s, vp)];\n case 'contain': return [Math.min(s, vp), Math.max(s, vp)];\n case 'exit': return [Math.max(s, vp), s + vp];\n case 'entry-crossing': return [0, s];\n case 'exit-crossing': return [vp, s + vp];\n }\n}\n\nconst DEFAULT_PHASE: PxScrollPhase = 'cover';\n\n/** One range endpoint resolved to a `u`-space value. */\nfunction resolveRangePointU(\n point: PxScrollRangePoint | undefined, defaultFraction: number,\n subjectSize: number, scrollportSize: number\n): number {\n const [u0, u1] = scrollPhaseInterval(point?.phase ?? DEFAULT_PHASE, subjectSize, scrollportSize);\n const fraction = typeof point?.fraction === 'number' ? point.fraction : defaultFraction;\n return u0 + fraction * (u1 - u0);\n}\n\n/**\n * `kind: 'view'` progress ∈ [0, 1]: where the subject's journey sits within the\n * configured range.\n *\n * @param subjectStart subject's leading edge in scrollport coordinates\n * (`subjectRect.top − scrollportRect.top` on the resolved axis)\n * @param subjectSize subject size on the axis\n * @param scrollportSize scrollport size on the axis\n *\n * A degenerate/inverted range (uStart ≥ uEnd — e.g. zero-size subject with an `entry`\n * range) reports 1 once the point is passed, 0 before — never NaN.\n * @internal\n */\nexport function scrollViewProgress(\n subjectStart: number, subjectSize: number, scrollportSize: number,\n range: PxScroll['range'] | undefined\n): number {\n const u = scrollportSize - subjectStart;\n const uStart = resolveRangePointU(range?.start, 0, subjectSize, scrollportSize);\n const uEnd = resolveRangePointU(range?.end, 1, subjectSize, scrollportSize);\n if (uEnd <= uStart) return u >= uEnd ? 1 : 0;\n return clamp((u - uStart) / (uEnd - uStart), 0, 1);\n}\n\n/**\n * `kind: 'scroll'` progress ∈ [0, 1]: the scroller's offset ratio mapped through the\n * range (phases don't exist here — `fraction` is of the total scroll range).\n *\n * `maxOffset === 0` (nothing to scroll) reports 1, matching the CSS spec's rule that a\n * zero-length timeline is at 100%.\n * @internal\n */\nexport function scrollOffsetProgress(\n offset: number, maxOffset: number,\n range: PxScroll['range'] | undefined\n): number {\n const raw = maxOffset > 0 ? clamp(offset / maxOffset, 0, 1) : 1;\n const start = typeof range?.start?.fraction === 'number' ? range.start.fraction : 0;\n const end = typeof range?.end?.fraction === 'number' ? range.end.fraction : 1;\n if (end <= start) return raw >= end ? 1 : 0;\n return clamp((raw - start) / (end - start), 0, 1);\n}\n\n/**\n * Resolve a logical axis to a physical one. `block`/`inline` are writing-mode relative:\n * in horizontal writing (`horizontal-tb`, the default) block flows vertically; in\n * vertical writing modes it flows horizontally.\n * @internal\n */\nexport function scrollResolveAxis(\n axis: PxScroll['axis'] | undefined, writingMode: string | undefined\n): 'x' | 'y' {\n const a = axis ?? 'block';\n if (a === 'x' || a === 'y') return a;\n const vertical = !!writingMode && writingMode.startsWith('vertical');\n if (a === 'inline') return vertical ? 'y' : 'x';\n return vertical ? 'x' : 'y'; // block\n}\n","/*---------------------------------------------------------------------------------------\n * Copyright (c) Pixodesk LTD.\n * Licensed under the MIT License. See the LICENSE file in the project root for details.\n *---------------------------------------------------------------------------------------*/\n\n// ============================================================================\n// THE PLAYER'S WIRE-KEY INVENTORY — every field the player schema can carry, as a canonical\n// path, sorted. The library half of the editor's ship-guard (task 5.1).\n//\n// Why a committed list at all: A RENAME IS LENGTH-NEUTRAL. One name out, one in, same count,\n// green suite — which is how three renames shipped with no compat read, the last one wiping\n// the geometry of every shape-preset path on open. Diffing the list names the key that left.\n//\n// It lives HERE, not only in the editor, because the library ships on its own: a player\n// released with a key quietly gone breaks every document using it, editor or not.\n//\n// CANONICAL PATHS — the same rule as the editor's `collectSchemaFields`, so the two lists speak\n// one dialect: each object schema is enumerated ONCE, at the first path it is reached by\n// (breadth-first); `[]` marks an array item, `{*}` a record value or open-object value, `|i` /\n// `|tag` a union member. Without the once-only rule every recursive `children` re-lists the\n// whole node schema and the inventory explodes into thousands of paths that say nothing new.\n// ============================================================================\n\nimport { describeSchema, type PxSchema } from '../schema/PxSchema';\n\n/** Every field identity `root` can carry, as canonical paths, sorted. @internal */\nexport function schemaFieldUniverse(root: PxSchema<any, any>): Array<string> {\n const fields = new Set<string>();\n const enumerated = new Set<unknown>();\n const queue: Array<{ schema: PxSchema<any, any>; path: string }> = [{ schema: root, path: '' }];\n\n while (queue.length) {\n const { schema, path } = queue.shift()!;\n const d = describeSchema(schema);\n switch (d.kind) {\n case 'shape': {\n if (enumerated.has(schema)) break; // already listed under its canonical path\n enumerated.add(schema);\n for (const key of Object.keys(d.shape)) {\n const id = path ? path + '.' + key : key;\n fields.add(id);\n queue.push({ schema: d.shape[key], path: id });\n }\n if (d.openValue) queue.push({ schema: d.openValue, path: path + '{*}' });\n break;\n }\n case 'optional': queue.push({ schema: d.inner, path }); break;\n case 'array': queue.push({ schema: d.item, path: path + '[]' }); break;\n case 'lazy': queue.push({ schema: d.resolved, path }); break;\n case 'record': queue.push({ schema: d.value, path: path + '{*}' }); break;\n case 'union':\n d.members.forEach((member, i) => queue.push({ schema: member, path: path + '|' + i }));\n break;\n case 'discriminatedUnion':\n for (const member of d.members) queue.push({ schema: member, path: path + '|' + discriminantOf(member, d.key) });\n break;\n default: break; // tuple / leaf: no named fields\n }\n }\n return [...fields].sort();\n}\n\n/** The literal a discriminated-union member carries at its discriminant, unwrapping an\n * OPTIONAL discriminant (`type?: 'time'`). `?` when it carries none. */\nfunction discriminantOf(member: PxSchema<any, any>, key: string): string {\n const d = describeSchema(member);\n if (d.kind !== 'shape') return '?';\n const keySchema = d.shape[key];\n if (keySchema === undefined) return '?';\n const kd = describeSchema(keySchema);\n return String((kd.kind === 'optional' ? kd.inner : keySchema)._default);\n}\n","/*---------------------------------------------------------------------------------------\n * Copyright (c) Pixodesk LTD.\n * Licensed under the MIT License. See the LICENSE file in the project root for details.\n *---------------------------------------------------------------------------------------*/\n\n// ============================================================================\n// SCHEMA RELEASES (tasks 5.3 / 5.4) — the decision \"does this release move the schema\n// version, and which part?\" made by the DIFF, not by a person, plus the dated log of every\n// release kept beside the step table (`schema-releases.player.json`).\n//\n// Pure functions, so the release CLI (`scripts/schema-release.mjs`) and the guard test run the\n// SAME rule — a CLI and a test that each re-implement it are two rules that drift apart.\n//\n// The diff is over the canonical field inventory (`schemaFieldUniverse`): key paths only, so\n// descriptions and comments can never make two identical schemas look different.\n// ============================================================================\n\nimport { parseWireVersion, PxWireStepKind, type PxWireVersionStep } from './PxWireVersion';\n\n/** One entry of the release log — what shipped, when, and what it changed. @internal */\nexport interface SchemaReleaseRecord {\n readonly version: string;\n /** ISO date, `YYYY-MM-DD`. */\n readonly date: string;\n /** The first release: nothing to compare it against. */\n readonly baseline?: boolean;\n readonly added: ReadonlyArray<string>;\n readonly removed: ReadonlyArray<string>;\n readonly note?: string;\n}\n\n/** Keys that appeared and keys that left between two inventories, each sorted. @internal */\nexport function diffFieldUniverse(\n previous: ReadonlyArray<string>, current: ReadonlyArray<string>,\n): { added: Array<string>; removed: Array<string> } {\n const prev = new Set(previous);\n const cur = new Set(current);\n return {\n added: current.filter(k => !prev.has(k)).sort(),\n removed: previous.filter(k => !cur.has(k)).sort(),\n };\n}\n\n/** What a release must do about the version. `refuse` set means: do not release as-is. @internal */\nexport interface SchemaReleasePlan {\n /** Did any key appear or leave since the last release? */\n readonly changed: boolean;\n /** Which kind of step the change requires — a removal is never additive. */\n readonly requiredKind?: PxWireStepKind;\n /** The version this release must carry. */\n readonly requiredVersion?: string;\n readonly refuse?: string;\n}\n\n/**\n * THE BUMP RULE. A key change requires `b + 1` and a step that explains it; no key change\n * requires nothing. The rule never picks the number by taste — the inventory diff does.\n * @internal\n */\nexport function planSchemaRelease(p: {\n readonly added: ReadonlyArray<string>;\n readonly removed: ReadonlyArray<string>;\n /** `PX_WIRE_SCHEMA_VERSION` — what the source says now. */\n readonly declared: string;\n /** The version of the last release record. */\n readonly lastReleased: string;\n readonly steps: ReadonlyArray<PxWireVersionStep>;\n}): SchemaReleasePlan {\n const changed = p.added.length > 0 || p.removed.length > 0;\n const last = parseWireVersion(p.lastReleased);\n const declared = parseWireVersion(p.declared);\n if (!last || !declared) return { changed, refuse: 'Unparseable version: ' + p.lastReleased + ' / ' + p.declared + '.' };\n\n const requiredVersion = last.a + '.' + (last.b + 1);\n if (!changed) {\n // Same keys: nothing to bump. A bump anyway is a SEMANTIC change and still needs its step.\n if (declared.b === last.b && declared.a === last.a) return { changed };\n const step = p.steps.find(s => s.to === p.declared);\n return step ? { changed, requiredVersion: p.declared }\n : { changed, refuse: 'The version moved to ' + p.declared + ' with no key change and no step explaining it.' };\n }\n\n const requiredKind = p.removed.length ? PxWireStepKind.converted : PxWireStepKind.additive;\n const summary = p.added.length + ' key(s) added, ' + p.removed.length + ' removed';\n if (declared.a !== last.a || declared.b !== last.b + 1) {\n return {\n changed, requiredKind, requiredVersion,\n refuse: 'The player schema changed (' + summary + ') but PX_WIRE_SCHEMA_VERSION is '\n + p.declared + '. Set it to ' + requiredVersion + ' and add the PX_WIRE_STEPS entry.',\n };\n }\n const step = p.steps.find(s => s.to === p.declared);\n if (!step) {\n return { changed, requiredKind, requiredVersion, refuse: 'No PX_WIRE_STEPS entry reaches ' + p.declared + '.' };\n }\n if (requiredKind === PxWireStepKind.converted && step.kind !== PxWireStepKind.converted) {\n return {\n changed, requiredKind, requiredVersion,\n refuse: 'Keys were REMOVED (' + p.removed.join(', ') + '), which is never additive — the '\n + p.declared + ' step must be `converted`, with an up().',\n };\n }\n return { changed, requiredKind, requiredVersion };\n}\n\n/**\n * Everything wrong with the release log, as sentences — empty when it is consistent. The log\n * must start at the baseline, move strictly forward, END at the version the source declares,\n * and every release after the baseline must have the step that explains it.\n * @internal\n */\nexport function releaseLogProblems(\n releases: ReadonlyArray<SchemaReleaseRecord>, steps: ReadonlyArray<PxWireVersionStep>,\n declared: string, baseline: string,\n): Array<string> {\n const problems: Array<string> = [];\n if (!releases.length) return ['The release log is empty.'];\n if (!releases[0].baseline || releases[0].version !== baseline) {\n problems.push('The first release must be the baseline ' + baseline + '.');\n }\n for (let i = 1; i < releases.length; i++) {\n const prev = parseWireVersion(releases[i - 1].version);\n const cur = parseWireVersion(releases[i].version);\n if (!prev || !cur || cur.a !== prev.a || cur.b !== prev.b + 1) {\n problems.push('Release ' + releases[i].version + ' does not follow ' + releases[i - 1].version + ' by one `b` step.');\n }\n if (releases[i].date < releases[i - 1].date) problems.push('Release ' + releases[i].version + ' is dated before its predecessor.');\n const step = steps.find(s => s.to === releases[i].version);\n if (!step) problems.push('Release ' + releases[i].version + ' has no PX_WIRE_STEPS entry.');\n else if (releases[i].removed.length && step.kind !== PxWireStepKind.converted) {\n problems.push('Release ' + releases[i].version + ' removed keys, but its step is not `converted`.');\n }\n }\n const latest = releases[releases.length - 1].version;\n if (latest !== declared) {\n problems.push('PX_WIRE_SCHEMA_VERSION is ' + declared + ' but the last release record is ' + latest\n + ' — a bump needs its changelog entry (run scripts/schema-release.mjs --apply).');\n }\n return problems;\n}\n"],"mappings":"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","names":["_a","step"]}
|