@hyperframes/parsers 0.8.151 → 0.8.153

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.
@@ -1,2 +1,2 @@
1
- export { B as BUILTIN_VAR_KEYS, D as DROPPED_VAR_KEYS, E as EXTRAS_KEYS, u as GSAP_DEFAULT_DURATION, H as HoldScope, f as PROPERTY_GROUPS, g as PropertyGroupName, S as SUPPORTED_EASES, h as SUPPORTED_PROPS, i as classifyPropertyGroup, j as classifyTweenPropertyGroup, x as holdScope, y as isTweenConfigKey, z as isXYPositionWrite, C as keyframeHoldForAnimation } from './gsapSerialize-DPyyDPBC.js';
1
+ export { B as BUILTIN_VAR_KEYS, D as DROPPED_VAR_KEYS, E as EXTRAS_KEYS, u as GSAP_DEFAULT_DURATION, H as HoldScope, f as PROPERTY_GROUPS, g as PropertyGroupName, S as SUPPORTED_EASES, h as SUPPORTED_PROPS, i as classifyPropertyGroup, j as classifyTweenPropertyGroup, x as holdScope, y as isTweenConfigKey, z as isXYPositionWrite, C as keyframeHoldForAnimation } from './gsapSerialize-Cj1MDhsF.js';
2
2
  import './types-Ejqndkej.js';
@@ -1,5 +1,5 @@
1
- import { G as GsapAnimation, P as ParsedGsap, A as ArcPathConfig, a as ArcPathSegment } from './gsapSerialize-DPyyDPBC.js';
2
- export { b as GsapKeyframeFormat, c as GsapKeyframesData, d as GsapMethod, e as GsapPercentageKeyframe, f as PROPERTY_GROUPS, g as PropertyGroupName, S as SUPPORTED_EASES, h as SUPPORTED_PROPS, i as classifyPropertyGroup, j as classifyTweenPropertyGroup, k as getAnimationsForElementId, l as gsapAnimationsToKeyframes, m as keyframesToGsapAnimations, s as serializeGsapAnimations, v as validateCompositionGsap } from './gsapSerialize-DPyyDPBC.js';
1
+ import { G as GsapAnimation, P as ParsedGsap, A as ArcPathConfig, a as ArcPathSegment } from './gsapSerialize-Cj1MDhsF.js';
2
+ export { b as GsapKeyframeFormat, c as GsapKeyframesData, d as GsapMethod, e as GsapPercentageKeyframe, f as PROPERTY_GROUPS, g as PropertyGroupName, S as SUPPORTED_EASES, h as SUPPORTED_PROPS, i as classifyPropertyGroup, j as classifyTweenPropertyGroup, k as getAnimationsForElementId, l as gsapAnimationsToKeyframes, m as keyframesToGsapAnimations, s as serializeGsapAnimations, v as validateCompositionGsap } from './gsapSerialize-Cj1MDhsF.js';
3
3
  export { SPRING_PRESETS, SpringPreset, generateSpringEaseData } from './springEase.js';
4
4
  import './types-Ejqndkej.js';
5
5
 
@@ -1,5 +1,5 @@
1
- import { P as ParsedGsap, d as GsapMethod, G as GsapAnimation } from './gsapSerialize-DPyyDPBC.js';
2
- export { A as ArcPathConfig, a as ArcPathSegment, n as GsapProvenance, o as GsapProvenanceKind, K as KeyframeEditability, M as MotionPathShape, p as buildArcPath, q as editabilityForProvenance } from './gsapSerialize-DPyyDPBC.js';
1
+ import { P as ParsedGsap, d as GsapMethod, G as GsapAnimation } from './gsapSerialize-Cj1MDhsF.js';
2
+ export { A as ArcPathConfig, a as ArcPathSegment, n as GsapProvenance, o as GsapProvenanceKind, K as KeyframeEditability, M as MotionPathShape, p as buildArcPath, q as editabilityForProvenance } from './gsapSerialize-Cj1MDhsF.js';
3
3
  import './types-Ejqndkej.js';
4
4
 
5
5
  /**
@@ -857,19 +857,19 @@ function collectIdentifierBindingIndex(ast) {
857
857
  }
858
858
  }
859
859
  function addBinding(bindings, scopeNode, name, selector) {
860
- let scoped = bindings.get(scopeNode);
860
+ let scoped = bindings.byScope.get(scopeNode);
861
861
  if (!scoped) {
862
862
  scoped = /* @__PURE__ */ new Map();
863
- bindings.set(scopeNode, scoped);
863
+ bindings.byScope.set(scopeNode, scoped);
864
864
  }
865
865
  if (!scoped.has(name)) scoped.set(name, selector);
866
866
  }
867
867
  function lookupBindingFromAncestors(name, ancestors, bindings) {
868
868
  for (const scopeNode of scopeChainFromAncestors(ancestors)) {
869
- const selector = bindings.get(scopeNode)?.get(name);
869
+ const selector = bindings.byScope.get(scopeNode)?.get(name);
870
870
  if (selector !== void 0) return selector;
871
871
  }
872
- return bindings.get(null)?.get(name) ?? null;
872
+ return bindings.byScope.get(null)?.get(name) ?? null;
873
873
  }
874
874
  function isFunctionNode2(node) {
875
875
  return node?.type === "ArrowFunctionExpression" || node?.type === "FunctionExpression" || node?.type === "FunctionDeclaration";
@@ -908,7 +908,7 @@ function collectScopeBindings(ast) {
908
908
  return bindings;
909
909
  }
910
910
  function collectTargetBindings(ast, scope, identifierBindings) {
911
- const bindings = /* @__PURE__ */ new Map();
911
+ const bindings = { byScope: /* @__PURE__ */ new Map(), identifiers: identifierBindings };
912
912
  acornWalk.ancestor(ast, {
913
913
  VariableDeclarator(node, _, ancestors) {
914
914
  const name = node.id?.name;
@@ -989,7 +989,18 @@ function resolveTargetSelector(node, ancestors, scope, bindings) {
989
989
  return typeof node.value === "string" ? node.value : null;
990
990
  }
991
991
  if (node.type === "Identifier") {
992
- return lookupBindingFromAncestors(node.name, ancestors, bindings);
992
+ const bound = lookupBindingFromAncestors(node.name, ancestors, bindings);
993
+ if (bound) return bound;
994
+ const declaration = findVisibleIdentifierDeclaration(
995
+ node.name,
996
+ ancestors,
997
+ bindings.identifiers,
998
+ node.start
999
+ );
1000
+ if (declaration?.kind !== "const" || bindings.identifiers.reassignedDeclarations.has(declaration.node))
1001
+ return null;
1002
+ const literal = resolveNode(declaration.node.init, scope);
1003
+ return typeof literal === "string" ? literal : null;
993
1004
  }
994
1005
  if (node.type === "CallExpression") {
995
1006
  return selectorFromQueryCall(node, scope);
@@ -1014,7 +1025,7 @@ function describeProxyTarget(targetNode, varsNode, scope) {
1014
1025
  const onUpdate = findPropertyNode(varsNode, "onUpdate");
1015
1026
  const driven = onUpdate ? drivenDomChannel(onUpdate) : void 0;
1016
1027
  if (driven) return `proxy \u2192 ${driven}`;
1017
- return "dwell/hold";
1028
+ return objNode.properties.length === 0 && !onUpdate ? "dwell/hold" : "proxy (unresolved DOM association)";
1018
1029
  }
1019
1030
  function isStyleAssignmentTarget(left) {
1020
1031
  return left?.type === "MemberExpression" && left.object?.type === "MemberExpression" && left.object.property?.name === "style" && !!left.property?.name;
@@ -1533,6 +1544,8 @@ function tweenCallToAnimation(call, scope, source, identifierBindings) {
1533
1544
  duration,
1534
1545
  ease
1535
1546
  };
1547
+ if (["stagger", "repeat", "repeatDelay", "delay"].some((key) => findPropertyNode(call.varsArg, key)))
1548
+ anim.inspectionTiming = inspectionTiming(call.varsArg, scope);
1536
1549
  if (targetIdentity) anim.targetIdentity = targetIdentity;
1537
1550
  if (!hasPositionArg) anim.implicitPosition = true;
1538
1551
  let group = classifyTweenPropertyGroup(properties);
@@ -1555,14 +1568,51 @@ function tweenCallToAnimation(call, scope, source, identifierBindings) {
1555
1568
  if (provenance) anim.provenance = provenance;
1556
1569
  return anim;
1557
1570
  }
1571
+ function inspectionTiming(varsNode, scope) {
1572
+ const numeric = (key) => {
1573
+ const node2 = findPropertyNode(varsNode, key);
1574
+ if (!node2) return 0;
1575
+ const value = resolveNode(node2, scope);
1576
+ return typeof value === "number" && Number.isFinite(value) ? value : null;
1577
+ };
1578
+ const node = findPropertyNode(varsNode, "stagger");
1579
+ let stagger = { each: 0 };
1580
+ if (node) {
1581
+ const value = resolveNode(node, scope);
1582
+ stagger = typeof value === "number" ? { each: value } : null;
1583
+ if (node.type === "ObjectExpression" && !(node.properties ?? []).some(
1584
+ (p) => !["each", "amount", "from", "ease", "axis", "grid"].includes(propKeyName(p) ?? "")
1585
+ )) {
1586
+ const each = resolveNode(findPropertyNode(node, "each"), scope);
1587
+ const amount = resolveNode(findPropertyNode(node, "amount"), scope);
1588
+ if (!findPropertyNode(node, "grid") && !findPropertyNode(node, "axis")) {
1589
+ if (typeof amount === "number") stagger = { amount };
1590
+ else if (typeof each === "number") stagger = { each };
1591
+ }
1592
+ }
1593
+ }
1594
+ return {
1595
+ repeat: numeric("repeat"),
1596
+ repeatDelay: numeric("repeatDelay"),
1597
+ delay: numeric("delay"),
1598
+ stagger
1599
+ };
1600
+ }
1558
1601
  function staggerAmount(raw) {
1559
1602
  if (typeof raw === "number") return raw;
1560
1603
  if (typeof raw !== "string") return void 0;
1561
1604
  const src = raw.startsWith("__raw:") ? raw.slice(6) : raw;
1562
- const m = /(?:each\s*:\s*)?(-?\d+(?:\.\d+)?)/.exec(src);
1563
- if (!m) return void 0;
1564
- const n = Number.parseFloat(m[1]);
1565
- return Number.isFinite(n) ? n : void 0;
1605
+ try {
1606
+ const node = acorn2.parseExpressionAt(src, 0, { ecmaVersion: "latest" });
1607
+ if (src.slice(node.end).trim()) return void 0;
1608
+ const value = resolveNode(
1609
+ node.type === "ObjectExpression" ? findPropertyNode(node, "each") : node,
1610
+ /* @__PURE__ */ new Map()
1611
+ );
1612
+ return typeof value === "number" && Number.isFinite(value) ? value : void 0;
1613
+ } catch {
1614
+ return void 0;
1615
+ }
1566
1616
  }
1567
1617
  function restValue(prop) {
1568
1618
  return prop === "opacity" || prop.startsWith("scale") ? 1 : 0;
@@ -1,4 +1,4 @@
1
- export { A as ArcPathConfig, a as ArcPathSegment, u as GSAP_DEFAULT_DURATION, G as GsapAnimation, c as GsapKeyframesData, d as GsapMethod, e as GsapPercentageKeyframe, n as GsapProvenance, o as GsapProvenanceKind, K as KeyframeEditability, f as PROPERTY_GROUPS, P as ParsedGsap, g as PropertyGroupName, S as SUPPORTED_EASES, h as SUPPORTED_PROPS, w as SourcedGsapPercentageKeyframe, r as SplitAnimationsOptions, t as SplitAnimationsResult, i as classifyPropertyGroup, j as classifyTweenPropertyGroup, q as editabilityForProvenance, k as getAnimationsForElementId, l as gsapAnimationsToKeyframes, m as keyframesToGsapAnimations, s as serializeGsapAnimations, v as validateCompositionGsap } from './gsapSerialize-DPyyDPBC.js';
1
+ export { A as ArcPathConfig, a as ArcPathSegment, u as GSAP_DEFAULT_DURATION, G as GsapAnimation, c as GsapKeyframesData, d as GsapMethod, e as GsapPercentageKeyframe, n as GsapProvenance, o as GsapProvenanceKind, K as KeyframeEditability, f as PROPERTY_GROUPS, P as ParsedGsap, g as PropertyGroupName, S as SUPPORTED_EASES, h as SUPPORTED_PROPS, w as SourcedGsapPercentageKeyframe, r as SplitAnimationsOptions, t as SplitAnimationsResult, i as classifyPropertyGroup, j as classifyTweenPropertyGroup, q as editabilityForProvenance, k as getAnimationsForElementId, l as gsapAnimationsToKeyframes, m as keyframesToGsapAnimations, s as serializeGsapAnimations, v as validateCompositionGsap } from './gsapSerialize-Cj1MDhsF.js';
2
2
  export { isStudioHoldSet } from './gsapParser.js';
3
3
  export { SPRING_PRESETS, SpringPreset, generateSpringEaseData } from './springEase.js';
4
4
  export { parseGsapScriptAcorn as parseGsapScript } from './gsapParserAcorn.js';
@@ -1148,19 +1148,19 @@ function collectIdentifierBindingIndex(ast) {
1148
1148
  }
1149
1149
  }
1150
1150
  function addBinding(bindings, scopeNode, name, selector) {
1151
- let scoped = bindings.get(scopeNode);
1151
+ let scoped = bindings.byScope.get(scopeNode);
1152
1152
  if (!scoped) {
1153
1153
  scoped = /* @__PURE__ */ new Map();
1154
- bindings.set(scopeNode, scoped);
1154
+ bindings.byScope.set(scopeNode, scoped);
1155
1155
  }
1156
1156
  if (!scoped.has(name)) scoped.set(name, selector);
1157
1157
  }
1158
1158
  function lookupBindingFromAncestors(name, ancestors, bindings) {
1159
1159
  for (const scopeNode of scopeChainFromAncestors(ancestors)) {
1160
- const selector = bindings.get(scopeNode)?.get(name);
1160
+ const selector = bindings.byScope.get(scopeNode)?.get(name);
1161
1161
  if (selector !== void 0) return selector;
1162
1162
  }
1163
- return bindings.get(null)?.get(name) ?? null;
1163
+ return bindings.byScope.get(null)?.get(name) ?? null;
1164
1164
  }
1165
1165
  function isFunctionNode2(node) {
1166
1166
  return node?.type === "ArrowFunctionExpression" || node?.type === "FunctionExpression" || node?.type === "FunctionDeclaration";
@@ -1199,7 +1199,7 @@ function collectScopeBindings(ast) {
1199
1199
  return bindings;
1200
1200
  }
1201
1201
  function collectTargetBindings(ast, scope, identifierBindings) {
1202
- const bindings = /* @__PURE__ */ new Map();
1202
+ const bindings = { byScope: /* @__PURE__ */ new Map(), identifiers: identifierBindings };
1203
1203
  acornWalk.ancestor(ast, {
1204
1204
  VariableDeclarator(node, _, ancestors) {
1205
1205
  const name = node.id?.name;
@@ -1280,7 +1280,18 @@ function resolveTargetSelector(node, ancestors, scope, bindings) {
1280
1280
  return typeof node.value === "string" ? node.value : null;
1281
1281
  }
1282
1282
  if (node.type === "Identifier") {
1283
- return lookupBindingFromAncestors(node.name, ancestors, bindings);
1283
+ const bound = lookupBindingFromAncestors(node.name, ancestors, bindings);
1284
+ if (bound) return bound;
1285
+ const declaration = findVisibleIdentifierDeclaration(
1286
+ node.name,
1287
+ ancestors,
1288
+ bindings.identifiers,
1289
+ node.start
1290
+ );
1291
+ if (declaration?.kind !== "const" || bindings.identifiers.reassignedDeclarations.has(declaration.node))
1292
+ return null;
1293
+ const literal = resolveNode(declaration.node.init, scope);
1294
+ return typeof literal === "string" ? literal : null;
1284
1295
  }
1285
1296
  if (node.type === "CallExpression") {
1286
1297
  return selectorFromQueryCall(node, scope);
@@ -1305,7 +1316,7 @@ function describeProxyTarget(targetNode, varsNode, scope) {
1305
1316
  const onUpdate = findPropertyNode(varsNode, "onUpdate");
1306
1317
  const driven = onUpdate ? drivenDomChannel(onUpdate) : void 0;
1307
1318
  if (driven) return `proxy \u2192 ${driven}`;
1308
- return "dwell/hold";
1319
+ return objNode.properties.length === 0 && !onUpdate ? "dwell/hold" : "proxy (unresolved DOM association)";
1309
1320
  }
1310
1321
  function isStyleAssignmentTarget(left) {
1311
1322
  return left?.type === "MemberExpression" && left.object?.type === "MemberExpression" && left.object.property?.name === "style" && !!left.property?.name;
@@ -1824,6 +1835,8 @@ function tweenCallToAnimation(call, scope, source, identifierBindings) {
1824
1835
  duration,
1825
1836
  ease
1826
1837
  };
1838
+ if (["stagger", "repeat", "repeatDelay", "delay"].some((key) => findPropertyNode(call.varsArg, key)))
1839
+ anim.inspectionTiming = inspectionTiming(call.varsArg, scope);
1827
1840
  if (targetIdentity) anim.targetIdentity = targetIdentity;
1828
1841
  if (!hasPositionArg) anim.implicitPosition = true;
1829
1842
  let group = classifyTweenPropertyGroup(properties);
@@ -1846,14 +1859,51 @@ function tweenCallToAnimation(call, scope, source, identifierBindings) {
1846
1859
  if (provenance) anim.provenance = provenance;
1847
1860
  return anim;
1848
1861
  }
1862
+ function inspectionTiming(varsNode, scope) {
1863
+ const numeric = (key) => {
1864
+ const node2 = findPropertyNode(varsNode, key);
1865
+ if (!node2) return 0;
1866
+ const value = resolveNode(node2, scope);
1867
+ return typeof value === "number" && Number.isFinite(value) ? value : null;
1868
+ };
1869
+ const node = findPropertyNode(varsNode, "stagger");
1870
+ let stagger = { each: 0 };
1871
+ if (node) {
1872
+ const value = resolveNode(node, scope);
1873
+ stagger = typeof value === "number" ? { each: value } : null;
1874
+ if (node.type === "ObjectExpression" && !(node.properties ?? []).some(
1875
+ (p) => !["each", "amount", "from", "ease", "axis", "grid"].includes(propKeyName(p) ?? "")
1876
+ )) {
1877
+ const each = resolveNode(findPropertyNode(node, "each"), scope);
1878
+ const amount = resolveNode(findPropertyNode(node, "amount"), scope);
1879
+ if (!findPropertyNode(node, "grid") && !findPropertyNode(node, "axis")) {
1880
+ if (typeof amount === "number") stagger = { amount };
1881
+ else if (typeof each === "number") stagger = { each };
1882
+ }
1883
+ }
1884
+ }
1885
+ return {
1886
+ repeat: numeric("repeat"),
1887
+ repeatDelay: numeric("repeatDelay"),
1888
+ delay: numeric("delay"),
1889
+ stagger
1890
+ };
1891
+ }
1849
1892
  function staggerAmount(raw) {
1850
1893
  if (typeof raw === "number") return raw;
1851
1894
  if (typeof raw !== "string") return void 0;
1852
1895
  const src = raw.startsWith("__raw:") ? raw.slice(6) : raw;
1853
- const m = /(?:each\s*:\s*)?(-?\d+(?:\.\d+)?)/.exec(src);
1854
- if (!m) return void 0;
1855
- const n = Number.parseFloat(m[1]);
1856
- return Number.isFinite(n) ? n : void 0;
1896
+ try {
1897
+ const node = acorn.parseExpressionAt(src, 0, { ecmaVersion: "latest" });
1898
+ if (src.slice(node.end).trim()) return void 0;
1899
+ const value = resolveNode(
1900
+ node.type === "ObjectExpression" ? findPropertyNode(node, "each") : node,
1901
+ /* @__PURE__ */ new Map()
1902
+ );
1903
+ return typeof value === "number" && Number.isFinite(value) ? value : void 0;
1904
+ } catch {
1905
+ return void 0;
1906
+ }
1857
1907
  }
1858
1908
  function restValue(prop) {
1859
1909
  return prop === "opacity" || prop.startsWith("scale") ? 1 : 0;
@@ -88,6 +88,16 @@ interface GsapAnimation {
88
88
  ease?: string;
89
89
  /** Non-editable GSAP config (stagger, yoyo, repeat, etc.) preserved for round-trips. */
90
90
  extras?: Record<string, unknown>;
91
+ inspectionTiming?: {
92
+ repeat: number | null;
93
+ repeatDelay: number | null;
94
+ delay: number | null;
95
+ stagger: {
96
+ each: number;
97
+ } | {
98
+ amount: number;
99
+ } | null;
100
+ };
91
101
  /** Native GSAP keyframes data — present when the tween uses keyframes: { ... }. */
92
102
  keyframes?: GsapKeyframesData;
93
103
  /** Arc motion path config — present when the tween uses motionPath for curved position interpolation. */
@@ -1,4 +1,4 @@
1
- import { G as GsapAnimation, A as ArcPathConfig, r as SplitAnimationsOptions, t as SplitAnimationsResult, a as ArcPathSegment } from './gsapSerialize-DPyyDPBC.js';
1
+ import { G as GsapAnimation, A as ArcPathConfig, r as SplitAnimationsOptions, t as SplitAnimationsResult, a as ArcPathSegment } from './gsapSerialize-Cj1MDhsF.js';
2
2
  import './types-Ejqndkej.js';
3
3
 
4
4
  type TweenTarget = Pick<GsapAnimation, "targetSelector" | "hasPartialSelector">;
@@ -491,19 +491,19 @@ function collectIdentifierBindingIndex(ast) {
491
491
  }
492
492
  }
493
493
  function addBinding(bindings, scopeNode, name, selector) {
494
- let scoped = bindings.get(scopeNode);
494
+ let scoped = bindings.byScope.get(scopeNode);
495
495
  if (!scoped) {
496
496
  scoped = /* @__PURE__ */ new Map();
497
- bindings.set(scopeNode, scoped);
497
+ bindings.byScope.set(scopeNode, scoped);
498
498
  }
499
499
  if (!scoped.has(name)) scoped.set(name, selector);
500
500
  }
501
501
  function lookupBindingFromAncestors(name, ancestors, bindings) {
502
502
  for (const scopeNode of scopeChainFromAncestors(ancestors)) {
503
- const selector = bindings.get(scopeNode)?.get(name);
503
+ const selector = bindings.byScope.get(scopeNode)?.get(name);
504
504
  if (selector !== void 0) return selector;
505
505
  }
506
- return bindings.get(null)?.get(name) ?? null;
506
+ return bindings.byScope.get(null)?.get(name) ?? null;
507
507
  }
508
508
  function isFunctionNode(node) {
509
509
  return node?.type === "ArrowFunctionExpression" || node?.type === "FunctionExpression" || node?.type === "FunctionDeclaration";
@@ -542,7 +542,7 @@ function collectScopeBindings(ast) {
542
542
  return bindings;
543
543
  }
544
544
  function collectTargetBindings(ast, scope, identifierBindings) {
545
- const bindings = /* @__PURE__ */ new Map();
545
+ const bindings = { byScope: /* @__PURE__ */ new Map(), identifiers: identifierBindings };
546
546
  acornWalk.ancestor(ast, {
547
547
  VariableDeclarator(node, _, ancestors) {
548
548
  const name = node.id?.name;
@@ -623,7 +623,18 @@ function resolveTargetSelector(node, ancestors, scope, bindings) {
623
623
  return typeof node.value === "string" ? node.value : null;
624
624
  }
625
625
  if (node.type === "Identifier") {
626
- return lookupBindingFromAncestors(node.name, ancestors, bindings);
626
+ const bound = lookupBindingFromAncestors(node.name, ancestors, bindings);
627
+ if (bound) return bound;
628
+ const declaration = findVisibleIdentifierDeclaration(
629
+ node.name,
630
+ ancestors,
631
+ bindings.identifiers,
632
+ node.start
633
+ );
634
+ if (declaration?.kind !== "const" || bindings.identifiers.reassignedDeclarations.has(declaration.node))
635
+ return null;
636
+ const literal = resolveNode(declaration.node.init, scope);
637
+ return typeof literal === "string" ? literal : null;
627
638
  }
628
639
  if (node.type === "CallExpression") {
629
640
  return selectorFromQueryCall(node, scope);
@@ -648,7 +659,7 @@ function describeProxyTarget(targetNode, varsNode, scope) {
648
659
  const onUpdate = findPropertyNode(varsNode, "onUpdate");
649
660
  const driven = onUpdate ? drivenDomChannel(onUpdate) : void 0;
650
661
  if (driven) return `proxy \u2192 ${driven}`;
651
- return "dwell/hold";
662
+ return objNode.properties.length === 0 && !onUpdate ? "dwell/hold" : "proxy (unresolved DOM association)";
652
663
  }
653
664
  function isStyleAssignmentTarget(left) {
654
665
  return left?.type === "MemberExpression" && left.object?.type === "MemberExpression" && left.object.property?.name === "style" && !!left.property?.name;
@@ -1164,6 +1175,8 @@ function tweenCallToAnimation(call, scope, source, identifierBindings) {
1164
1175
  duration,
1165
1176
  ease
1166
1177
  };
1178
+ if (["stagger", "repeat", "repeatDelay", "delay"].some((key) => findPropertyNode(call.varsArg, key)))
1179
+ anim.inspectionTiming = inspectionTiming(call.varsArg, scope);
1167
1180
  if (targetIdentity) anim.targetIdentity = targetIdentity;
1168
1181
  if (!hasPositionArg) anim.implicitPosition = true;
1169
1182
  let group = classifyTweenPropertyGroup(properties);
@@ -1186,6 +1199,36 @@ function tweenCallToAnimation(call, scope, source, identifierBindings) {
1186
1199
  if (provenance) anim.provenance = provenance;
1187
1200
  return anim;
1188
1201
  }
1202
+ function inspectionTiming(varsNode, scope) {
1203
+ const numeric = (key) => {
1204
+ const node2 = findPropertyNode(varsNode, key);
1205
+ if (!node2) return 0;
1206
+ const value = resolveNode(node2, scope);
1207
+ return typeof value === "number" && Number.isFinite(value) ? value : null;
1208
+ };
1209
+ const node = findPropertyNode(varsNode, "stagger");
1210
+ let stagger = { each: 0 };
1211
+ if (node) {
1212
+ const value = resolveNode(node, scope);
1213
+ stagger = typeof value === "number" ? { each: value } : null;
1214
+ if (node.type === "ObjectExpression" && !(node.properties ?? []).some(
1215
+ (p) => !["each", "amount", "from", "ease", "axis", "grid"].includes(propKeyName(p) ?? "")
1216
+ )) {
1217
+ const each = resolveNode(findPropertyNode(node, "each"), scope);
1218
+ const amount = resolveNode(findPropertyNode(node, "amount"), scope);
1219
+ if (!findPropertyNode(node, "grid") && !findPropertyNode(node, "axis")) {
1220
+ if (typeof amount === "number") stagger = { amount };
1221
+ else if (typeof each === "number") stagger = { each };
1222
+ }
1223
+ }
1224
+ }
1225
+ return {
1226
+ repeat: numeric("repeat"),
1227
+ repeatDelay: numeric("repeatDelay"),
1228
+ delay: numeric("delay"),
1229
+ stagger
1230
+ };
1231
+ }
1189
1232
  function resolvePositionString(pos, cursor, prevStart) {
1190
1233
  const trimmed = pos.trim();
1191
1234
  if (trimmed === "") return cursor;
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { C as CompositionVariable, T as TimelineElement, a as CanvasResolution, K as Keyframe, S as StageZoomKeyframe, V as ValidationResult } from './types-Ejqndkej.js';
2
2
  export { A as AddElementData, b as Asset, B as BooleanVariable, c as CANVAS_DIMENSIONS, d as COMPOSITION_VARIABLE_TYPES, e as ColorVariable, f as CompositionAPI, g as CompositionAsset, h as CompositionSpec, i as CompositionVariableBase, j as CompositionVariableType, D as DEFAULT_DURATIONS, E as ElementKeyframes, k as EnumVariable, F as FontVariable, I as ImageVariable, l as KeyframeProperties, M as MediaElementType, m as MediaFile, N as NumberVariable, P as PlayerAPI, R as ResolvedResolutionFlag, n as StageZoom, o as StringVariable, p as TIMELINE_COLORS, q as TimelineCompositionElement, r as TimelineElementBase, s as TimelineElementType, t as TimelineMediaElement, u as TimelineTextElement, v as VALID_CANVAS_RESOLUTIONS, W as WaveformData, w as getDefaultStageZoom, x as isAspectAgnosticResolutionAlias, y as isCompositionElement, z as isMediaElement, G as isTextElement, H as normalizeResolutionFlag, J as resolveResolutionFlagPair } from './types-Ejqndkej.js';
3
- export { A as ArcPathConfig, a as ArcPathSegment, u as GSAP_DEFAULT_DURATION, G as GsapAnimation, c as GsapKeyframesData, d as GsapMethod, e as GsapPercentageKeyframe, n as GsapProvenance, o as GsapProvenanceKind, K as KeyframeEditability, f as PROPERTY_GROUPS, P as ParsedGsap, g as PropertyGroupName, S as SUPPORTED_EASES, h as SUPPORTED_PROPS, w as SourcedGsapPercentageKeyframe, r as SplitAnimationsOptions, t as SplitAnimationsResult, i as classifyPropertyGroup, j as classifyTweenPropertyGroup, q as editabilityForProvenance, k as getAnimationsForElementId, l as gsapAnimationsToKeyframes, m as keyframesToGsapAnimations, s as serializeGsapAnimations, v as validateCompositionGsap } from './gsapSerialize-DPyyDPBC.js';
3
+ export { A as ArcPathConfig, a as ArcPathSegment, u as GSAP_DEFAULT_DURATION, G as GsapAnimation, c as GsapKeyframesData, d as GsapMethod, e as GsapPercentageKeyframe, n as GsapProvenance, o as GsapProvenanceKind, K as KeyframeEditability, f as PROPERTY_GROUPS, P as ParsedGsap, g as PropertyGroupName, S as SUPPORTED_EASES, h as SUPPORTED_PROPS, w as SourcedGsapPercentageKeyframe, r as SplitAnimationsOptions, t as SplitAnimationsResult, i as classifyPropertyGroup, j as classifyTweenPropertyGroup, q as editabilityForProvenance, k as getAnimationsForElementId, l as gsapAnimationsToKeyframes, m as keyframesToGsapAnimations, s as serializeGsapAnimations, v as validateCompositionGsap } from './gsapSerialize-Cj1MDhsF.js';
4
4
  export { isStudioHoldSet } from './gsapParser.js';
5
5
  export { getObjectArrayKeyframeTiming } from './gsapParserExports.js';
6
6
  export { SPRING_PRESETS, SpringPreset, generateSpringEaseData } from './springEase.js';
package/dist/index.js CHANGED
@@ -1241,19 +1241,19 @@ function collectIdentifierBindingIndex(ast) {
1241
1241
  }
1242
1242
  }
1243
1243
  function addBinding(bindings, scopeNode, name, selector) {
1244
- let scoped = bindings.get(scopeNode);
1244
+ let scoped = bindings.byScope.get(scopeNode);
1245
1245
  if (!scoped) {
1246
1246
  scoped = /* @__PURE__ */ new Map();
1247
- bindings.set(scopeNode, scoped);
1247
+ bindings.byScope.set(scopeNode, scoped);
1248
1248
  }
1249
1249
  if (!scoped.has(name)) scoped.set(name, selector);
1250
1250
  }
1251
1251
  function lookupBindingFromAncestors(name, ancestors, bindings) {
1252
1252
  for (const scopeNode of scopeChainFromAncestors(ancestors)) {
1253
- const selector = bindings.get(scopeNode)?.get(name);
1253
+ const selector = bindings.byScope.get(scopeNode)?.get(name);
1254
1254
  if (selector !== void 0) return selector;
1255
1255
  }
1256
- return bindings.get(null)?.get(name) ?? null;
1256
+ return bindings.byScope.get(null)?.get(name) ?? null;
1257
1257
  }
1258
1258
  function isFunctionNode2(node) {
1259
1259
  return node?.type === "ArrowFunctionExpression" || node?.type === "FunctionExpression" || node?.type === "FunctionDeclaration";
@@ -1292,7 +1292,7 @@ function collectScopeBindings(ast) {
1292
1292
  return bindings;
1293
1293
  }
1294
1294
  function collectTargetBindings(ast, scope, identifierBindings) {
1295
- const bindings = /* @__PURE__ */ new Map();
1295
+ const bindings = { byScope: /* @__PURE__ */ new Map(), identifiers: identifierBindings };
1296
1296
  acornWalk.ancestor(ast, {
1297
1297
  VariableDeclarator(node, _, ancestors) {
1298
1298
  const name = node.id?.name;
@@ -1373,7 +1373,18 @@ function resolveTargetSelector(node, ancestors, scope, bindings) {
1373
1373
  return typeof node.value === "string" ? node.value : null;
1374
1374
  }
1375
1375
  if (node.type === "Identifier") {
1376
- return lookupBindingFromAncestors(node.name, ancestors, bindings);
1376
+ const bound = lookupBindingFromAncestors(node.name, ancestors, bindings);
1377
+ if (bound) return bound;
1378
+ const declaration = findVisibleIdentifierDeclaration(
1379
+ node.name,
1380
+ ancestors,
1381
+ bindings.identifiers,
1382
+ node.start
1383
+ );
1384
+ if (declaration?.kind !== "const" || bindings.identifiers.reassignedDeclarations.has(declaration.node))
1385
+ return null;
1386
+ const literal = resolveNode(declaration.node.init, scope);
1387
+ return typeof literal === "string" ? literal : null;
1377
1388
  }
1378
1389
  if (node.type === "CallExpression") {
1379
1390
  return selectorFromQueryCall(node, scope);
@@ -1398,7 +1409,7 @@ function describeProxyTarget(targetNode, varsNode, scope) {
1398
1409
  const onUpdate = findPropertyNode(varsNode, "onUpdate");
1399
1410
  const driven = onUpdate ? drivenDomChannel(onUpdate) : void 0;
1400
1411
  if (driven) return `proxy \u2192 ${driven}`;
1401
- return "dwell/hold";
1412
+ return objNode.properties.length === 0 && !onUpdate ? "dwell/hold" : "proxy (unresolved DOM association)";
1402
1413
  }
1403
1414
  function isStyleAssignmentTarget(left) {
1404
1415
  return left?.type === "MemberExpression" && left.object?.type === "MemberExpression" && left.object.property?.name === "style" && !!left.property?.name;
@@ -1917,6 +1928,8 @@ function tweenCallToAnimation(call, scope, source, identifierBindings) {
1917
1928
  duration,
1918
1929
  ease
1919
1930
  };
1931
+ if (["stagger", "repeat", "repeatDelay", "delay"].some((key) => findPropertyNode(call.varsArg, key)))
1932
+ anim.inspectionTiming = inspectionTiming(call.varsArg, scope);
1920
1933
  if (targetIdentity) anim.targetIdentity = targetIdentity;
1921
1934
  if (!hasPositionArg) anim.implicitPosition = true;
1922
1935
  let group = classifyTweenPropertyGroup(properties);
@@ -1939,14 +1952,51 @@ function tweenCallToAnimation(call, scope, source, identifierBindings) {
1939
1952
  if (provenance) anim.provenance = provenance;
1940
1953
  return anim;
1941
1954
  }
1955
+ function inspectionTiming(varsNode, scope) {
1956
+ const numeric2 = (key) => {
1957
+ const node2 = findPropertyNode(varsNode, key);
1958
+ if (!node2) return 0;
1959
+ const value = resolveNode(node2, scope);
1960
+ return typeof value === "number" && Number.isFinite(value) ? value : null;
1961
+ };
1962
+ const node = findPropertyNode(varsNode, "stagger");
1963
+ let stagger = { each: 0 };
1964
+ if (node) {
1965
+ const value = resolveNode(node, scope);
1966
+ stagger = typeof value === "number" ? { each: value } : null;
1967
+ if (node.type === "ObjectExpression" && !(node.properties ?? []).some(
1968
+ (p) => !["each", "amount", "from", "ease", "axis", "grid"].includes(propKeyName(p) ?? "")
1969
+ )) {
1970
+ const each = resolveNode(findPropertyNode(node, "each"), scope);
1971
+ const amount = resolveNode(findPropertyNode(node, "amount"), scope);
1972
+ if (!findPropertyNode(node, "grid") && !findPropertyNode(node, "axis")) {
1973
+ if (typeof amount === "number") stagger = { amount };
1974
+ else if (typeof each === "number") stagger = { each };
1975
+ }
1976
+ }
1977
+ }
1978
+ return {
1979
+ repeat: numeric2("repeat"),
1980
+ repeatDelay: numeric2("repeatDelay"),
1981
+ delay: numeric2("delay"),
1982
+ stagger
1983
+ };
1984
+ }
1942
1985
  function staggerAmount(raw) {
1943
1986
  if (typeof raw === "number") return raw;
1944
1987
  if (typeof raw !== "string") return void 0;
1945
1988
  const src = raw.startsWith("__raw:") ? raw.slice(6) : raw;
1946
- const m = /(?:each\s*:\s*)?(-?\d+(?:\.\d+)?)/.exec(src);
1947
- if (!m) return void 0;
1948
- const n = Number.parseFloat(m[1]);
1949
- return Number.isFinite(n) ? n : void 0;
1989
+ try {
1990
+ const node = acorn.parseExpressionAt(src, 0, { ecmaVersion: "latest" });
1991
+ if (src.slice(node.end).trim()) return void 0;
1992
+ const value = resolveNode(
1993
+ node.type === "ObjectExpression" ? findPropertyNode(node, "each") : node,
1994
+ /* @__PURE__ */ new Map()
1995
+ );
1996
+ return typeof value === "number" && Number.isFinite(value) ? value : void 0;
1997
+ } catch {
1998
+ return void 0;
1999
+ }
1950
2000
  }
1951
2001
  function restValue(prop) {
1952
2002
  return prop === "opacity" || prop.startsWith("scale") ? 1 : 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hyperframes/parsers",
3
- "version": "0.8.151",
3
+ "version": "0.8.153",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/heygen-com/hyperframes",
@@ -119,7 +119,7 @@
119
119
  "tsx": "^4.21.0",
120
120
  "typescript": "^5.0.0",
121
121
  "vitest": "^4.1.11",
122
- "@hyperframes/core": "0.8.151"
122
+ "@hyperframes/core": "0.8.153"
123
123
  },
124
124
  "scripts": {
125
125
  "build": "tsup",