@pixodesk/svg-animator-vue 1.0.27 → 1.0.29

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.umd.js CHANGED
@@ -57939,6 +57939,13 @@ ${codeFrame}` : message);
57939
57939
  kind: px.enum(["view", "scroll"]).optional(),
57940
57940
  axis: px.enum(["block", "inline", "x", "y"]).optional(),
57941
57941
  source: px.enum(["nearest", "root"]).optional(),
57942
+ // Free-form: the two keywords `parent`/`scroller` plus any CSS selector.
57943
+ subject: px.string().optional(),
57944
+ smoothing: px.number().optional(),
57945
+ pin: px.boolean().optional(),
57946
+ pinAlign: px.enum(["top", "center", "bottom"]).optional(),
57947
+ pinTop: px.number().optional(),
57948
+ pinDistance: px.number().optional(),
57942
57949
  range: PxScrollRangeSchema.optional()
57943
57950
  }));
57944
57951
  var PxAnimatorConfigSchema = implementsInterface()(px.object({
@@ -61167,6 +61174,19 @@ ${codeFrame}` : message);
61167
61174
  TEXT_CONTENT_ATTR,
61168
61175
  "xml:space"
61169
61176
  ];
61177
+ var PAINT_STATIC_KEYS = [
61178
+ "fillOpacity",
61179
+ "fillRule",
61180
+ "strokeOpacity",
61181
+ "strokeDasharray",
61182
+ "strokeDashoffset",
61183
+ "strokeLinecap",
61184
+ "strokeLinejoin",
61185
+ "strokeMiterlimit",
61186
+ "mixBlendMode",
61187
+ "filter"
61188
+ ];
61189
+ var PAINT_ANIMATE_KEYS = ["fill", "stroke", "strokeWidth", "opacity", "fillOpacity", "strokeOpacity", "strokeDasharray", "strokeDashoffset"];
61170
61190
  function parseLen(v) {
61171
61191
  if (typeof v === "number") return v;
61172
61192
  if (typeof v === "string") {
@@ -61178,17 +61198,39 @@ ${codeFrame}` : message);
61178
61198
  function str(v) {
61179
61199
  return typeof v === "string" ? v : void 0;
61180
61200
  }
61201
+ function paintAnimateOf(node) {
61202
+ const bag = node.animate;
61203
+ if (!bag || typeof bag !== "object") return void 0;
61204
+ let out;
61205
+ for (const k of PAINT_ANIMATE_KEYS) {
61206
+ if (bag[k] !== void 0) (out != null ? out : out = {})[k] = bag[k];
61207
+ }
61208
+ return out;
61209
+ }
61181
61210
  function resolveStyle2(node, parent) {
61182
- var _a, _b, _c, _d, _e, _f, _g;
61183
- return {
61211
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
61212
+ const isTextRoot = node.type === "text";
61213
+ const nodeStyle = node.style;
61214
+ const own = (key) => {
61215
+ var _a2;
61216
+ return isTextRoot ? void 0 : (_a2 = node[key]) != null ? _a2 : nodeStyle == null ? void 0 : nodeStyle[key];
61217
+ };
61218
+ const res = {
61184
61219
  fontFamily: (_a = str(node.fontFamily)) != null ? _a : parent.fontFamily,
61185
61220
  fontSize: (_b = parseLen(node.fontSize)) != null ? _b : parent.fontSize,
61186
61221
  fill: (_c = node.fill) != null ? _c : parent.fill,
61187
61222
  stroke: (_d = node.stroke) != null ? _d : parent.stroke,
61188
61223
  strokeWidth: (_e = node.strokeWidth) != null ? _e : parent.strokeWidth,
61189
61224
  letterSpacing: (_f = parseLen(node.letterSpacing)) != null ? _f : parent.letterSpacing,
61190
- wordSpacing: (_g = parseLen(node.wordSpacing)) != null ? _g : parent.wordSpacing
61225
+ wordSpacing: (_g = parseLen(node.wordSpacing)) != null ? _g : parent.wordSpacing,
61226
+ opacity: (_h = parseLen(own("opacity"))) != null ? _h : parent.opacity,
61227
+ animate: (_i = isTextRoot ? void 0 : paintAnimateOf(node)) != null ? _i : parent.animate
61191
61228
  };
61229
+ for (const key of PAINT_STATIC_KEYS) {
61230
+ const v = (_j = own(key)) != null ? _j : parent[key];
61231
+ if (v !== void 0) res[key] = v;
61232
+ }
61233
+ return res;
61192
61234
  }
61193
61235
  function rootStyleOf(node) {
61194
61236
  var _a, _b, _c;
@@ -61207,6 +61249,11 @@ ${codeFrame}` : message);
61207
61249
  if (s.fill !== void 0) p.fill = s.fill;
61208
61250
  if (s.stroke !== void 0) p.stroke = s.stroke;
61209
61251
  if (s.strokeWidth !== void 0) p.strokeWidth = s.strokeWidth;
61252
+ if (s.opacity !== void 0 && s.opacity !== 1) p.opacity = s.opacity;
61253
+ for (const key of PAINT_STATIC_KEYS) {
61254
+ if (s[key] !== void 0) p[key] = s[key];
61255
+ }
61256
+ if (s.animate !== void 0) p.animate = s.animate;
61210
61257
  return p;
61211
61258
  }
61212
61259
  function glyphFontFor(s, glyphs, soleFont, warnings) {
@@ -61220,6 +61267,7 @@ ${codeFrame}` : message);
61220
61267
  return names.length === 1 ? glyphs[names[0]] : void 0;
61221
61268
  }
61222
61269
  var MISSING_GLYPH_ADVANCE_EM = 0.6;
61270
+ var MISSING_GLYPH_CLASS_NAME = "px-missing-glyph";
61223
61271
  function missingGlyphBoxEm(advanceEm, ascentEm) {
61224
61272
  if (advanceEm <= 0 || ascentEm <= 0) return "";
61225
61273
  const inset = 0.08;
@@ -61255,7 +61303,7 @@ ${codeFrame}` : message);
61255
61303
  pen.x += g.width * scale;
61256
61304
  } else if (/\S/.test(ch)) {
61257
61305
  const advEm = g && g.width > 0 ? g.width : MISSING_GLYPH_ADVANCE_EM * upm;
61258
- placements.push({ glyphD: missingGlyphBoxEm(advEm, ascentEm), m: [scale, 0, 0, scale, pen.x, pen.y], paint, line, x: pen.x, y: pen.y, scale });
61306
+ placements.push({ glyphD: missingGlyphBoxEm(advEm, ascentEm), m: [scale, 0, 0, scale, pen.x, pen.y], paint, isMissing: true, line, x: pen.x, y: pen.y, scale });
61259
61307
  pen.x += advEm * scale;
61260
61308
  } else {
61261
61309
  pen.x += (g ? g.width : 0) * scale;
@@ -61318,7 +61366,7 @@ ${codeFrame}` : message);
61318
61366
  } else if (/\S/.test(ch)) {
61319
61367
  const wEm = g && g.width > 0 ? g.width : MISSING_GLYPH_ADVANCE_EM * gf.unitsPerEm;
61320
61368
  const boxAdv = wEm * scale;
61321
- cells.push({ glyphD: missingGlyphBoxEm(wEm, ascentEm), widthEm: wEm, scale, paint, midBase: adv + boxAdv / 2 });
61369
+ cells.push({ glyphD: missingGlyphBoxEm(wEm, ascentEm), widthEm: wEm, scale, paint, isMissing: true, midBase: adv + boxAdv / 2 });
61322
61370
  adv += boxAdv;
61323
61371
  } else {
61324
61372
  adv += (g ? g.width : 0) * scale;
@@ -61374,6 +61422,7 @@ ${codeFrame}` : message);
61374
61422
  const placements = placeCells.map((c) => ({
61375
61423
  glyphD: c.glyphD,
61376
61424
  paint: c.paint,
61425
+ isMissing: c.isMissing,
61377
61426
  m: alongAffine(sampler, base + c.midBase * k, c.scale, c.widthEm, perp)
61378
61427
  }));
61379
61428
  return toGroup(node, buildPaths(placements, create, warnings), create);
@@ -61462,12 +61511,13 @@ ${codeFrame}` : message);
61462
61511
  const transform = { keyframes: kfs };
61463
61512
  if (loop !== void 0) transform.loop = loop;
61464
61513
  const animate = { transform };
61514
+ if (c.paint.animate) Object.assign(animate, c.paint.animate);
61465
61515
  if (isClip && opKfs.some((k) => k.value === 0)) {
61466
61516
  const op = { keyframes: opKfs };
61467
61517
  if (loop !== void 0) op.loop = loop;
61468
61518
  animate.opacity = op;
61469
61519
  }
61470
- out.push(create("path", __spreadProps2(__spreadValues2({ d }, paintProps(c.paint)), { animate }), []));
61520
+ out.push(create("path", __spreadProps2(__spreadValues2(__spreadValues2({ d }, paintProps(c.paint)), missingGlyphProps(c.isMissing)), { animate }), []));
61471
61521
  }
61472
61522
  return out;
61473
61523
  }
@@ -61476,24 +61526,34 @@ ${codeFrame}` : message);
61476
61526
  if (paint.fill !== void 0) p.fill = paint.fill;
61477
61527
  if (paint.stroke !== void 0) p.stroke = paint.stroke;
61478
61528
  if (paint.strokeWidth !== void 0) p.strokeWidth = paint.strokeWidth;
61529
+ if (paint.opacity !== void 0) p.opacity = paint.opacity;
61530
+ for (const key of PAINT_STATIC_KEYS) {
61531
+ if (paint[key] !== void 0) p[key] = paint[key];
61532
+ }
61479
61533
  return p;
61480
61534
  }
61535
+ function missingGlyphProps(isMissing) {
61536
+ return isMissing ? { class: MISSING_GLYPH_CLASS_NAME } : {};
61537
+ }
61481
61538
  function buildPaths(placements, create, warnings) {
61482
- var _a, _b, _c;
61483
61539
  if (!placements.length) {
61484
61540
  warnings == null ? void 0 : warnings.push("textGlyphs: nothing to render");
61485
61541
  return [];
61486
61542
  }
61487
61543
  const byPaint = /* @__PURE__ */ new Map();
61488
61544
  for (const p of placements) {
61489
- const key = JSON.stringify([(_a = p.paint.fill) != null ? _a : null, (_b = p.paint.stroke) != null ? _b : null, (_c = p.paint.strokeWidth) != null ? _c : null]);
61545
+ const key = JSON.stringify([p.paint, !!p.isMissing]);
61490
61546
  const baked = transformPathData(p.glyphD, p.m);
61491
61547
  const entry = byPaint.get(key);
61492
61548
  if (entry) entry.d += baked;
61493
- else byPaint.set(key, { paint: p.paint, d: baked });
61549
+ else byPaint.set(key, { paint: p.paint, d: baked, isMissing: p.isMissing });
61494
61550
  }
61495
61551
  const out = [];
61496
- for (const { paint, d } of byPaint.values()) out.push(create("path", __spreadValues2({ d }, paintProps(paint)), []));
61552
+ for (const { paint, d, isMissing } of byPaint.values()) {
61553
+ out.push(create("path", __spreadValues2(__spreadValues2(__spreadValues2({
61554
+ d
61555
+ }, paintProps(paint)), missingGlyphProps(isMissing)), paint.animate !== void 0 ? { animate: __spreadValues2({}, paint.animate) } : {}), []));
61556
+ }
61497
61557
  return out;
61498
61558
  }
61499
61559
  function toGroup(node, children, create) {
@@ -62812,6 +62872,10 @@ ${codeFrame}` : message);
62812
62872
  if (!config || !isScrollTimeline(config)) return null;
62813
62873
  const scroll = config.scroll || {};
62814
62874
  const kind = (_a = scroll.kind) != null ? _a : "view";
62875
+ if (scroll.smoothing) {
62876
+ console.warn('scroll timeline: `smoothing` needs the built-in driver \u2014 ignoring `driver: "native"`');
62877
+ return null;
62878
+ }
62815
62879
  const g = globalThis;
62816
62880
  const view = kind === "view";
62817
62881
  const Ctor = view ? g.ViewTimeline : g.ScrollTimeline;
@@ -62820,7 +62884,7 @@ ${codeFrame}` : message);
62820
62884
  let timeline;
62821
62885
  try {
62822
62886
  if (view) {
62823
- timeline = new Ctor({ subject, axis });
62887
+ timeline = new Ctor({ subject: resolveScrollSubject(subject, scroll.subject), axis });
62824
62888
  } else {
62825
62889
  const source = scroll.source === "root" ? documentScroller() : findNearestScroller(subject, "y") || findNearestScroller(subject, "x") || documentScroller();
62826
62890
  timeline = new Ctor({ source, axis });
@@ -62836,7 +62900,10 @@ ${codeFrame}` : message);
62836
62900
  };
62837
62901
  }
62838
62902
  function findNearestScroller(el, axis) {
62903
+ const body = document.body;
62904
+ const root = document.documentElement;
62839
62905
  for (let p = el.parentElement; p; p = p.parentElement) {
62906
+ if (p === body || p === root) return null;
62840
62907
  const style = getComputedStyle(p);
62841
62908
  const overflow = axis === "y" ? style.overflowY : style.overflowX;
62842
62909
  if (overflow === "auto" || overflow === "scroll" || overflow === "hidden" || overflow === "overlay") {
@@ -62848,11 +62915,42 @@ ${codeFrame}` : message);
62848
62915
  function documentScroller() {
62849
62916
  return document.scrollingElement || document.documentElement;
62850
62917
  }
62918
+ var SUBJECT_PARENT = "parent";
62919
+ var SUBJECT_SCROLLER = "scroller";
62920
+ function resolveScrollSubject(svgRoot, subject) {
62921
+ var _a, _b;
62922
+ const spec = subject == null ? void 0 : subject.trim();
62923
+ if (!spec) return svgRoot;
62924
+ if (spec === SUBJECT_PARENT) {
62925
+ let outermostPinned = null;
62926
+ for (let p = svgRoot.parentElement; p && p !== document.body; p = p.parentElement) {
62927
+ const position = getComputedStyle(p).position;
62928
+ if (position === "sticky" || position === "fixed") outermostPinned = p;
62929
+ }
62930
+ return (_b = (_a = outermostPinned == null ? void 0 : outermostPinned.parentElement) != null ? _a : svgRoot.parentElement) != null ? _b : svgRoot;
62931
+ }
62932
+ if (spec === SUBJECT_SCROLLER) {
62933
+ return findNearestScroller(svgRoot, "y") || findNearestScroller(svgRoot, "x") || documentScroller();
62934
+ }
62935
+ let found = null;
62936
+ try {
62937
+ found = document.querySelector(spec);
62938
+ } catch (e) {
62939
+ console.warn('scroll timeline: subject "' + spec + '" is not a valid selector \u2014 measuring the SVG itself');
62940
+ return svgRoot;
62941
+ }
62942
+ if (!found) {
62943
+ console.warn('scroll timeline: subject "' + spec + '" matched no element \u2014 measuring the SVG itself');
62944
+ return svgRoot;
62945
+ }
62946
+ return found;
62947
+ }
62851
62948
  function createScrollDriver(subject, config, onProgress) {
62852
- var _a;
62949
+ var _a, _b;
62853
62950
  if (!config || !isScrollTimeline(config)) return null;
62854
62951
  const scroll = config.scroll || {};
62855
62952
  const kind = (_a = scroll.kind) != null ? _a : "view";
62953
+ const measured = resolveScrollSubject(subject, scroll.subject);
62856
62954
  const nearest = findNearestScroller(subject, "y") || findNearestScroller(subject, "x");
62857
62955
  const scroller = kind === "scroll" && scroll.source === "root" ? documentScroller() : nearest || documentScroller();
62858
62956
  const isRootScroller = scroller === documentScroller();
@@ -62863,7 +62961,7 @@ ${codeFrame}` : message);
62863
62961
  const maxOffset = axis === "y" ? scroller.scrollHeight - scroller.clientHeight : scroller.scrollWidth - scroller.clientWidth;
62864
62962
  return scrollOffsetProgress(offset, maxOffset, scroll.range);
62865
62963
  }
62866
- const subjectRect = subject.getBoundingClientRect();
62964
+ const subjectRect = measured.getBoundingClientRect();
62867
62965
  let portStart, portSize;
62868
62966
  if (isRootScroller) {
62869
62967
  portStart = 0;
@@ -62877,12 +62975,43 @@ ${codeFrame}` : message);
62877
62975
  const subjectSize = axis === "y" ? subjectRect.height : subjectRect.width;
62878
62976
  return scrollViewProgress(subjectStart, subjectSize, portSize, scroll.range);
62879
62977
  };
62880
- let rafId = null;
62978
+ const smoothingSec = Math.max(0, (_b = scroll.smoothing) != null ? _b : 0) / 1e3;
62979
+ const SETTLE_EPSILON = 1e-3;
62881
62980
  let destroyed = false;
62981
+ let smoothed = null;
62982
+ let smoothRaf = null;
62983
+ let lastFrameMs = 0;
62984
+ const emit = (target) => {
62985
+ if (!smoothingSec) {
62986
+ onProgress(target);
62987
+ return;
62988
+ }
62989
+ if (smoothed === null) {
62990
+ smoothed = target;
62991
+ onProgress(target);
62992
+ return;
62993
+ }
62994
+ if (smoothRaf !== null) return;
62995
+ lastFrameMs = 0;
62996
+ const step = (nowMs) => {
62997
+ smoothRaf = null;
62998
+ if (destroyed) return;
62999
+ const dtSec = lastFrameMs ? Math.min(0.1, (nowMs - lastFrameMs) / 1e3) : 1 / 60;
63000
+ lastFrameMs = nowMs;
63001
+ const goal = compute();
63002
+ const k = 1 - Math.exp(-dtSec / smoothingSec);
63003
+ smoothed = smoothed + (goal - smoothed) * k;
63004
+ if (Math.abs(goal - smoothed) < SETTLE_EPSILON) smoothed = goal;
63005
+ onProgress(smoothed);
63006
+ if (smoothed !== goal) smoothRaf = requestAnimationFrame(step);
63007
+ };
63008
+ smoothRaf = requestAnimationFrame(step);
63009
+ };
63010
+ let rafId = null;
62882
63011
  const tick = () => {
62883
63012
  rafId = null;
62884
63013
  if (destroyed) return;
62885
- onProgress(compute());
63014
+ emit(compute());
62886
63015
  };
62887
63016
  const schedule = () => {
62888
63017
  if (destroyed || rafId !== null) return;
@@ -62894,7 +63023,8 @@ ${codeFrame}` : message);
62894
63023
  let resizeObserver;
62895
63024
  if (typeof ResizeObserver !== "undefined") {
62896
63025
  resizeObserver = new ResizeObserver(schedule);
62897
- resizeObserver.observe(subject);
63026
+ resizeObserver.observe(measured);
63027
+ if (measured !== subject) resizeObserver.observe(subject);
62898
63028
  if (!isRootScroller) resizeObserver.observe(scroller);
62899
63029
  }
62900
63030
  const driver = {
@@ -62908,14 +63038,76 @@ ${codeFrame}` : message);
62908
63038
  cancelAnimationFrame(rafId);
62909
63039
  rafId = null;
62910
63040
  }
63041
+ if (smoothRaf !== null) {
63042
+ cancelAnimationFrame(smoothRaf);
63043
+ smoothRaf = null;
63044
+ }
62911
63045
  },
63046
+ // `refresh` is a deliberate JUMP (attach, host relayout) — never eased.
62912
63047
  refresh: () => {
62913
- if (!destroyed) onProgress(compute());
63048
+ if (!destroyed) {
63049
+ smoothed = compute();
63050
+ onProgress(smoothed);
63051
+ }
62914
63052
  }
62915
63053
  };
62916
63054
  driver.refresh();
62917
63055
  return driver;
62918
63056
  }
63057
+ function pinScrollportHeight(svgRoot) {
63058
+ const scroller = findNearestScroller(svgRoot, "y");
63059
+ return scroller ? scroller.clientHeight : document.documentElement.clientHeight;
63060
+ }
63061
+ function applyScrollPin(svgRoot, scroll) {
63062
+ const styled = svgRoot;
63063
+ if (!(scroll == null ? void 0 : scroll.pin) || !styled.style) return () => {
63064
+ };
63065
+ const style = styled.style;
63066
+ const prevPosition = style.position;
63067
+ const prevTop = style.top;
63068
+ style.position = "sticky";
63069
+ const alignFactor = scroll.pinAlign === "center" ? 0.5 : scroll.pinAlign === "bottom" ? 1 : 0;
63070
+ const applyTop = () => {
63071
+ var _a;
63072
+ const extra = (_a = scroll.pinTop) != null ? _a : 0;
63073
+ if (!alignFactor) {
63074
+ style.top = extra + "px";
63075
+ return;
63076
+ }
63077
+ const portSize = pinScrollportHeight(svgRoot);
63078
+ const ownSize = svgRoot.getBoundingClientRect().height;
63079
+ style.top = Math.round((portSize - ownSize) * alignFactor + extra) + "px";
63080
+ };
63081
+ applyTop();
63082
+ let resizeObserver = null;
63083
+ const onWindowResize = alignFactor ? applyTop : null;
63084
+ if (alignFactor) {
63085
+ if (onWindowResize) window.addEventListener("resize", onWindowResize);
63086
+ if (typeof ResizeObserver !== "undefined") {
63087
+ resizeObserver = new ResizeObserver(applyTop);
63088
+ resizeObserver.observe(svgRoot);
63089
+ }
63090
+ }
63091
+ let wrapper = null;
63092
+ const parent = svgRoot.parentElement;
63093
+ if (scroll.pinDistance && scroll.pinDistance > 0 && parent) {
63094
+ wrapper = document.createElement("div");
63095
+ wrapper.setAttribute("data-px-pin", "");
63096
+ wrapper.style.height = scroll.pinDistance * 100 + "vh";
63097
+ parent.insertBefore(wrapper, svgRoot);
63098
+ wrapper.appendChild(svgRoot);
63099
+ }
63100
+ return () => {
63101
+ if (onWindowResize) window.removeEventListener("resize", onWindowResize);
63102
+ resizeObserver == null ? void 0 : resizeObserver.disconnect();
63103
+ style.position = prevPosition;
63104
+ style.top = prevTop;
63105
+ if (wrapper == null ? void 0 : wrapper.parentElement) {
63106
+ wrapper.parentElement.insertBefore(svgRoot, wrapper);
63107
+ wrapper.remove();
63108
+ }
63109
+ };
63110
+ }
62919
63111
  function finaliseAnimator(animatorConfig, callbacks, make) {
62920
63112
  let apiRef;
62921
63113
  let effectiveCallbacks = callbacks;
@@ -62940,7 +63132,10 @@ ${codeFrame}` : message);
62940
63132
  if (isScrollTimeline(animatorConfig)) {
62941
63133
  return finaliseAnimator(animatorConfig, callbacks, (cb) => {
62942
63134
  var _a, _b;
63135
+ let unpin = () => {
63136
+ };
62943
63137
  if (animatorConfig.mode !== PxAnimatorMode.frames && ((_a = animatorConfig.scroll) == null ? void 0 : _a.driver) === "native" && rootElement) {
63138
+ unpin = applyScrollPin(rootElement, animatorConfig.scroll);
62944
63139
  const native = createNativeScrollTimeline(rootElement, animatorConfig);
62945
63140
  if (native) {
62946
63141
  const api2 = createWebApiAnimator(
@@ -62950,12 +63145,23 @@ ${codeFrame}` : message);
62950
63145
  animatorConfig.mode === PxAnimatorMode.waapi,
62951
63146
  native
62952
63147
  );
62953
- if (api2) return api2;
63148
+ if (api2) {
63149
+ const destroyNative = api2.destroy.bind(api2);
63150
+ api2.destroy = () => {
63151
+ unpin();
63152
+ destroyNative();
63153
+ };
63154
+ return api2;
63155
+ }
62954
63156
  }
63157
+ unpin();
63158
+ unpin = () => {
63159
+ };
62955
63160
  }
62956
63161
  const api = (animatorConfig.mode !== PxAnimatorMode.frames ? createWebApiAnimator(doc, cb, rootElement, animatorConfig.mode === PxAnimatorMode.waapi) : null) || createFrameLoopAnimator(doc, adapter, cb, rootElement);
62957
63162
  const subject = ((_b = api.getRootElement) == null ? void 0 : _b.call(api)) || rootElement;
62958
63163
  if (subject) {
63164
+ unpin = applyScrollPin(subject, animatorConfig.scroll);
62959
63165
  const totalMs = scrollTotalDurationMs(animatorConfig);
62960
63166
  const driver = createScrollDriver(
62961
63167
  subject,
@@ -62966,6 +63172,7 @@ ${codeFrame}` : message);
62966
63172
  const destroy = api.destroy.bind(api);
62967
63173
  api.destroy = () => {
62968
63174
  driver.destroy();
63175
+ unpin();
62969
63176
  destroy();
62970
63177
  };
62971
63178
  }