@hyperframes/studio 0.6.37 → 0.6.39

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.html CHANGED
@@ -5,7 +5,7 @@
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
6
6
  <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
7
7
  <title>HyperFrames Studio</title>
8
- <script type="module" crossorigin src="/assets/index-CMBmEncK.js"></script>
8
+ <script type="module" crossorigin src="/assets/index-C55KfVpx.js"></script>
9
9
  <link rel="stylesheet" crossorigin href="/assets/index-SKRp8mGz.css">
10
10
  </head>
11
11
  <body>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hyperframes/studio",
3
- "version": "0.6.37",
3
+ "version": "0.6.39",
4
4
  "description": "",
5
5
  "repository": {
6
6
  "type": "git",
@@ -31,8 +31,8 @@
31
31
  "@codemirror/view": "6.40.0",
32
32
  "@phosphor-icons/react": "^2.1.10",
33
33
  "mediabunny": "^1.45.3",
34
- "@hyperframes/core": "0.6.37",
35
- "@hyperframes/player": "0.6.37"
34
+ "@hyperframes/core": "0.6.39",
35
+ "@hyperframes/player": "0.6.39"
36
36
  },
37
37
  "devDependencies": {
38
38
  "@types/react": "19",
@@ -46,7 +46,7 @@
46
46
  "vite": "^6.4.2",
47
47
  "vitest": "^3.2.4",
48
48
  "zustand": "^5.0.0",
49
- "@hyperframes/producer": "0.6.37"
49
+ "@hyperframes/producer": "0.6.39"
50
50
  },
51
51
  "peerDependencies": {
52
52
  "react": "19",
@@ -31,12 +31,6 @@ import {
31
31
  STUDIO_ROTATION_TRANSFORM_ORIGIN,
32
32
  } from "./manualEditsTypes";
33
33
  import { roundRotationAngle } from "./manualEditsParsing";
34
- import {
35
- STUDIO_MOTION_ATTR,
36
- STUDIO_MOTION_ORIGINAL_TRANSFORM_ATTR,
37
- STUDIO_MOTION_ORIGINAL_OPACITY_ATTR,
38
- STUDIO_MOTION_ORIGINAL_VISIBILITY_ATTR,
39
- } from "./studioMotionTypes";
40
34
  import { applyStudioMotionFromDom } from "./studioMotion";
41
35
 
42
36
  /* ── Gesture tracking ─────────────────────────────────────────────── */
@@ -221,24 +215,28 @@ function writeStudioPathOffsetVars(
221
215
  // into element.style.transform (as a matrix) on every seek. When the studio's reapply hook also
222
216
  // writes `translate`, both properties compose additively, doubling the visual offset. This helper
223
217
  // zeroes out only the translate component (m41/m42) so the `translate` prop isn't double-counted.
218
+ function isIdentityAfterTranslateStrip(m: DOMMatrix): boolean {
219
+ return m.is2D && m.a === 1 && m.b === 0 && m.c === 0 && m.d === 1;
220
+ }
221
+
224
222
  function stripGsapTranslateFromTransform(element: HTMLElement): void {
225
223
  const transform = element.style.getPropertyValue("transform");
226
224
  if (!transform || transform === "none") return;
227
- const win = element.ownerDocument.defaultView as (Window & typeof globalThis) | null;
228
- const DOMMatrixCtor = (win as unknown as { DOMMatrix?: typeof DOMMatrix })?.DOMMatrix;
225
+ const DOMMatrixCtor = (element.ownerDocument.defaultView as (Window & typeof globalThis) | null)
226
+ ?.DOMMatrix;
229
227
  if (!DOMMatrixCtor) return;
230
228
  try {
231
229
  const m = new DOMMatrixCtor(transform);
232
230
  if (m.m41 === 0 && m.m42 === 0) return;
233
231
  m.m41 = 0;
234
232
  m.m42 = 0;
235
- if (m.is2D && m.a === 1 && m.b === 0 && m.c === 0 && m.d === 1) {
233
+ if (isIdentityAfterTranslateStrip(m)) {
236
234
  element.style.removeProperty("transform");
237
235
  } else {
238
236
  element.style.setProperty("transform", m.toString());
239
237
  }
240
238
  } catch {
241
- // non-parseable transform or DOMMatrix unavailable — leave as-is
239
+ /* non-parseable transform — leave as-is */
242
240
  }
243
241
  }
244
242
 
@@ -464,351 +462,30 @@ export function applyStudioRotationDraft(element: HTMLElement, rotation: { angle
464
462
  );
465
463
  }
466
464
 
467
- /* ── HTML patch builders ──────────────────────────────────────────── */
468
- import type { PatchOperation } from "../../utils/sourcePatcher";
469
-
470
- export function buildPathOffsetPatches(element: HTMLElement): PatchOperation[] {
471
- const x = element.style.getPropertyValue(STUDIO_OFFSET_X_PROP);
472
- const y = element.style.getPropertyValue(STUDIO_OFFSET_Y_PROP);
473
- const translate = element.style.getPropertyValue("translate");
474
- const originalTranslate = element.getAttribute(STUDIO_ORIGINAL_TRANSLATE_ATTR);
475
- const originalInlineTranslate = element.getAttribute(STUDIO_ORIGINAL_INLINE_TRANSLATE_ATTR);
476
- const displayVal = element.style.getPropertyValue("display");
477
- const transformDisplayAttr = element.getAttribute(STUDIO_ORIGINAL_TRANSFORM_DISPLAY_ATTR);
478
- const ops: PatchOperation[] = [];
479
- if (x) ops.push({ type: "inline-style", property: STUDIO_OFFSET_X_PROP, value: x });
480
- if (y) ops.push({ type: "inline-style", property: STUDIO_OFFSET_Y_PROP, value: y });
481
- if (translate) ops.push({ type: "inline-style", property: "translate", value: translate });
482
- ops.push({ type: "attribute", property: STUDIO_PATH_OFFSET_ATTR, value: "true" });
483
- if (originalTranslate !== null)
484
- ops.push({
485
- type: "attribute",
486
- property: STUDIO_ORIGINAL_TRANSLATE_ATTR,
487
- value: originalTranslate,
488
- });
489
- if (originalInlineTranslate !== null)
490
- ops.push({
491
- type: "attribute",
492
- property: STUDIO_ORIGINAL_INLINE_TRANSLATE_ATTR,
493
- value: originalInlineTranslate,
494
- });
495
- if (displayVal) ops.push({ type: "inline-style", property: "display", value: displayVal });
496
- if (transformDisplayAttr !== null)
497
- ops.push({
498
- type: "attribute",
499
- property: STUDIO_ORIGINAL_TRANSFORM_DISPLAY_ATTR,
500
- value: transformDisplayAttr,
501
- });
502
- return ops;
503
- }
504
-
505
- export function buildClearPathOffsetPatches(element: HTMLElement): PatchOperation[] {
506
- const originalInlineTranslate = element.getAttribute(STUDIO_ORIGINAL_INLINE_TRANSLATE_ATTR);
507
- const ops: PatchOperation[] = [
508
- { type: "inline-style", property: STUDIO_OFFSET_X_PROP, value: null },
509
- { type: "inline-style", property: STUDIO_OFFSET_Y_PROP, value: null },
510
- {
511
- type: "inline-style",
512
- property: "translate",
513
- value: originalInlineTranslate || null,
514
- },
515
- { type: "attribute", property: STUDIO_PATH_OFFSET_ATTR, value: null },
516
- { type: "attribute", property: STUDIO_ORIGINAL_TRANSLATE_ATTR, value: null },
517
- { type: "attribute", property: STUDIO_ORIGINAL_INLINE_TRANSLATE_ATTR, value: null },
518
- ];
519
- const origDisplay = element.getAttribute(STUDIO_ORIGINAL_TRANSFORM_DISPLAY_ATTR);
520
- if (origDisplay !== null) {
521
- ops.push({ type: "inline-style", property: "display", value: origDisplay || null });
522
- ops.push({ type: "attribute", property: STUDIO_ORIGINAL_TRANSFORM_DISPLAY_ATTR, value: null });
523
- }
524
- return ops;
525
- }
526
-
527
- export function buildBoxSizePatches(element: HTMLElement): PatchOperation[] {
528
- const ops: PatchOperation[] = [];
529
-
530
- const studioWidth = element.style.getPropertyValue(STUDIO_WIDTH_PROP);
531
- const studioHeight = element.style.getPropertyValue(STUDIO_HEIGHT_PROP);
532
- if (studioWidth)
533
- ops.push({ type: "inline-style", property: STUDIO_WIDTH_PROP, value: studioWidth });
534
- if (studioHeight)
535
- ops.push({ type: "inline-style", property: STUDIO_HEIGHT_PROP, value: studioHeight });
536
-
537
- const width = element.style.getPropertyValue("width");
538
- const height = element.style.getPropertyValue("height");
539
- const minWidth = element.style.getPropertyValue("min-width");
540
- const minHeight = element.style.getPropertyValue("min-height");
541
- const maxWidth = element.style.getPropertyValue("max-width");
542
- const maxHeight = element.style.getPropertyValue("max-height");
543
- const flexBasis = element.style.getPropertyValue("flex-basis");
544
- const flexGrow = element.style.getPropertyValue("flex-grow");
545
- const flexShrink = element.style.getPropertyValue("flex-shrink");
546
- const boxSizing = element.style.getPropertyValue("box-sizing");
547
- const scale = element.style.getPropertyValue("scale");
548
- const transformOrigin = element.style.getPropertyValue("transform-origin");
549
- const displayVal = element.style.getPropertyValue("display");
550
-
551
- if (width) ops.push({ type: "inline-style", property: "width", value: width });
552
- if (height) ops.push({ type: "inline-style", property: "height", value: height });
553
- if (minWidth) ops.push({ type: "inline-style", property: "min-width", value: minWidth });
554
- if (minHeight) ops.push({ type: "inline-style", property: "min-height", value: minHeight });
555
- if (maxWidth) ops.push({ type: "inline-style", property: "max-width", value: maxWidth });
556
- if (maxHeight) ops.push({ type: "inline-style", property: "max-height", value: maxHeight });
557
- if (flexBasis) ops.push({ type: "inline-style", property: "flex-basis", value: flexBasis });
558
- if (flexGrow) ops.push({ type: "inline-style", property: "flex-grow", value: flexGrow });
559
- if (flexShrink) ops.push({ type: "inline-style", property: "flex-shrink", value: flexShrink });
560
- if (boxSizing) ops.push({ type: "inline-style", property: "box-sizing", value: boxSizing });
561
- if (scale) ops.push({ type: "inline-style", property: "scale", value: scale });
562
- if (transformOrigin)
563
- ops.push({ type: "inline-style", property: "transform-origin", value: transformOrigin });
564
- if (displayVal) ops.push({ type: "inline-style", property: "display", value: displayVal });
565
-
566
- ops.push({ type: "attribute", property: STUDIO_BOX_SIZE_ATTR, value: "true" });
567
-
568
- const origWidth = element.getAttribute(STUDIO_ORIGINAL_WIDTH_ATTR);
569
- const origHeight = element.getAttribute(STUDIO_ORIGINAL_HEIGHT_ATTR);
570
- const origMinWidth = element.getAttribute(STUDIO_ORIGINAL_MIN_WIDTH_ATTR);
571
- const origMinHeight = element.getAttribute(STUDIO_ORIGINAL_MIN_HEIGHT_ATTR);
572
- const origMaxWidth = element.getAttribute(STUDIO_ORIGINAL_MAX_WIDTH_ATTR);
573
- const origMaxHeight = element.getAttribute(STUDIO_ORIGINAL_MAX_HEIGHT_ATTR);
574
- const origFlexBasis = element.getAttribute(STUDIO_ORIGINAL_FLEX_BASIS_ATTR);
575
- const origFlexGrow = element.getAttribute(STUDIO_ORIGINAL_FLEX_GROW_ATTR);
576
- const origFlexShrink = element.getAttribute(STUDIO_ORIGINAL_FLEX_SHRINK_ATTR);
577
- const origBoxSizing = element.getAttribute(STUDIO_ORIGINAL_BOX_SIZING_ATTR);
578
- const origScale = element.getAttribute(STUDIO_ORIGINAL_SCALE_ATTR);
579
- const origTransformOrigin = element.getAttribute(STUDIO_ORIGINAL_TRANSFORM_ORIGIN_ATTR);
580
- const origDisplay = element.getAttribute(STUDIO_ORIGINAL_DISPLAY_ATTR);
581
- const origTransformDisplay = element.getAttribute(STUDIO_ORIGINAL_TRANSFORM_DISPLAY_ATTR);
582
-
583
- if (origWidth !== null)
584
- ops.push({ type: "attribute", property: STUDIO_ORIGINAL_WIDTH_ATTR, value: origWidth });
585
- if (origHeight !== null)
586
- ops.push({ type: "attribute", property: STUDIO_ORIGINAL_HEIGHT_ATTR, value: origHeight });
587
- if (origMinWidth !== null)
588
- ops.push({ type: "attribute", property: STUDIO_ORIGINAL_MIN_WIDTH_ATTR, value: origMinWidth });
589
- if (origMinHeight !== null)
590
- ops.push({
591
- type: "attribute",
592
- property: STUDIO_ORIGINAL_MIN_HEIGHT_ATTR,
593
- value: origMinHeight,
594
- });
595
- if (origMaxWidth !== null)
596
- ops.push({ type: "attribute", property: STUDIO_ORIGINAL_MAX_WIDTH_ATTR, value: origMaxWidth });
597
- if (origMaxHeight !== null)
598
- ops.push({
599
- type: "attribute",
600
- property: STUDIO_ORIGINAL_MAX_HEIGHT_ATTR,
601
- value: origMaxHeight,
602
- });
603
- if (origFlexBasis !== null)
604
- ops.push({
605
- type: "attribute",
606
- property: STUDIO_ORIGINAL_FLEX_BASIS_ATTR,
607
- value: origFlexBasis,
608
- });
609
- if (origFlexGrow !== null)
610
- ops.push({ type: "attribute", property: STUDIO_ORIGINAL_FLEX_GROW_ATTR, value: origFlexGrow });
611
- if (origFlexShrink !== null)
612
- ops.push({
613
- type: "attribute",
614
- property: STUDIO_ORIGINAL_FLEX_SHRINK_ATTR,
615
- value: origFlexShrink,
616
- });
617
- if (origBoxSizing !== null)
618
- ops.push({
619
- type: "attribute",
620
- property: STUDIO_ORIGINAL_BOX_SIZING_ATTR,
621
- value: origBoxSizing,
622
- });
623
- if (origScale !== null)
624
- ops.push({ type: "attribute", property: STUDIO_ORIGINAL_SCALE_ATTR, value: origScale });
625
- if (origTransformOrigin !== null)
626
- ops.push({
627
- type: "attribute",
628
- property: STUDIO_ORIGINAL_TRANSFORM_ORIGIN_ATTR,
629
- value: origTransformOrigin,
630
- });
631
- if (origDisplay !== null)
632
- ops.push({ type: "attribute", property: STUDIO_ORIGINAL_DISPLAY_ATTR, value: origDisplay });
633
- if (origTransformDisplay !== null)
634
- ops.push({
635
- type: "attribute",
636
- property: STUDIO_ORIGINAL_TRANSFORM_DISPLAY_ATTR,
637
- value: origTransformDisplay,
638
- });
639
-
640
- return ops;
641
- }
642
-
643
- export function buildClearBoxSizePatches(element: HTMLElement): PatchOperation[] {
644
- const ops: PatchOperation[] = [
645
- { type: "inline-style", property: STUDIO_WIDTH_PROP, value: null },
646
- { type: "inline-style", property: STUDIO_HEIGHT_PROP, value: null },
647
- { type: "attribute", property: STUDIO_BOX_SIZE_ATTR, value: null },
648
- ];
649
-
650
- const origAttrs: Array<[string, string]> = [
651
- [STUDIO_ORIGINAL_WIDTH_ATTR, "width"],
652
- [STUDIO_ORIGINAL_HEIGHT_ATTR, "height"],
653
- [STUDIO_ORIGINAL_MIN_WIDTH_ATTR, "min-width"],
654
- [STUDIO_ORIGINAL_MIN_HEIGHT_ATTR, "min-height"],
655
- [STUDIO_ORIGINAL_MAX_WIDTH_ATTR, "max-width"],
656
- [STUDIO_ORIGINAL_MAX_HEIGHT_ATTR, "max-height"],
657
- [STUDIO_ORIGINAL_FLEX_BASIS_ATTR, "flex-basis"],
658
- [STUDIO_ORIGINAL_FLEX_GROW_ATTR, "flex-grow"],
659
- [STUDIO_ORIGINAL_FLEX_SHRINK_ATTR, "flex-shrink"],
660
- [STUDIO_ORIGINAL_BOX_SIZING_ATTR, "box-sizing"],
661
- [STUDIO_ORIGINAL_SCALE_ATTR, "scale"],
662
- [STUDIO_ORIGINAL_TRANSFORM_ORIGIN_ATTR, "transform-origin"],
663
- [STUDIO_ORIGINAL_DISPLAY_ATTR, "display"],
664
- ];
665
-
666
- for (const [attrName, styleProp] of origAttrs) {
667
- const origVal = element.getAttribute(attrName);
668
- if (origVal !== null) {
669
- ops.push({ type: "inline-style", property: styleProp, value: origVal || null });
670
- }
671
- ops.push({ type: "attribute", property: attrName, value: null });
672
- }
673
-
674
- const origTransformDisplay = element.getAttribute(STUDIO_ORIGINAL_TRANSFORM_DISPLAY_ATTR);
675
- if (origTransformDisplay !== null) {
676
- ops.push({ type: "inline-style", property: "display", value: origTransformDisplay || null });
677
- ops.push({ type: "attribute", property: STUDIO_ORIGINAL_TRANSFORM_DISPLAY_ATTR, value: null });
678
- }
465
+ /* ── HTML patch builders (re-exported from manualEditsDomPatches) ── */
466
+ export {
467
+ buildPathOffsetPatches,
468
+ buildClearPathOffsetPatches,
469
+ buildBoxSizePatches,
470
+ buildClearBoxSizePatches,
471
+ buildRotationPatches,
472
+ buildClearRotationPatches,
473
+ buildMotionPatches,
474
+ buildClearMotionPatches,
475
+ } from "./manualEditsDomPatches";
679
476
 
680
- return ops;
681
- }
682
-
683
- export function buildRotationPatches(element: HTMLElement): PatchOperation[] {
684
- const ops: PatchOperation[] = [];
685
-
686
- const studioRotation = element.style.getPropertyValue(STUDIO_ROTATION_PROP);
687
- const rotate = element.style.getPropertyValue("rotate");
688
- const transformOrigin = element.style.getPropertyValue("transform-origin");
689
- const displayVal = element.style.getPropertyValue("display");
690
-
691
- if (studioRotation)
692
- ops.push({ type: "inline-style", property: STUDIO_ROTATION_PROP, value: studioRotation });
693
- if (rotate) ops.push({ type: "inline-style", property: "rotate", value: rotate });
694
- if (transformOrigin)
695
- ops.push({ type: "inline-style", property: "transform-origin", value: transformOrigin });
696
- if (displayVal) ops.push({ type: "inline-style", property: "display", value: displayVal });
697
-
698
- ops.push({ type: "attribute", property: STUDIO_ROTATION_ATTR, value: "true" });
477
+ /* ── Seek reapply (position + motion) ────────────────────────────── */
699
478
 
700
- const origRotate = element.getAttribute(STUDIO_ORIGINAL_ROTATE_ATTR);
701
- const origInlineRotate = element.getAttribute(STUDIO_ORIGINAL_INLINE_ROTATE_ATTR);
702
- const origRotationTransformOrigin = element.getAttribute(
703
- STUDIO_ORIGINAL_ROTATION_TRANSFORM_ORIGIN_ATTR,
479
+ function queryStudioElements(doc: Document, attr: string): HTMLElement[] {
480
+ const ctor = doc.defaultView?.HTMLElement;
481
+ if (!ctor) return [];
482
+ return Array.from(doc.querySelectorAll(`[${attr}="true"]`)).filter(
483
+ (el): el is HTMLElement => el instanceof ctor,
704
484
  );
705
- const origTransformDisplay = element.getAttribute(STUDIO_ORIGINAL_TRANSFORM_DISPLAY_ATTR);
706
-
707
- if (origRotate !== null)
708
- ops.push({ type: "attribute", property: STUDIO_ORIGINAL_ROTATE_ATTR, value: origRotate });
709
- if (origInlineRotate !== null)
710
- ops.push({
711
- type: "attribute",
712
- property: STUDIO_ORIGINAL_INLINE_ROTATE_ATTR,
713
- value: origInlineRotate,
714
- });
715
- if (origRotationTransformOrigin !== null)
716
- ops.push({
717
- type: "attribute",
718
- property: STUDIO_ORIGINAL_ROTATION_TRANSFORM_ORIGIN_ATTR,
719
- value: origRotationTransformOrigin,
720
- });
721
- if (origTransformDisplay !== null)
722
- ops.push({
723
- type: "attribute",
724
- property: STUDIO_ORIGINAL_TRANSFORM_DISPLAY_ATTR,
725
- value: origTransformDisplay,
726
- });
727
-
728
- return ops;
729
- }
730
-
731
- export function buildClearRotationPatches(element: HTMLElement): PatchOperation[] {
732
- const origInlineRotate = element.getAttribute(STUDIO_ORIGINAL_INLINE_ROTATE_ATTR);
733
- const origRotationTransformOrigin = element.getAttribute(
734
- STUDIO_ORIGINAL_ROTATION_TRANSFORM_ORIGIN_ATTR,
735
- );
736
- const ops: PatchOperation[] = [
737
- { type: "inline-style", property: STUDIO_ROTATION_PROP, value: null },
738
- { type: "inline-style", property: "rotate", value: origInlineRotate || null },
739
- {
740
- type: "inline-style",
741
- property: "transform-origin",
742
- value: origRotationTransformOrigin !== null ? origRotationTransformOrigin || null : null,
743
- },
744
- { type: "attribute", property: STUDIO_ROTATION_ATTR, value: null },
745
- { type: "attribute", property: STUDIO_ROTATION_DRAFT_ATTR, value: null },
746
- { type: "attribute", property: STUDIO_ORIGINAL_ROTATE_ATTR, value: null },
747
- { type: "attribute", property: STUDIO_ORIGINAL_INLINE_ROTATE_ATTR, value: null },
748
- { type: "attribute", property: STUDIO_ORIGINAL_ROTATION_TRANSFORM_ORIGIN_ATTR, value: null },
749
- ];
750
- const origTransformDisplay = element.getAttribute(STUDIO_ORIGINAL_TRANSFORM_DISPLAY_ATTR);
751
- if (origTransformDisplay !== null) {
752
- ops.push({ type: "inline-style", property: "display", value: origTransformDisplay || null });
753
- ops.push({ type: "attribute", property: STUDIO_ORIGINAL_TRANSFORM_DISPLAY_ATTR, value: null });
754
- }
755
- return ops;
756
- }
757
-
758
- /* ── Motion HTML patch builders ──────────────────────────────────── */
759
-
760
- export function buildMotionPatches(element: HTMLElement): PatchOperation[] {
761
- const motionJson = element.getAttribute(STUDIO_MOTION_ATTR);
762
- if (!motionJson) return [];
763
- const ops: PatchOperation[] = [
764
- { type: "attribute", property: STUDIO_MOTION_ATTR, value: motionJson },
765
- ];
766
- const origTransform = element.getAttribute(STUDIO_MOTION_ORIGINAL_TRANSFORM_ATTR);
767
- if (origTransform !== null) {
768
- ops.push({
769
- type: "attribute",
770
- property: STUDIO_MOTION_ORIGINAL_TRANSFORM_ATTR,
771
- value: origTransform,
772
- });
773
- }
774
- const origOpacity = element.getAttribute(STUDIO_MOTION_ORIGINAL_OPACITY_ATTR);
775
- if (origOpacity !== null) {
776
- ops.push({
777
- type: "attribute",
778
- property: STUDIO_MOTION_ORIGINAL_OPACITY_ATTR,
779
- value: origOpacity,
780
- });
781
- }
782
- const origVisibility = element.getAttribute(STUDIO_MOTION_ORIGINAL_VISIBILITY_ATTR);
783
- if (origVisibility !== null) {
784
- ops.push({
785
- type: "attribute",
786
- property: STUDIO_MOTION_ORIGINAL_VISIBILITY_ATTR,
787
- value: origVisibility,
788
- });
789
- }
790
- return ops;
791
- }
792
-
793
- export function buildClearMotionPatches(_element: HTMLElement): PatchOperation[] {
794
- return [
795
- { type: "attribute", property: STUDIO_MOTION_ATTR, value: null },
796
- { type: "attribute", property: STUDIO_MOTION_ORIGINAL_TRANSFORM_ATTR, value: null },
797
- { type: "attribute", property: STUDIO_MOTION_ORIGINAL_OPACITY_ATTR, value: null },
798
- { type: "attribute", property: STUDIO_MOTION_ORIGINAL_VISIBILITY_ATTR, value: null },
799
- ];
800
485
  }
801
486
 
802
- /* ── Seek reapply (position + motion) ────────────────────────────── */
803
-
804
- export function reapplyPositionEditsAfterSeek(doc: Document): void {
805
- const htmlElement = doc.defaultView?.HTMLElement;
806
- if (!htmlElement) return;
807
-
808
- const offsetEls = Array.from(doc.querySelectorAll(`[${STUDIO_PATH_OFFSET_ATTR}="true"]`)).filter(
809
- (el): el is HTMLElement => el instanceof htmlElement,
810
- );
811
- for (const el of offsetEls) {
487
+ function reapplyPathOffsets(doc: Document): void {
488
+ for (const el of queryStudioElements(doc, STUDIO_PATH_OFFSET_ATTR)) {
812
489
  const x = el.style.getPropertyValue(STUDIO_OFFSET_X_PROP);
813
490
  const y = el.style.getPropertyValue(STUDIO_OFFSET_Y_PROP);
814
491
  if (x || y) {
@@ -818,28 +495,30 @@ export function reapplyPositionEditsAfterSeek(doc: Document): void {
818
495
  });
819
496
  }
820
497
  }
498
+ }
821
499
 
822
- const boxSizeEls = Array.from(doc.querySelectorAll(`[${STUDIO_BOX_SIZE_ATTR}="true"]`)).filter(
823
- (el): el is HTMLElement => el instanceof htmlElement,
824
- );
825
- for (const el of boxSizeEls) {
500
+ function reapplyBoxSizes(doc: Document): void {
501
+ for (const el of queryStudioElements(doc, STUDIO_BOX_SIZE_ATTR)) {
826
502
  const w = Number.parseFloat(el.style.getPropertyValue(STUDIO_WIDTH_PROP));
827
503
  const h = Number.parseFloat(el.style.getPropertyValue(STUDIO_HEIGHT_PROP));
828
504
  if (Number.isFinite(w) && Number.isFinite(h) && w > 0 && h > 0) {
829
505
  applyStudioBoxSize(el, { width: w, height: h });
830
506
  }
831
507
  }
508
+ }
832
509
 
833
- const rotationEls = Array.from(doc.querySelectorAll(`[${STUDIO_ROTATION_ATTR}="true"]`)).filter(
834
- (el): el is HTMLElement => el instanceof htmlElement,
835
- );
836
- for (const el of rotationEls) {
510
+ function reapplyRotations(doc: Document): void {
511
+ for (const el of queryStudioElements(doc, STUDIO_ROTATION_ATTR)) {
837
512
  const angle = Number.parseFloat(el.style.getPropertyValue(STUDIO_ROTATION_PROP));
838
513
  if (Number.isFinite(angle)) {
839
514
  applyStudioRotation(el, { angle });
840
515
  }
841
516
  }
517
+ }
842
518
 
843
- // Reapply DOM-backed motion timeline after seek
519
+ export function reapplyPositionEditsAfterSeek(doc: Document): void {
520
+ reapplyPathOffsets(doc);
521
+ reapplyBoxSizes(doc);
522
+ reapplyRotations(doc);
844
523
  applyStudioMotionFromDom(doc);
845
524
  }