@hyperframes/parsers 0.8.98 → 0.8.99

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.
@@ -62,6 +62,7 @@ interface GsapAnimation {
62
62
  hasUnresolvedKeyframes?: boolean;
63
63
  /** True when the tween's target selector couldn't be statically resolved (dynamic). */
64
64
  hasUnresolvedSelector?: boolean;
65
+ hasPartialSelector?: boolean;
65
66
  /** Absolute start time computed by walking the timeline chain (handles +=, -=, <, >, labels). */
66
67
  resolvedStart?: number;
67
68
  /** True when no position arg was authored — the tween is sequentially placed by GSAP. */
@@ -1,27 +1,37 @@
1
- import { G as GsapAnimation, A as ArcPathConfig, g as SplitAnimationsOptions, h as SplitAnimationsResult, a as ArcPathSegment } from './gsapSerialize-b8lNzSbI.js';
1
+ import { G as GsapAnimation, A as ArcPathConfig, g as SplitAnimationsOptions, h as SplitAnimationsResult, a as ArcPathSegment } from './gsapSerialize-D92cSJOu.js';
2
2
  import './types-Y0NXTiVo.js';
3
3
  import './gsapConstants.js';
4
4
 
5
+ type TweenTarget = Pick<GsapAnimation, "targetSelector" | "hasPartialSelector">;
6
+ type TweenTime = Pick<GsapAnimation, "position" | "implicitPosition">;
7
+ declare function clipTweenMatcher(clipSelectors: string | readonly string[], root?: ParentNode): (tween: TweenTarget) => boolean;
8
+ /** Where a GSAP script's clips live: linkedom keeps a `<template>`'s children under it, out of document queries. */
9
+ declare function clipQueryRoot(script: Element): ParentNode;
10
+ /** A written position; an implicit one follows the tween before it and must stay unwritten. */
11
+ declare function hasExplicitTime<T extends TweenTime>(animation: T): animation is T & {
12
+ position: number;
13
+ };
14
+
5
15
  declare function updateAnimationInScript(script: string, animationId: string, updates: Partial<GsapAnimation> & {
6
16
  easeEach?: string;
7
17
  resetKeyframeEases?: boolean;
8
18
  }): string;
9
19
  /**
10
- * Shift every tween targeting `targetSelector` by `delta` seconds (clamped ≥0),
20
+ * Shift every tween the clip at `targetSelector` carries by `delta` seconds (clamped ≥0),
11
21
  * rewriting each call's position argument. Mirrors recast's shiftPositionsInScript
12
22
  * (used by timeline clip-move to keep GSAP positions in sync with the clip start).
13
23
  */
14
- declare function shiftPositionsInScript(script: string, targetSelector: string, delta: number): string;
24
+ declare function shiftPositionsInScript(script: string, targetSelector: string, delta: number, root?: ParentNode): string;
15
25
  /** Copies each tween on `fromSelector` for `toSelector`, `delta` seconds later, in its own argument text. Exact or
16
26
  * absent: only a tween at a number, written straight in the timeline's own block, is copied. */
17
27
  declare function copyAnimationsInScript(script: string, fromSelector: string, toSelector: string, delta: number): string;
18
28
  /**
19
- * Linearly remap every tween targeting `targetSelector` from the old clip
29
+ * Linearly remap every tween the clip at `targetSelector` carries from the old clip
20
30
  * [oldStart, oldDuration] onto the new [newStart, newDuration] (position and,
21
31
  * when present, duration scaled by the duration ratio). Mirrors recast's
22
32
  * scalePositionsInScript (used by timeline clip-resize).
23
33
  */
24
- declare function scalePositionsInScript(script: string, targetSelector: string, oldStart: number, oldDuration: number, newStart: number, newDuration: number): string;
34
+ declare function scalePositionsInScript(script: string, targetSelector: string, oldStart: number, oldDuration: number, newStart: number, newDuration: number, root?: ParentNode): string;
25
35
  declare function addAnimationToScript(script: string, animation: Omit<GsapAnimation, "id">): {
26
36
  script: string;
27
37
  id: string;
@@ -151,4 +161,4 @@ type UnrollElement = {
151
161
  */
152
162
  declare function unrollDynamicAnimations(script: string, animationId: string, elements: UnrollElement[]): string;
153
163
 
154
- export { type UnrollElement, addAnimationToScript, addAnimationWithKeyframesToScript, addKeyframeToScript, addLabelToScript, addMotionPathPointInScript, addMotionPathToScript, convertToKeyframesFromScript, copyAnimationsInScript, dedupePositionWritesInScript, materializeKeyframesFromScript, moveKeyframeInScript, removeAllKeyframesFromScript, removeAnimationFromScript, removeArcPathFromScript, removeKeyframeFromScript, removeLabelFromScript, removeMotionPathPointInScript, removePropertyFromAnimation, resizeKeyframedTweenInScript, scalePositionsInScript, setArcPathInScript, shiftPositionsInScript, splitAnimationsInScript, splitIntoPropertyGroupsFromScript, syncPositionHoldsBeforeKeyframes, unrollDynamicAnimations, updateAnimationInScript, updateArcSegmentInScript, updateKeyframeInScript, updateMotionPathPointInScript };
164
+ export { type UnrollElement, addAnimationToScript, addAnimationWithKeyframesToScript, addKeyframeToScript, addLabelToScript, addMotionPathPointInScript, addMotionPathToScript, clipQueryRoot, clipTweenMatcher, convertToKeyframesFromScript, copyAnimationsInScript, dedupePositionWritesInScript, hasExplicitTime, materializeKeyframesFromScript, moveKeyframeInScript, removeAllKeyframesFromScript, removeAnimationFromScript, removeArcPathFromScript, removeKeyframeFromScript, removeLabelFromScript, removeMotionPathPointInScript, removePropertyFromAnimation, resizeKeyframedTweenInScript, scalePositionsInScript, setArcPathInScript, shiftPositionsInScript, splitAnimationsInScript, splitIntoPropertyGroupsFromScript, syncPositionHoldsBeforeKeyframes, unrollDynamicAnimations, updateAnimationInScript, updateArcSegmentInScript, updateKeyframeInScript, updateMotionPathPointInScript };
@@ -568,6 +568,11 @@ function resolveTargetSelector(node, ancestors, scope, bindings) {
568
568
  }
569
569
  return null;
570
570
  }
571
+ function hasUnresolvedArrayPart(node, ancestors, scope, bindings) {
572
+ return node?.type === "ArrayExpression" && node.elements.some(
573
+ (el) => !resolveTargetSelector(el, ancestors, scope, bindings) || hasUnresolvedArrayPart(el, ancestors, scope, bindings)
574
+ );
575
+ }
571
576
  function describeProxyTarget(targetNode, varsNode, scope) {
572
577
  const objNode = targetNode?.type === "ObjectExpression" ? targetNode : targetNode?.type === "Identifier" ? resolveConstNode(targetNode, scope) : void 0;
573
578
  if (objNode?.type !== "ObjectExpression") return null;
@@ -752,12 +757,14 @@ function findAllTweenCalls(ast, ref, scope, targetBindings) {
752
757
  const method = callee.property.name;
753
758
  const args = node.arguments;
754
759
  const selectorValue = args.length >= 1 ? resolveTargetSelector(args[0], nodeAncestors, scope, targetBindings) ?? "__unresolved__" : "__unresolved__";
760
+ const partial = hasUnresolvedArrayPart(args[0], nodeAncestors, scope, targetBindings) ? { selectorPartial: true } : {};
755
761
  if (method === "fromTo" && args.length >= 3) {
756
762
  results.push({
757
763
  node,
758
764
  ancestors: nodeAncestors,
759
765
  method: "fromTo",
760
766
  selector: selectorValue,
767
+ ...partial,
761
768
  fromArg: args[1],
762
769
  varsArg: args[2],
763
770
  positionArg: args[3]
@@ -768,6 +775,7 @@ function findAllTweenCalls(ast, ref, scope, targetBindings) {
768
775
  ancestors: nodeAncestors,
769
776
  method,
770
777
  selector: selectorValue,
778
+ ...partial,
771
779
  varsArg: args[1],
772
780
  positionArg: args[2],
773
781
  ...isGlobalSet ? { global: true } : {}
@@ -1105,6 +1113,7 @@ function tweenCallToAnimation(call, scope, source, identifierBindings) {
1105
1113
  if (hasUnresolvedKeyframes) anim.hasUnresolvedKeyframes = true;
1106
1114
  if (durationUnresolved) anim.durationUnresolved = true;
1107
1115
  if (selector === "__unresolved__") anim.hasUnresolvedSelector = true;
1116
+ if (call.selectorPartial) anim.hasPartialSelector = true;
1108
1117
  if (provenance) anim.provenance = provenance;
1109
1118
  return anim;
1110
1119
  }
@@ -1273,6 +1282,37 @@ function parseGsapScriptAcornForWrite(script) {
1273
1282
 
1274
1283
  // src/gsapWriterAcorn.ts
1275
1284
  import * as acornWalk2 from "acorn-walk";
1285
+
1286
+ // src/clipTweens.ts
1287
+ function clipTweenMatcher(clipSelectors, root) {
1288
+ const own = typeof clipSelectors === "string" ? [clipSelectors] : clipSelectors;
1289
+ const clips = root ? own.flatMap((selector) => queryAll(root, selector)) : [];
1290
+ return ({ targetSelector, hasPartialSelector }) => {
1291
+ if (hasPartialSelector) return false;
1292
+ if (own.includes(targetSelector)) return true;
1293
+ if (!root || clips.length === 0) return false;
1294
+ const targets = queryAll(root, targetSelector);
1295
+ return targets.length > 0 && targets.every((target) => {
1296
+ const owner = target.closest("[data-start]");
1297
+ return clips.includes(target) || owner !== null && clips.includes(owner);
1298
+ });
1299
+ };
1300
+ }
1301
+ function clipQueryRoot(script) {
1302
+ return script.closest("template") ?? script.ownerDocument;
1303
+ }
1304
+ function hasExplicitTime(animation) {
1305
+ return typeof animation.position === "number" && !animation.implicitPosition;
1306
+ }
1307
+ function queryAll(root, selector) {
1308
+ try {
1309
+ return Array.from(root.querySelectorAll(selector));
1310
+ } catch {
1311
+ return [];
1312
+ }
1313
+ }
1314
+
1315
+ // src/gsapWriterAcorn.ts
1276
1316
  function valueToCode(value) {
1277
1317
  if (typeof value === "string" && value.startsWith("__raw:")) return value.slice(6);
1278
1318
  if (typeof value === "string") return JSON.stringify(value);
@@ -1518,14 +1558,14 @@ function overwritePosition(ms, call, position) {
1518
1558
  ms.appendLeft(call.node.end - 1, `, ${valueToCode(position)}`);
1519
1559
  }
1520
1560
  }
1521
- function shiftPositionsInScript(script, targetSelector, delta) {
1561
+ function shiftPositionsInScript(script, targetSelector, delta, root) {
1522
1562
  const parsed = parseGsapScriptAcornForWrite(script);
1523
1563
  if (!parsed) return script;
1564
+ const carries = clipTweenMatcher(targetSelector, root);
1524
1565
  const ms = new MagicString(script);
1525
1566
  let changed = false;
1526
1567
  for (const entry of parsed.located) {
1527
- if (entry.animation.targetSelector !== targetSelector) continue;
1528
- if (typeof entry.animation.position !== "number") continue;
1568
+ if (!carries(entry.animation) || !hasExplicitTime(entry.animation)) continue;
1529
1569
  overwritePosition(ms, entry.call, shiftedPosition(entry.animation.position, delta));
1530
1570
  changed = true;
1531
1571
  }
@@ -1600,21 +1640,23 @@ function timelineBlock(parsed) {
1600
1640
  function isLoopOrForEach(node) {
1601
1641
  return isLoopNode(node) || isForEachStatement(node) || node?.type === "DoWhileStatement";
1602
1642
  }
1603
- function scalePositionsInScript(script, targetSelector, oldStart, oldDuration, newStart, newDuration) {
1643
+ function scalePositionsInScript(script, targetSelector, oldStart, oldDuration, newStart, newDuration, root) {
1604
1644
  if (oldDuration <= 0 || newDuration <= 0) return script;
1605
1645
  const ratio = newDuration / oldDuration;
1606
1646
  const parsed = parseGsapScriptAcornForWrite(script);
1607
1647
  if (!parsed) return script;
1648
+ const carries = clipTweenMatcher(targetSelector, root);
1608
1649
  const ms = new MagicString(script);
1609
1650
  let changed = false;
1610
1651
  for (const entry of parsed.located) {
1611
- if (entry.animation.targetSelector !== targetSelector) continue;
1612
- if (typeof entry.animation.position !== "number") continue;
1613
- const newPos = Math.max(
1614
- 0,
1615
- Math.round((newStart + (entry.animation.position - oldStart) * ratio) * 1e3) / 1e3
1616
- );
1617
- overwritePosition(ms, entry.call, newPos);
1652
+ if (!carries(entry.animation) || typeof entry.animation.position !== "number") continue;
1653
+ if (hasExplicitTime(entry.animation)) {
1654
+ const newPos = Math.max(
1655
+ 0,
1656
+ Math.round((newStart + (entry.animation.position - oldStart) * ratio) * 1e3) / 1e3
1657
+ );
1658
+ overwritePosition(ms, entry.call, newPos);
1659
+ }
1618
1660
  if (typeof entry.animation.duration === "number" && entry.animation.duration > 0) {
1619
1661
  const newDur = Math.max(1e-3, Math.round(entry.animation.duration * ratio * 1e3) / 1e3);
1620
1662
  upsertProp(ms, entry.call.varsArg, "duration", newDur);
@@ -3054,9 +3096,12 @@ export {
3054
3096
  addLabelToScript,
3055
3097
  addMotionPathPointInScript,
3056
3098
  addMotionPathToScript,
3099
+ clipQueryRoot,
3100
+ clipTweenMatcher,
3057
3101
  convertToKeyframesFromScript,
3058
3102
  copyAnimationsInScript,
3059
3103
  dedupePositionWritesInScript,
3104
+ hasExplicitTime,
3060
3105
  materializeKeyframesFromScript,
3061
3106
  moveKeyframeInScript,
3062
3107
  removeAllKeyframesFromScript,