@hyperframes/sdk 0.6.113

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/LICENSE +190 -0
  2. package/dist/adapters/fs.d.ts +9 -0
  3. package/dist/adapters/fs.d.ts.map +1 -0
  4. package/dist/adapters/fs.js +122 -0
  5. package/dist/adapters/fs.js.map +1 -0
  6. package/dist/adapters/headless.d.ts +3 -0
  7. package/dist/adapters/headless.d.ts.map +1 -0
  8. package/dist/adapters/headless.js +17 -0
  9. package/dist/adapters/headless.js.map +1 -0
  10. package/dist/adapters/iframe.d.ts +102 -0
  11. package/dist/adapters/iframe.d.ts.map +1 -0
  12. package/dist/adapters/iframe.js +569 -0
  13. package/dist/adapters/iframe.js.map +1 -0
  14. package/dist/adapters/memory.d.ts +5 -0
  15. package/dist/adapters/memory.d.ts.map +1 -0
  16. package/dist/adapters/memory.js +54 -0
  17. package/dist/adapters/memory.js.map +1 -0
  18. package/dist/adapters/types.d.ts +65 -0
  19. package/dist/adapters/types.d.ts.map +1 -0
  20. package/dist/adapters/types.js +2 -0
  21. package/dist/adapters/types.js.map +1 -0
  22. package/dist/document.d.ts +25 -0
  23. package/dist/document.d.ts.map +1 -0
  24. package/dist/document.js +238 -0
  25. package/dist/document.js.map +1 -0
  26. package/dist/engine/apply-patches.d.ts +20 -0
  27. package/dist/engine/apply-patches.d.ts.map +1 -0
  28. package/dist/engine/apply-patches.js +284 -0
  29. package/dist/engine/apply-patches.js.map +1 -0
  30. package/dist/engine/cssWriter.d.ts +18 -0
  31. package/dist/engine/cssWriter.d.ts.map +1 -0
  32. package/dist/engine/cssWriter.js +139 -0
  33. package/dist/engine/cssWriter.js.map +1 -0
  34. package/dist/engine/keyframeBackfill.d.ts +17 -0
  35. package/dist/engine/keyframeBackfill.d.ts.map +1 -0
  36. package/dist/engine/keyframeBackfill.js +43 -0
  37. package/dist/engine/keyframeBackfill.js.map +1 -0
  38. package/dist/engine/model.d.ts +55 -0
  39. package/dist/engine/model.d.ts.map +1 -0
  40. package/dist/engine/model.js +256 -0
  41. package/dist/engine/model.js.map +1 -0
  42. package/dist/engine/mutate.d.ts +26 -0
  43. package/dist/engine/mutate.d.ts.map +1 -0
  44. package/dist/engine/mutate.js +1243 -0
  45. package/dist/engine/mutate.js.map +1 -0
  46. package/dist/engine/patches.d.ts +71 -0
  47. package/dist/engine/patches.d.ts.map +1 -0
  48. package/dist/engine/patches.js +197 -0
  49. package/dist/engine/patches.js.map +1 -0
  50. package/dist/engine/serialize.d.ts +15 -0
  51. package/dist/engine/serialize.d.ts.map +1 -0
  52. package/dist/engine/serialize.js +20 -0
  53. package/dist/engine/serialize.js.map +1 -0
  54. package/dist/engine/variableModel.d.ts +29 -0
  55. package/dist/engine/variableModel.d.ts.map +1 -0
  56. package/dist/engine/variableModel.js +81 -0
  57. package/dist/engine/variableModel.js.map +1 -0
  58. package/dist/history.d.ts +39 -0
  59. package/dist/history.d.ts.map +1 -0
  60. package/dist/history.js +116 -0
  61. package/dist/history.js.map +1 -0
  62. package/dist/index.d.ts +15 -0
  63. package/dist/index.d.ts.map +1 -0
  64. package/dist/index.js +11 -0
  65. package/dist/index.js.map +1 -0
  66. package/dist/persist-queue.d.ts +24 -0
  67. package/dist/persist-queue.d.ts.map +1 -0
  68. package/dist/persist-queue.js +62 -0
  69. package/dist/persist-queue.js.map +1 -0
  70. package/dist/session.d.ts +38 -0
  71. package/dist/session.d.ts.map +1 -0
  72. package/dist/session.js +514 -0
  73. package/dist/session.js.map +1 -0
  74. package/dist/types.d.ts +521 -0
  75. package/dist/types.d.ts.map +1 -0
  76. package/dist/types.js +16 -0
  77. package/dist/types.js.map +1 -0
  78. package/package.json +55 -0
@@ -0,0 +1,569 @@
1
+ /**
2
+ * Same-origin iframe PreviewAdapter — WS-A1 (hit-test + selection) +
3
+ * WS-A2 (applyDraft / commitPreview / cancelPreview → moveElement) +
4
+ * WS-G (image-alpha hit-test, phase 1).
5
+ *
6
+ * Requirements:
7
+ * - The iframe MUST be same-origin (srcdoc / blob URL). Cross-origin access to
8
+ * contentDocument throws a DOMException; this adapter does not guard that —
9
+ * the caller is responsible for ensuring same-origin.
10
+ *
11
+ * Image-alpha (phase 1):
12
+ * - Replaces elementFromPoint with elementsFromPoint (z-stack) so transparent
13
+ * image hits fall through to the element behind.
14
+ * - For <img> hits, maps the client point to the natural-pixel coordinate
15
+ * (object-fit/object-position aware), draws to an offscreen canvas (cached
16
+ * by src + natural dimensions, so a srcset re-render gets a fresh canvas),
17
+ * samples alpha. Transparent pixel → miss, continue the stack.
18
+ * - Cross-origin images taint the canvas → getImageData throws SecurityError
19
+ * → falls back to treating the pixel as OPAQUE (never drop an unverifiable
20
+ * hit) and warns once per src. Callers must ensure CORS or accept the fallback.
21
+ * - A CSS rotation/skew on the image or an ancestor also falls back to opaque
22
+ * (the axis-aligned rect mapping can't sample a rotated image correctly);
23
+ * transform-inverse mapping is phase 2.
24
+ * - Images above a pixel budget skip alpha-testing (opaque) to bound canvas
25
+ * memory. Limitation: animated <img> (gif) or src swaps invalidate the cache
26
+ * only when currentSrc/dimensions change. Phase 1 is optimized for static images.
27
+ * - Phase 2 (full per-pixel alpha via drawElement rasterization) is NOT built
28
+ * here — gated on a perf spike.
29
+ */
30
+ // ─── CSS var names written onto elements during drag ─────────────────────────
31
+ const VAR_DX = "--hf-studio-dx";
32
+ const VAR_DY = "--hf-studio-dy";
33
+ // ─── Pure resolver (testable without a browser) ───────────────────────────────
34
+ /**
35
+ * Walk from `el` upward through parentElement, looking for the nearest node
36
+ * that carries `[data-hf-id]` and is NOT `[data-hf-root]`.
37
+ *
38
+ * Returns null when:
39
+ * - The walk exits the tree without finding `[data-hf-id]`
40
+ * - The matching node is `[data-hf-root]` (transparent to hit-testing)
41
+ * - `isVisible(node)` returns false for the matching node
42
+ *
43
+ * Keeping this a pure function (no elementFromPoint, no window access) makes
44
+ * it unit-testable in a plain Node environment.
45
+ */
46
+ export function resolveNearestHfElement(el, isVisible) {
47
+ let node = el;
48
+ while (node !== null) {
49
+ const id = node.getAttribute("data-hf-id");
50
+ if (id !== null) {
51
+ if (node.hasAttribute("data-hf-root"))
52
+ return null;
53
+ if (!isVisible(node))
54
+ return null;
55
+ return { id, tag: node.tagName.toLowerCase() };
56
+ }
57
+ node = node.parentElement;
58
+ }
59
+ return null;
60
+ }
61
+ // ─── Draft position math (pure — testable without a browser) ─────────────────
62
+ /**
63
+ * Compute the new absolute x/y for a moveElement op given:
64
+ * - the element's current `data-x` / `data-y` string values (may be null)
65
+ * - the accumulated drag delta (dx, dy) from applyDraft calls
66
+ *
67
+ * `data-x` / `data-y` default to 0 when absent or non-numeric.
68
+ */
69
+ export function computeDraftPosition(dataX, dataY, dx, dy) {
70
+ const baseX = parseFloat(dataX ?? "0") || 0;
71
+ const baseY = parseFloat(dataY ?? "0") || 0;
72
+ return { x: baseX + dx, y: baseY + dy };
73
+ }
74
+ // ─── Image-alpha pure helpers (WS-G phase 1) ──────────────────────────────────
75
+ /**
76
+ * Returns true when the first pixel in `imageData` has alpha >= threshold.
77
+ *
78
+ * Pure — no DOM access; unit-testable with a plain Uint8ClampedArray.
79
+ * threshold defaults to 1 so a fully-transparent pixel (a=0) is a miss.
80
+ */
81
+ export function alphaIsOpaque(imageData, threshold = 1) {
82
+ // ImageData.data is [R, G, B, A, R, G, B, A, ...]
83
+ const alpha = imageData.data[3] ?? 0;
84
+ return alpha >= threshold;
85
+ }
86
+ /**
87
+ * Map a client-space point to the natural-pixel coordinates of the image.
88
+ *
89
+ * Handles object-fit: fill | cover | contain (default=fill when unset).
90
+ * object-position is parsed as two percentage/px values (default "50% 50%").
91
+ *
92
+ * Returns null when the point falls outside the rendered image area (e.g.
93
+ * the letterbox region of a contain-fitted image). A null result means the
94
+ * image does not own this pixel — the caller should continue the z-stack.
95
+ *
96
+ * Pure — no DOM/window access; unit-testable with plain objects.
97
+ */
98
+ // fallow-ignore-next-line complexity
99
+ export function mapPointToImagePixel(rect, natural, objectFit, objectPosition, point) {
100
+ // Local coords within the CSS box
101
+ const lx = point.x - rect.left;
102
+ const ly = point.y - rect.top;
103
+ if (lx < 0 || ly < 0 || lx > rect.width || ly > rect.height)
104
+ return null;
105
+ const fit = objectFit || "fill";
106
+ // For fill (or unrecognized values): the natural image is stretched to the
107
+ // box; direct linear mapping.
108
+ if (fit !== "cover" && fit !== "contain" && fit !== "none") {
109
+ if (rect.width === 0 || rect.height === 0)
110
+ return null;
111
+ const px = Math.floor((lx / rect.width) * natural.width);
112
+ const py = Math.floor((ly / rect.height) * natural.height);
113
+ return { px: clamp(px, 0, natural.width - 1), py: clamp(py, 0, natural.height - 1) };
114
+ }
115
+ // For none: image is drawn at its natural size; no scaling.
116
+ if (fit === "none") {
117
+ const pos = parseObjectPosition(objectPosition, rect, natural);
118
+ const ox = pos.x;
119
+ const oy = pos.y;
120
+ const px = Math.floor(lx - ox);
121
+ const py = Math.floor(ly - oy);
122
+ if (px < 0 || py < 0 || px >= natural.width || py >= natural.height)
123
+ return null;
124
+ return { px, py };
125
+ }
126
+ // cover: scale uniformly so the image covers the box; may clip edges.
127
+ // contain: scale uniformly so the image fits within the box; may letterbox.
128
+ if (natural.width === 0 || natural.height === 0)
129
+ return null;
130
+ const scaleX = rect.width / natural.width;
131
+ const scaleY = rect.height / natural.height;
132
+ const scale = fit === "cover" ? Math.max(scaleX, scaleY) : Math.min(scaleX, scaleY);
133
+ const renderedW = natural.width * scale;
134
+ const renderedH = natural.height * scale;
135
+ const pos = parseObjectPosition(objectPosition, rect, {
136
+ width: renderedW,
137
+ height: renderedH,
138
+ });
139
+ // Offset of the rendered image's top-left within the CSS box
140
+ const imgLeft = pos.x;
141
+ const imgTop = pos.y;
142
+ // Local coords relative to the rendered image's top-left
143
+ const rx = lx - imgLeft;
144
+ const ry = ly - imgTop;
145
+ if (rx < 0 || ry < 0 || rx > renderedW || ry > renderedH)
146
+ return null;
147
+ if (scale === 0)
148
+ return null;
149
+ const px = Math.floor(rx / scale);
150
+ const py = Math.floor(ry / scale);
151
+ return { px: clamp(px, 0, natural.width - 1), py: clamp(py, 0, natural.height - 1) };
152
+ }
153
+ // ─── object-position parser (pure) ───────────────────────────────────────────
154
+ /**
155
+ * Parse a CSS object-position value into x/y offsets (top-left of the
156
+ * rendered content relative to the CSS box top-left).
157
+ *
158
+ * Supports the common subset: keyword pairs, percentage pairs, pixel pairs,
159
+ * and single-value shorthand. Mixed units (e.g. "50% 10px") are supported.
160
+ *
161
+ * Pure — no DOM access.
162
+ */
163
+ function parseObjectPosition(objectPosition, box, content) {
164
+ const raw = (objectPosition || "50% 50%").trim();
165
+ const parts = raw.split(/\s+/);
166
+ // Resolve a single token into a pixel offset along the given axis.
167
+ // `available` is the "slack" (box dimension - content dimension).
168
+ // fallow-ignore-next-line complexity
169
+ function resolveToken(token, available) {
170
+ if (token === "left" || token === "top")
171
+ return 0;
172
+ if (token === "right" || token === "bottom")
173
+ return available;
174
+ if (token === "center")
175
+ return available / 2;
176
+ if (token.endsWith("%")) {
177
+ const pct = parseFloat(token) / 100;
178
+ return isNaN(pct) ? available / 2 : pct * available;
179
+ }
180
+ if (token.endsWith("px")) {
181
+ const px = parseFloat(token);
182
+ return isNaN(px) ? available / 2 : px;
183
+ }
184
+ // Bare number — treat as px
185
+ const n = parseFloat(token);
186
+ return isNaN(n) ? available / 2 : n;
187
+ }
188
+ const availX = box.width - content.width;
189
+ const availY = box.height - content.height;
190
+ const isVert = (t) => t === "top" || t === "bottom";
191
+ const isHoriz = (t) => t === "left" || t === "right";
192
+ if (parts.length === 1) {
193
+ const tokenX = parts[0] ?? "50%";
194
+ // Single value: if it's a vertical keyword the x defaults to center
195
+ if (isVert(tokenX)) {
196
+ return { x: availX / 2, y: resolveToken(tokenX, availY) };
197
+ }
198
+ return { x: resolveToken(tokenX, availX), y: availY / 2 };
199
+ }
200
+ // Keyword pairs may be given vertical-first ("bottom left"); normalize so the
201
+ // first token addresses the x-axis and the second the y-axis.
202
+ let xToken = parts[0] ?? "50%";
203
+ let yToken = parts[1] ?? "50%";
204
+ if (isVert(xToken) || isHoriz(yToken)) {
205
+ [xToken, yToken] = [yToken, xToken];
206
+ }
207
+ return {
208
+ x: resolveToken(xToken, availX),
209
+ y: resolveToken(yToken, availY),
210
+ };
211
+ }
212
+ function clamp(v, min, max) {
213
+ return v < min ? min : v > max ? max : v;
214
+ }
215
+ // ─── Visibility check ─────────────────────────────────────────────────────────
216
+ /**
217
+ * Returns true when no element in the ancestor chain (inclusive) has
218
+ * computed opacity === 0. Checks ancestors because a parent at opacity:0
219
+ * makes the child invisible even if the child's own opacity is 1.
220
+ *
221
+ * This reflects the current GSAP timeline state (whatever the player has
222
+ * seeked to). For atTime values matching the live playhead this is always
223
+ * accurate. For speculative times this is NOT seeked — WS-A1 does not mutate
224
+ * the timeline; accurate out-of-band opacity queries are WS-G follow-on.
225
+ */
226
+ function isOpacityVisible(el, win) {
227
+ let node = el;
228
+ while (node !== null) {
229
+ const style = win.getComputedStyle(node);
230
+ if (parseFloat(style.opacity) === 0)
231
+ return false;
232
+ node = node.parentElement;
233
+ }
234
+ return true;
235
+ }
236
+ // ─── Image-alpha canvas cache (WS-G phase 1) ─────────────────────────────────
237
+ /**
238
+ * Cache of offscreen canvases keyed by image currentSrc.
239
+ *
240
+ * Canvases are drawn once; the same canvas is reused across hit-tests.
241
+ * Animated images (gif) or dynamic src swaps are NOT tracked — this is a
242
+ * phase-1 static-image optimization. A tainted entry stores null to record
243
+ * that the image is cross-origin and all pixels should be treated as opaque.
244
+ *
245
+ * Exported for tests that need to reset the cache between runs.
246
+ */
247
+ export const _imgCanvasCache = new Map();
248
+ /**
249
+ * Bounded cap so a long session can't accumulate one full-resolution
250
+ * OffscreenCanvas per image src indefinitely.
251
+ * ponytail: FIFO eviction, upgrade to LRU if cache hit-rate matters.
252
+ */
253
+ const _IMG_CANVAS_CACHE_MAX = 64;
254
+ function cacheCanvas(key, value) {
255
+ if (!_imgCanvasCache.has(key) && _imgCanvasCache.size >= _IMG_CANVAS_CACHE_MAX) {
256
+ const oldest = _imgCanvasCache.keys().next().value;
257
+ if (oldest !== undefined)
258
+ _imgCanvasCache.delete(oldest);
259
+ }
260
+ _imgCanvasCache.set(key, value);
261
+ }
262
+ /**
263
+ * Skip alpha-testing images above this pixel budget — allocating a full-res
264
+ * OffscreenCanvas for one hit-test is memory-prohibitive (a 4000×3000 image is
265
+ * ~46 MB). Above the cap we fail safe to opaque.
266
+ * ponytail: per-image pixel cap; a byte-budget cache is phase 2.
267
+ */
268
+ const _MAX_ALPHA_TEST_PIXELS = 16_000_000;
269
+ /**
270
+ * Srcs we've already warned about taint for — keeps the cross-origin warning to
271
+ * once per image instead of once per hit-test. Cleared with `_imgCanvasCache`
272
+ * is not necessary; suppressing duplicate warnings across resets is harmless.
273
+ */
274
+ const _warnedTaintSrcs = new Set();
275
+ function warnTaintOnce(src) {
276
+ if (_warnedTaintSrcs.has(src))
277
+ return;
278
+ _warnedTaintSrcs.add(src);
279
+ // Visibility for the silent-failure path: a cross-origin / uncorsed image
280
+ // taints the canvas, so alpha hit-test is unavailable and we fall back to
281
+ // opaque. Without this, the fall-back is invisible ("hit-test feels wrong").
282
+ console.warn(`[hyperframes] image-alpha hit-test unavailable for cross-origin/tainted image; treating as opaque: ${src}`);
283
+ }
284
+ /**
285
+ * True when the element or any ancestor carries a CSS rotation or skew. Such a
286
+ * transform makes getBoundingClientRect() return the axis-aligned bounding box,
287
+ * so the rect→natural-pixel mapping would sample the wrong pixel. Pure translate
288
+ * / scale keep the matrix b and c components at 0 and map correctly. No-op
289
+ * (returns false) when DOMMatrix is unavailable (e.g. the test env), preserving
290
+ * existing behavior there.
291
+ */
292
+ function hasRotationOrSkew(el, win) {
293
+ if (typeof win.DOMMatrix !== "function")
294
+ return false;
295
+ for (let node = el; node; node = node.parentElement) {
296
+ const t = win.getComputedStyle(node).transform;
297
+ if (!t || t === "none")
298
+ continue;
299
+ try {
300
+ const m = new win.DOMMatrix(t);
301
+ if (Math.abs(m.b) > 1e-6 || Math.abs(m.c) > 1e-6)
302
+ return true;
303
+ }
304
+ catch {
305
+ return true; // unparseable transform — fail safe (treat as non-axis-aligned)
306
+ }
307
+ }
308
+ return false;
309
+ }
310
+ /**
311
+ * Sample the alpha at (clientX, clientY) for an <img> element.
312
+ *
313
+ * Returns true (opaque) when:
314
+ * - The image has not finished loading (naturalWidth/naturalHeight === 0)
315
+ * - The point maps outside the rendered image area (not this image's pixel)
316
+ * - The canvas is tainted (cross-origin, SecurityError) — fallback: opaque
317
+ * - Alpha >= 1
318
+ *
319
+ * Returns false (transparent/miss) only when the canvas is readable AND the
320
+ * alpha at the mapped pixel is 0. A click on the element's border/padding maps
321
+ * outside the content box → also false (the click falls through to the layer
322
+ * behind), since border/padding pixels aren't part of the image — intentional.
323
+ *
324
+ * `win` is the iframe's contentWindow, used to call getComputedStyle on the
325
+ * element which lives in the iframe's document.
326
+ */
327
+ // fallow-ignore-next-line complexity
328
+ function imageAlphaOpaqueAt(img, clientX, clientY, win) {
329
+ // Not loaded yet — treat as opaque (safe fallback)
330
+ if (img.naturalWidth === 0 || img.naturalHeight === 0)
331
+ return true;
332
+ const src = img.currentSrc || img.src;
333
+ if (!src)
334
+ return true;
335
+ // CSS rotation/skew on the image or an ancestor breaks the axis-aligned
336
+ // rect→natural-pixel mapping below (getBoundingClientRect returns the AABB),
337
+ // so we'd sample the wrong pixel. Fail safe to opaque rather than guess.
338
+ // Full transform-inverse mapping is phase 2.
339
+ if (hasRotationOrSkew(img, win))
340
+ return true;
341
+ // Pathological-size guard: don't allocate a huge canvas for one hit-test.
342
+ if (img.naturalWidth * img.naturalHeight > _MAX_ALPHA_TEST_PIXELS)
343
+ return true;
344
+ // object-fit/object-position lay the image out within the CONTENT box, not
345
+ // the border box that getBoundingClientRect() returns. Inset by border +
346
+ // padding so the mapping is correct for an <img> that has a border or padding.
347
+ const rect = img.getBoundingClientRect();
348
+ const style = win.getComputedStyle(img);
349
+ const borderL = parseFloat(style.borderLeftWidth) || 0;
350
+ const borderT = parseFloat(style.borderTopWidth) || 0;
351
+ const borderR = parseFloat(style.borderRightWidth) || 0;
352
+ const borderB = parseFloat(style.borderBottomWidth) || 0;
353
+ const padL = parseFloat(style.paddingLeft) || 0;
354
+ const padT = parseFloat(style.paddingTop) || 0;
355
+ const padR = parseFloat(style.paddingRight) || 0;
356
+ const padB = parseFloat(style.paddingBottom) || 0;
357
+ const objectFit = style.objectFit || "fill";
358
+ const objectPosition = style.objectPosition || "50% 50%";
359
+ const mapped = mapPointToImagePixel({
360
+ left: rect.left + borderL + padL,
361
+ top: rect.top + borderT + padT,
362
+ width: rect.width - borderL - borderR - padL - padR,
363
+ height: rect.height - borderT - borderB - padT - padB,
364
+ }, { width: img.naturalWidth, height: img.naturalHeight }, objectFit, objectPosition, { x: clientX, y: clientY });
365
+ // Point is outside the rendered image area — not this image's pixel.
366
+ // Continue the z-stack (return false = miss on this element).
367
+ if (mapped === null)
368
+ return false;
369
+ // Retrieve or build the offscreen canvas. Key on src + natural dimensions: a
370
+ // srcset/responsive layout can serve the same URL at a different natural size,
371
+ // and keying on src alone would reuse a canvas drawn at the prior dimensions.
372
+ const cacheKey = `${src}@${img.naturalWidth}x${img.naturalHeight}`;
373
+ let canvas = _imgCanvasCache.get(cacheKey);
374
+ if (canvas === undefined) {
375
+ // First time: draw to an offscreen canvas and cache.
376
+ try {
377
+ const oc = new OffscreenCanvas(img.naturalWidth, img.naturalHeight);
378
+ const ctx = oc.getContext("2d");
379
+ if (!ctx) {
380
+ // OffscreenCanvas 2D unavailable — treat as opaque.
381
+ cacheCanvas(cacheKey, null);
382
+ return true;
383
+ }
384
+ ctx.drawImage(img, 0, 0, img.naturalWidth, img.naturalHeight);
385
+ cacheCanvas(cacheKey, oc);
386
+ canvas = oc;
387
+ }
388
+ catch {
389
+ // SecurityError from tainted canvas — record null and fall back opaque.
390
+ warnTaintOnce(src);
391
+ cacheCanvas(cacheKey, null);
392
+ return true;
393
+ }
394
+ }
395
+ // null means we already know this src is tainted — treat as opaque.
396
+ if (canvas === null)
397
+ return true;
398
+ try {
399
+ const ctx = canvas.getContext("2d");
400
+ if (!ctx)
401
+ return true;
402
+ // The mapped-pixel read also surfaces lazy canvas taint (SecurityError),
403
+ // so no separate taint probe is needed.
404
+ const data = ctx.getImageData(mapped.px, mapped.py, 1, 1);
405
+ return alphaIsOpaque(data);
406
+ }
407
+ catch {
408
+ // Taint discovered on getImageData — update cache and fall back opaque.
409
+ warnTaintOnce(src);
410
+ cacheCanvas(cacheKey, null);
411
+ return true;
412
+ }
413
+ }
414
+ // ─── IframePreviewAdapter ─────────────────────────────────────────────────────
415
+ /**
416
+ * The hit-test z-stack at (x, y): the full elementsFromPoint stack, or a
417
+ * single-element fallback for hosts that lack elementsFromPoint.
418
+ */
419
+ function hitStack(doc, x, y) {
420
+ if (typeof doc.elementsFromPoint === "function")
421
+ return doc.elementsFromPoint(x, y);
422
+ const top = doc.elementFromPoint(x, y);
423
+ return top ? [top] : [];
424
+ }
425
+ class IframePreviewAdapter {
426
+ iframe;
427
+ _dispatch;
428
+ _selection = [];
429
+ _handlers = [];
430
+ /** Tracked id and element for the in-progress drag. */
431
+ _draftId = null;
432
+ _draftEl = null;
433
+ constructor(iframe, dispatch) {
434
+ this.iframe = iframe;
435
+ this._dispatch = dispatch;
436
+ }
437
+ /**
438
+ * Synchronous hit-test. Returns the nearest `[data-hf-id]` element under
439
+ * (x, y) in the iframe's coordinate space, or null for a transparent hit
440
+ * (root, opacity-0, nothing at all, or a transparent image pixel).
441
+ *
442
+ * WS-G phase 1: uses elementsFromPoint (z-stack) so a transparent-image hit
443
+ * falls through to the layer behind. For <img> elements, the alpha at the
444
+ * mapped natural pixel is sampled from an offscreen canvas. Cross-origin
445
+ * images that taint the canvas are treated as opaque (safe fallback).
446
+ *
447
+ * atTime: reflects the GSAP state at the playhead when this is called.
448
+ * Seeking to a different time to check visibility is WS-G follow-on.
449
+ */
450
+ elementAtPoint(x, y, _opts) {
451
+ const doc = this.iframe.contentDocument;
452
+ if (!doc)
453
+ return null;
454
+ const win = this.iframe.contentWindow;
455
+ if (!win)
456
+ return null;
457
+ const stack = hitStack(doc, x, y);
458
+ for (const candidate of stack) {
459
+ // One opacity walk per candidate (candidate → root). An opacity:0 element
460
+ // is skipped, so the click falls through to the layer painted behind it.
461
+ if (!isOpacityVisible(candidate, win))
462
+ continue;
463
+ // Image-alpha check: if this is an <img>, verify the pixel is opaque.
464
+ if (win.HTMLImageElement && candidate instanceof win.HTMLImageElement) {
465
+ if (!imageAlphaOpaqueAt(candidate, x, y, win)) {
466
+ // Transparent pixel — fall through to the next element in the stack.
467
+ continue;
468
+ }
469
+ }
470
+ // The candidate's whole ancestor chain is already known visible (the walk
471
+ // above covers it, and the hf node is on that chain), so the resolver
472
+ // needs no second visibility walk.
473
+ const result = resolveNearestHfElement(candidate, () => true);
474
+ if (result !== null)
475
+ return result;
476
+ }
477
+ return null;
478
+ }
479
+ /**
480
+ * Write draft CSS custom properties (`--hf-studio-dx`, `--hf-studio-dy`) onto
481
+ * the target element inside the iframe at 60fps. The composition's CSS uses
482
+ * these vars to visually translate the element without touching the model.
483
+ *
484
+ * Calling applyDraft with a new id replaces the tracked element (does not
485
+ * cancel the prior draft — call cancelPreview first if switching targets).
486
+ *
487
+ * width/height in DraftProps are not yet wired (resize → setStyle, future op).
488
+ */
489
+ applyDraft(id, props) {
490
+ const doc = this.iframe.contentDocument;
491
+ if (!doc)
492
+ return;
493
+ // Reuse the tracked element across the 60fps drag; only re-query when the id
494
+ // changes or the cached node detached (e.g. an iframe reload mid-drag).
495
+ const cached = id === this._draftId && this._draftEl?.isConnected ? this._draftEl : null;
496
+ const el = cached ??
497
+ doc.querySelector(`[data-hf-id="${id.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"]`);
498
+ if (!el)
499
+ return;
500
+ this._draftId = id;
501
+ this._draftEl = el;
502
+ if (props.dx !== undefined)
503
+ el.style.setProperty(VAR_DX, String(props.dx));
504
+ if (props.dy !== undefined)
505
+ el.style.setProperty(VAR_DY, String(props.dy));
506
+ }
507
+ /**
508
+ * Read the accumulated draft deltas, derive a moveElement op, dispatch it,
509
+ * then clear the CSS vars and draft state.
510
+ *
511
+ * No-ops when:
512
+ * - No applyDraft was called (nothing to commit)
513
+ * - No dispatch callback was provided at construction
514
+ */
515
+ commitPreview() {
516
+ if (!this._draftId || !this._draftEl || !this._dispatch) {
517
+ this._clearDraft();
518
+ return;
519
+ }
520
+ const el = this._draftEl;
521
+ const dx = parseFloat(el.style.getPropertyValue(VAR_DX) || "0") || 0;
522
+ const dy = parseFloat(el.style.getPropertyValue(VAR_DY) || "0") || 0;
523
+ const dataX = el.getAttribute("data-x");
524
+ const dataY = el.getAttribute("data-y");
525
+ const { x, y } = computeDraftPosition(dataX, dataY, dx, dy);
526
+ this._dispatch({ type: "moveElement", target: this._draftId, x, y });
527
+ this._clearDraft();
528
+ }
529
+ /** Revert draft CSS vars without dispatching any op. */
530
+ cancelPreview() {
531
+ this._clearDraft();
532
+ }
533
+ _clearDraft() {
534
+ if (this._draftEl) {
535
+ this._draftEl.style.removeProperty(VAR_DX);
536
+ this._draftEl.style.removeProperty(VAR_DY);
537
+ }
538
+ this._draftId = null;
539
+ this._draftEl = null;
540
+ }
541
+ // Selection -----------------------------------------------------------------
542
+ select(ids, opts) {
543
+ if (opts?.additive) {
544
+ const merged = new Set([...this._selection, ...ids]);
545
+ this._selection = [...merged];
546
+ }
547
+ else {
548
+ this._selection = [...ids];
549
+ }
550
+ this._emit();
551
+ }
552
+ on(event, handler) {
553
+ if (event !== "selection")
554
+ return () => { };
555
+ this._handlers.push(handler);
556
+ return () => {
557
+ this._handlers = this._handlers.filter((h) => h !== handler);
558
+ };
559
+ }
560
+ _emit() {
561
+ const ids = [...this._selection];
562
+ for (const h of this._handlers)
563
+ h(ids);
564
+ }
565
+ }
566
+ export function createIframePreviewAdapter(iframe, dispatch) {
567
+ return new IframePreviewAdapter(iframe, dispatch);
568
+ }
569
+ //# sourceMappingURL=iframe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"iframe.js","sourceRoot":"","sources":["../../src/adapters/iframe.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { PersistAdapter } from "./types.js";
2
+ export declare function createMemoryAdapter(): PersistAdapter & {
3
+ injectFault(message: string): void;
4
+ };
5
+ //# sourceMappingURL=memory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../../src/adapters/memory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAuB,MAAM,YAAY,CAAC;AA2DtE,wBAAgB,mBAAmB,IAAI,cAAc,GAAG;IAAE,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAE7F"}
@@ -0,0 +1,54 @@
1
+ class MemoryAdapter {
2
+ store = new Map();
3
+ history = new Map();
4
+ errorListeners = [];
5
+ versionCounter = 0;
6
+ faultMessage = null;
7
+ async read(path) {
8
+ return this.store.get(path);
9
+ }
10
+ async write(path, content) {
11
+ if (this.faultMessage !== null) {
12
+ const msg = this.faultMessage;
13
+ this.faultMessage = null;
14
+ this.errorListeners.forEach((l) => l({ error: { message: msg } }));
15
+ return;
16
+ }
17
+ this.store.set(path, content);
18
+ const hist = this.history.get(path) ?? [];
19
+ const entry = {
20
+ key: `v${++this.versionCounter}`,
21
+ content,
22
+ };
23
+ hist.unshift(entry);
24
+ this.history.set(path, hist);
25
+ }
26
+ async flush() {
27
+ // Memory adapter writes are synchronous — nothing to drain.
28
+ }
29
+ async listVersions(path) {
30
+ return [...(this.history.get(path) ?? [])];
31
+ }
32
+ async loadFrom(path, versionKey) {
33
+ const hist = this.history.get(path) ?? [];
34
+ return hist.find((v) => v.key === versionKey)?.content;
35
+ }
36
+ on(event, handler) {
37
+ if (event !== "persist:error")
38
+ return () => { };
39
+ this.errorListeners.push(handler);
40
+ return () => {
41
+ const idx = this.errorListeners.indexOf(handler);
42
+ if (idx !== -1)
43
+ this.errorListeners.splice(idx, 1);
44
+ };
45
+ }
46
+ /** Test helper — next write fires persist:error instead of committing */
47
+ injectFault(message) {
48
+ this.faultMessage = message;
49
+ }
50
+ }
51
+ export function createMemoryAdapter() {
52
+ return new MemoryAdapter();
53
+ }
54
+ //# sourceMappingURL=memory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory.js","sourceRoot":"","sources":["../../src/adapters/memory.ts"],"names":[],"mappings":"AAGA,MAAM,aAAa;IACA,KAAK,GAAG,IAAI,GAAG,EAAkB,CAAC;IAClC,OAAO,GAAG,IAAI,GAAG,EAAiC,CAAC;IACnD,cAAc,GAA0C,EAAE,CAAC;IACpE,cAAc,GAAG,CAAC,CAAC;IACnB,YAAY,GAAkB,IAAI,CAAC;IAE3C,KAAK,CAAC,IAAI,CAAC,IAAY;QACrB,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC9B,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,IAAY,EAAE,OAAe;QACvC,IAAI,IAAI,CAAC,YAAY,KAAK,IAAI,EAAE,CAAC;YAC/B,MAAM,GAAG,GAAG,IAAI,CAAC,YAAY,CAAC;YAC9B,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;YACzB,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC;YACnE,OAAO;QACT,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC9B,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QAC1C,MAAM,KAAK,GAAwB;YACjC,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,cAAc,EAAE;YAChC,OAAO;SACR,CAAC;QACF,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACpB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC/B,CAAC;IAED,KAAK,CAAC,KAAK;QACT,4DAA4D;IAC9D,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,IAAY;QAC7B,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IAC7C,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,IAAY,EAAE,UAAkB;QAC7C,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QAC1C,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,UAAU,CAAC,EAAE,OAAO,CAAC;IACzD,CAAC;IAED,EAAE,CAAC,KAAsB,EAAE,OAAuC;QAChE,IAAI,KAAK,KAAK,eAAe;YAAE,OAAO,GAAG,EAAE,GAAE,CAAC,CAAC;QAC/C,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAClC,OAAO,GAAG,EAAE;YACV,MAAM,GAAG,GAAG,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YACjD,IAAI,GAAG,KAAK,CAAC,CAAC;gBAAE,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACrD,CAAC,CAAC;IACJ,CAAC;IAED,yEAAyE;IACzE,WAAW,CAAC,OAAe;QACzB,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC;IAC9B,CAAC;CACF;AAED,MAAM,UAAU,mBAAmB;IACjC,OAAO,IAAI,aAAa,EAAE,CAAC;AAC7B,CAAC"}