@unseenco/theatre-gsap 0.4.3 → 0.5.0

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.js CHANGED
@@ -20,19 +20,30 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var src_exports = {};
22
22
  __export(src_exports, {
23
- attachGsapSequenceBridge: () => import_theatre_core.attachGsapSequenceBridge,
23
+ attachGsapSequenceBridge: () => import_theatre_core2.attachGsapSequenceBridge,
24
+ attachTheatrePageScroll: () => attachTheatrePageScroll,
25
+ bindGsapScrollTriggerPlugin: () => bindGsapScrollTriggerPlugin,
26
+ bindGsapTickerToRafDriver: () => bindGsapTickerToRafDriver,
24
27
  configureTheatreGsap: () => configureTheatreGsap,
28
+ createDefaultPageScrollDriver: () => createDefaultPageScrollDriver,
25
29
  getAnimationEntry: () => getAnimationEntry2,
26
30
  getAnimationEntryById: () => getAnimationEntryById,
27
31
  getAnimationEntryForSheetObject: () => getAnimationEntryForSheetObject2,
28
32
  getTheatreGsapConfig: () => getTheatreGsapConfig,
33
+ getTheatrePageScrollContext: () => getTheatrePageScrollContext,
34
+ isRafDriverDrivenByGsapTicker: () => isRafDriverDrivenByGsapTicker,
29
35
  listAnimationEntries: () => listAnimationEntries2,
30
- registerGsapAnimation: () => registerGsapAnimation
36
+ refreshRegisteredGsapScrollTriggerLayouts: () => refreshRegisteredGsapScrollTriggerLayouts,
37
+ registerAllGsapScrollTriggers: () => registerAllGsapScrollTriggers,
38
+ registerGsapAnimation: () => registerGsapAnimation,
39
+ registerGsapScrollTrigger: () => registerGsapScrollTrigger,
40
+ scheduleGsapTickerRafWarningCheck: () => scheduleGsapTickerRafWarningCheck,
41
+ warnIfGsapTickerNotDrivingTheatreRaf: () => warnIfGsapTickerNotDrivingTheatreRaf
31
42
  });
32
43
  module.exports = __toCommonJS(src_exports);
33
44
 
34
45
  // src/registerGsapAnimation.ts
35
- var import_privateAPIs = require("@unseenco/theatre-core/privateAPIs");
46
+ var import_privateAPIs2 = require("@unseenco/theatre-core/privateAPIs");
36
47
 
37
48
  // ../../theatre/shared/src/utils/errors.ts
38
49
  var TheatreError = class extends Error {
@@ -555,11 +566,11 @@ function validateAndSanitiseSlashedPathOrThrow(unsanitisedPath, fnName) {
555
566
  Please replace the path with the sanitized one, otherwise it will likely break in the future.`,
556
567
  [
557
568
  {
558
- url: "https://www.theatrejs.com/docs/latest/manual/objects#creating-sheet-objects",
569
+ url: "https://unseen-theatre.netlify.app/docs/guide/manual/objects#creating-objects",
559
570
  title: "Sheet Objects"
560
571
  },
561
572
  {
562
- url: "https://www.theatrejs.com/docs/latest/api/core#sheet.object",
573
+ url: "https://unseen-theatre.netlify.app/docs/api/theatre-core#sheet.object",
563
574
  title: "API"
564
575
  }
565
576
  ]
@@ -628,6 +639,21 @@ function linkGsapTimelineChildAnimations(animation) {
628
639
  return map;
629
640
  }
630
641
 
642
+ // ../../theatre/shared/src/gsap/gsapAnimationLabel.ts
643
+ function readGsapAnimationVarsId(animation) {
644
+ const id = animation.vars?.id;
645
+ if (typeof id === "string" && id.trim().length > 0) {
646
+ return id.trim();
647
+ }
648
+ return void 0;
649
+ }
650
+ function resolveGsapAnimationRegistrationLabel(animation, optionsLabel, fallback = "GSAP animation") {
651
+ if (typeof optionsLabel === "string" && optionsLabel.length > 0) {
652
+ return optionsLabel;
653
+ }
654
+ return readGsapAnimationVarsId(animation) ?? fallback;
655
+ }
656
+
631
657
  // ../../theatre/shared/src/gsap/gsapSheetObjectKey.ts
632
658
  var GSAP_NAMESPACE_STORE_KEY = "__unseenco_theatre_gsap_configuredNamespace__";
633
659
  function setConfiguredGsapSheetObjectNamespace(namespace) {
@@ -2226,22 +2252,136 @@ function listAnimationEntries() {
2226
2252
  return entries;
2227
2253
  }
2228
2254
 
2255
+ // ../../theatre/shared/src/sheets/pageScrollContext.ts
2256
+ var defaultPageScrollContext = {
2257
+ scroller: null,
2258
+ axis: "vertical"
2259
+ };
2260
+ var activePageScrollContext = defaultPageScrollContext;
2261
+ function setActivePageScrollContext(context) {
2262
+ activePageScrollContext = {
2263
+ scroller: context.scroller,
2264
+ axis: context.axis ?? "vertical"
2265
+ };
2266
+ }
2267
+ function resolvePageScrollAxis(context = defaultPageScrollContext) {
2268
+ return context.axis ?? "vertical";
2269
+ }
2270
+ function resolvePageScrollScroller(st, defaultsScroller) {
2271
+ const surface = st;
2272
+ const fromSt = surface.scroller ?? surface.vars?.scroller;
2273
+ if (fromSt != null) {
2274
+ return fromSt;
2275
+ }
2276
+ if (defaultsScroller !== void 0) {
2277
+ return defaultsScroller;
2278
+ }
2279
+ return null;
2280
+ }
2281
+ function isWindowLike(value) {
2282
+ return typeof Window !== "undefined" && (value === window || value instanceof Window);
2283
+ }
2284
+ function isNativeDocumentScroller(scroller) {
2285
+ if (scroller == null)
2286
+ return true;
2287
+ if (isWindowLike(scroller))
2288
+ return true;
2289
+ if (typeof document === "undefined")
2290
+ return false;
2291
+ return scroller === document.documentElement || scroller === document.body;
2292
+ }
2293
+ function pageScrollScrollersMatch(a, b) {
2294
+ if (a === b)
2295
+ return true;
2296
+ if (isNativeDocumentScroller(a) && isNativeDocumentScroller(b))
2297
+ return true;
2298
+ return false;
2299
+ }
2300
+ function isScrollTriggerHorizontal(st) {
2301
+ const surface = st;
2302
+ return surface.horizontal === true || surface.vars?.horizontal === true;
2303
+ }
2304
+ function isPageScrollTrigger(st, context = defaultPageScrollContext) {
2305
+ const axis = resolvePageScrollAxis(context);
2306
+ const stHorizontal = isScrollTriggerHorizontal(st);
2307
+ if (stHorizontal !== (axis === "horizontal")) {
2308
+ return false;
2309
+ }
2310
+ const stScroller = resolvePageScrollScroller(st, context.scroller);
2311
+ return pageScrollScrollersMatch(stScroller, context.scroller);
2312
+ }
2313
+
2314
+ // src/gsapScrollTriggerPlugin.ts
2315
+ var import_ScrollTrigger = require("gsap/ScrollTrigger");
2316
+ var boundScrollTrigger;
2317
+ function bindGsapScrollTriggerPlugin(scrollTrigger) {
2318
+ boundScrollTrigger = scrollTrigger;
2319
+ }
2320
+ function getGsapScrollTriggerPlugin() {
2321
+ if (boundScrollTrigger) {
2322
+ return boundScrollTrigger;
2323
+ }
2324
+ const g = globalThis;
2325
+ return g.ScrollTrigger ?? import_ScrollTrigger.ScrollTrigger;
2326
+ }
2327
+ function requireGsapScrollTriggerPlugin() {
2328
+ const plugin = getGsapScrollTriggerPlugin();
2329
+ if (!plugin) {
2330
+ throw new Error(
2331
+ 'ScrollTrigger is not available. Import ScrollTrigger from "gsap/ScrollTrigger", call gsap.registerPlugin(ScrollTrigger), and optionally bindGsapScrollTriggerPlugin(ScrollTrigger) before registering scroll triggers with Theatre.'
2332
+ );
2333
+ }
2334
+ return plugin;
2335
+ }
2336
+ function refreshGsapScrollTriggers() {
2337
+ getGsapScrollTriggerPlugin()?.refresh();
2338
+ }
2339
+
2229
2340
  // src/config.ts
2230
2341
  var activeConfig = {
2231
2342
  namespace: "GSAP",
2232
2343
  outlineNamespace: { defaultCollapsed: false }
2233
2344
  };
2234
2345
  setConfiguredGsapSheetObjectNamespace(activeConfig.namespace);
2346
+ function pageScrollContextFromConfig(pageScroll) {
2347
+ return {
2348
+ scroller: pageScroll.scroller ?? defaultPageScrollContext.scroller,
2349
+ axis: pageScroll.axis ?? defaultPageScrollContext.axis ?? "vertical"
2350
+ };
2351
+ }
2352
+ function applyScrollTriggerDefaultsForPageScroll(pageScroll) {
2353
+ const ScrollTrigger = getGsapScrollTriggerPlugin();
2354
+ const { scroller, axis } = pageScrollContextFromConfig(pageScroll);
2355
+ ScrollTrigger?.defaults?.({
2356
+ scroller: scroller ?? void 0,
2357
+ ...axis === "horizontal" ? { horizontal: true } : {}
2358
+ });
2359
+ }
2235
2360
  function configureTheatreGsap(config) {
2236
2361
  const prev = activeConfig;
2237
2362
  activeConfig = {
2238
2363
  namespace: config.namespace ?? prev.namespace ?? "GSAP",
2239
- outlineNamespace: config.outlineNamespace ?? prev.outlineNamespace
2364
+ outlineNamespace: config.outlineNamespace ?? prev.outlineNamespace,
2365
+ suppressGsapTickerRafWarning: config.suppressGsapTickerRafWarning ?? prev.suppressGsapTickerRafWarning,
2366
+ pageScroll: config.pageScroll ?? prev.pageScroll
2240
2367
  };
2241
2368
  setConfiguredGsapSheetObjectNamespace(activeConfig.namespace ?? "GSAP");
2369
+ if (config.pageScroll !== void 0) {
2370
+ const ctx = pageScrollContextFromConfig(config.pageScroll);
2371
+ setActivePageScrollContext(ctx);
2372
+ applyScrollTriggerDefaultsForPageScroll(config.pageScroll);
2373
+ }
2242
2374
  return {
2243
2375
  reset() {
2244
2376
  activeConfig = prev;
2377
+ setConfiguredGsapSheetObjectNamespace(prev.namespace ?? "GSAP");
2378
+ if (prev.pageScroll !== void 0) {
2379
+ const ctx = pageScrollContextFromConfig(prev.pageScroll);
2380
+ setActivePageScrollContext(ctx);
2381
+ applyScrollTriggerDefaultsForPageScroll(prev.pageScroll);
2382
+ } else {
2383
+ setActivePageScrollContext(defaultPageScrollContext);
2384
+ }
2245
2385
  }
2246
2386
  };
2247
2387
  }
@@ -2298,33 +2438,479 @@ function formatOutlineNamespacePathKey(pathSegments) {
2298
2438
  return pathSegments.join(" / ");
2299
2439
  }
2300
2440
 
2441
+ // src/gsapTickerRafBridge.ts
2442
+ var import_privateAPIs = require("@unseenco/theatre-core/privateAPIs");
2443
+ var gsapTickerDrivenDriverIds = /* @__PURE__ */ new Set();
2444
+ function bindGsapTickerToRafDriver(rafDriver, gsap) {
2445
+ const onTick = (time) => {
2446
+ rafDriver.tick(time * 1e3);
2447
+ };
2448
+ gsapTickerDrivenDriverIds.add(rafDriver.id);
2449
+ gsap.ticker.add(onTick);
2450
+ return () => {
2451
+ gsap.ticker.remove(onTick);
2452
+ gsapTickerDrivenDriverIds.delete(rafDriver.id);
2453
+ };
2454
+ }
2455
+ function isRafDriverDrivenByGsapTicker(rafDriver) {
2456
+ return gsapTickerDrivenDriverIds.has(rafDriver.id);
2457
+ }
2458
+ var hasWarnedGsapTickerRaf = false;
2459
+ var gsapTickerRafWarningMicrotaskQueued = false;
2460
+ function scheduleGsapTickerRafWarningCheck() {
2461
+ if (gsapTickerRafWarningMicrotaskQueued)
2462
+ return;
2463
+ gsapTickerRafWarningMicrotaskQueued = true;
2464
+ queueMicrotask(() => {
2465
+ gsapTickerRafWarningMicrotaskQueued = false;
2466
+ warnIfGsapTickerNotDrivingTheatreRaf();
2467
+ });
2468
+ }
2469
+ function warnIfGsapTickerNotDrivingTheatreRaf() {
2470
+ if (typeof window === "undefined")
2471
+ return;
2472
+ if (getTheatreGsapConfig().suppressGsapTickerRafWarning)
2473
+ return;
2474
+ if (hasWarnedGsapTickerRaf)
2475
+ return;
2476
+ const coreDriver = (0, import_privateAPIs.getTheatreCoreRafDriver)();
2477
+ if (!isRafDriverDrivenByGsapTicker(coreDriver)) {
2478
+ hasWarnedGsapTickerRaf = true;
2479
+ console.warn(
2480
+ "[theatre-gsap] Theatre is not driven by gsap.ticker. After setCoreRafDriver(), call bindGsapTickerToRafDriver(rafDriver, gsap) so GSAP and Theatre share one clock. See the GSAP extension guide."
2481
+ );
2482
+ }
2483
+ }
2484
+
2301
2485
  // src/registerGsapAnimation.ts
2302
2486
  function registerGsapAnimation(animation, sheet, options) {
2303
2487
  const config = getTheatreGsapConfig();
2304
2488
  const namespace = options.namespace ?? config.namespace ?? "GSAP";
2305
- const objectKey = buildGsapSheetObjectKey(namespace, options.label);
2489
+ const label = resolveGsapAnimationRegistrationLabel(animation, options.label);
2490
+ const objectKey = buildGsapSheetObjectKey(namespace, label);
2306
2491
  const id = options.id ?? objectKey;
2307
2492
  animation.pause();
2308
2493
  const sheetObjectPublic = sheet.object(objectKey, {}, { reconfigure: false });
2309
- const sheetObjectInternal = (0, import_privateAPIs.privateAPI)(sheetObjectPublic);
2494
+ const sheetObjectInternal = (0, import_privateAPIs2.privateAPI)(sheetObjectPublic);
2310
2495
  const existing = getAnimationEntry(sheetObjectInternal, id);
2311
2496
  if (config.outlineNamespace && !existing) {
2312
- (0, import_privateAPIs.privateAPI)(sheet).template.setOutlineNamespaceConfig(
2497
+ (0, import_privateAPIs2.privateAPI)(sheet).template.setOutlineNamespaceConfig(
2313
2498
  formatOutlineNamespacePathKey([namespace]),
2314
2499
  config.outlineNamespace
2315
2500
  );
2316
2501
  }
2317
2502
  registerAnimationInRegistry2({
2318
2503
  id,
2319
- label: options.label,
2504
+ label,
2320
2505
  animation,
2321
2506
  sheetObject: sheetObjectInternal,
2322
- defaultDuration: options.defaultDuration,
2507
+ defaultDuration: options.defaultDuration ?? (sheet.getSequenceMode() === "page" ? 10 : void 0),
2323
2508
  onRebuildTimeline: options.onRebuildTimeline
2324
2509
  });
2510
+ scheduleGsapTickerRafWarningCheck();
2325
2511
  return { id, sheetObject: sheetObjectPublic };
2326
2512
  }
2327
2513
 
2328
- // src/attachGsapSequenceBridge.ts
2514
+ // src/registerGsapScrollTrigger.ts
2515
+ var import_privateAPIs3 = require("@unseenco/theatre-core/privateAPIs");
2516
+
2517
+ // ../../theatre/shared/src/gsap/scrollTriggerGuards.ts
2518
+ function resolveScrollTriggerAnimation(st) {
2519
+ const surface = st;
2520
+ if (surface.animation != null)
2521
+ return surface.animation;
2522
+ if (surface.vars?.animation != null)
2523
+ return surface.vars.animation;
2524
+ return void 0;
2525
+ }
2526
+ function defaultScrollTriggerLabel(st, fallbackIndex) {
2527
+ const surface = st;
2528
+ const id = surface.vars?.id;
2529
+ if (typeof id === "string" && id.length > 0)
2530
+ return id;
2531
+ const trigger = surface.trigger;
2532
+ if (trigger && typeof trigger === "object" && "id" in trigger) {
2533
+ const elementId = trigger.id;
2534
+ if (typeof elementId === "string" && elementId.length > 0) {
2535
+ return elementId;
2536
+ }
2537
+ }
2538
+ return `ScrollTrigger ${fallbackIndex + 1}`;
2539
+ }
2540
+ function readAnimationSpanSeconds(animation) {
2541
+ return Math.max(readGsapTweenTimelineDuration(animation), MIN_ANIMATION_SPAN);
2542
+ }
2543
+ var MIN_ANIMATION_SPAN = 0.01;
2544
+
2545
+ // ../../theatre/shared/src/gsap/scrollTriggerLayout.ts
2546
+ var MIN_SEQUENCE_DURATION = 0.01;
2547
+ function scrollPixelsToPageUnits(startPx, endPx, maxScrollPx, sequenceLength) {
2548
+ const length = Math.max(sequenceLength, MIN_SEQUENCE_DURATION);
2549
+ if (maxScrollPx <= 0) {
2550
+ return { start: 0, duration: length };
2551
+ }
2552
+ const startProgress = Math.max(0, Math.min(1, startPx / maxScrollPx));
2553
+ const endProgress = Math.max(0, Math.min(1, endPx / maxScrollPx));
2554
+ const lo = Math.min(startProgress, endProgress);
2555
+ const hi = Math.max(startProgress, endProgress);
2556
+ let start = lo * length;
2557
+ let duration = Math.max((hi - lo) * length, MIN_SEQUENCE_DURATION);
2558
+ if (start + duration > length) {
2559
+ start = Math.max(0, length - duration);
2560
+ }
2561
+ if (start < 0)
2562
+ start = 0;
2563
+ return { start, duration };
2564
+ }
2565
+ function getNativeDocumentMaxScroll(axis = "vertical") {
2566
+ if (typeof document === "undefined" || typeof window === "undefined") {
2567
+ return 0;
2568
+ }
2569
+ const el = document.documentElement;
2570
+ if (axis === "horizontal") {
2571
+ const scrolling = document.scrollingElement ?? el;
2572
+ return Math.max(0, scrolling.scrollWidth - scrolling.clientWidth);
2573
+ }
2574
+ return Math.max(0, el.scrollHeight - window.innerHeight);
2575
+ }
2576
+ function getMaxScrollForScroller(scroller, axis = "vertical") {
2577
+ if (typeof document === "undefined" || typeof window === "undefined") {
2578
+ return 0;
2579
+ }
2580
+ if (isNativeDocumentScroller(scroller)) {
2581
+ return getNativeDocumentMaxScroll(axis);
2582
+ }
2583
+ const el = scroller;
2584
+ if (axis === "horizontal") {
2585
+ return Math.max(0, el.scrollWidth - el.clientWidth);
2586
+ }
2587
+ return Math.max(0, el.scrollHeight - el.clientHeight);
2588
+ }
2589
+ function getMaxScrollForPageScrollContext(scroller, axis = "vertical") {
2590
+ return getMaxScrollForScroller(scroller, axis);
2591
+ }
2592
+
2593
+ // ../../theatre/shared/src/sheets/remotePageScrollMetrics.ts
2594
+ var remoteMetrics;
2595
+ function resolveMaxScrollPxForPageLayout(localMaxScrollPx, axis) {
2596
+ if (localMaxScrollPx > 0) {
2597
+ return localMaxScrollPx;
2598
+ }
2599
+ const remote = remoteMetrics;
2600
+ if (remote && remote.axis === axis && remote.maxScroll > 0) {
2601
+ return remote.maxScroll;
2602
+ }
2603
+ return localMaxScrollPx;
2604
+ }
2605
+
2606
+ // ../../theatre/shared/src/gsap/extractScrollTriggerLayout.ts
2607
+ function extractScrollTriggerLayout(st, options) {
2608
+ const pageScrollContext = options.pageScrollContext ?? defaultPageScrollContext;
2609
+ if (!isPageScrollTrigger(st, pageScrollContext)) {
2610
+ return { ok: false, reason: "unsupported_scroller" };
2611
+ }
2612
+ const surface = st;
2613
+ const animation = resolveScrollTriggerAnimation(st);
2614
+ if (!animation) {
2615
+ return { ok: false, reason: "missing_animation" };
2616
+ }
2617
+ const axis = resolvePageScrollAxis(pageScrollContext);
2618
+ const localMaxScroll = getMaxScrollForPageScrollContext(
2619
+ pageScrollContext.scroller,
2620
+ axis
2621
+ );
2622
+ const maxScroll = resolveMaxScrollPxForPageLayout(localMaxScroll, axis);
2623
+ const layout = scrollPixelsToPageUnits(
2624
+ surface.start,
2625
+ surface.end,
2626
+ maxScroll,
2627
+ options.sequenceLength
2628
+ );
2629
+ const fallbackIndex = options.fallbackIndex ?? 0;
2630
+ const label = options.label ?? defaultScrollTriggerLabel(st, fallbackIndex);
2631
+ const id = options.id ?? (typeof surface.vars?.id === "string" && surface.vars.id.length > 0 ? surface.vars.id : `st_${label.replace(/\s+/g, "_")}_${fallbackIndex}`);
2632
+ const kind = isGsapTimeline(animation) ? "timeline" : "tween";
2633
+ const animationSpanSeconds = readAnimationSpanSeconds(animation);
2634
+ const timelineChildren = kind === "timeline" ? introspectGsapTimelineChildren(animation) : [];
2635
+ return {
2636
+ ok: true,
2637
+ value: {
2638
+ id,
2639
+ label,
2640
+ layout,
2641
+ kind,
2642
+ animationSpanSeconds,
2643
+ timelineChildren
2644
+ }
2645
+ };
2646
+ }
2647
+
2648
+ // ../../theatre/shared/src/gsap/scrollTriggerRegistry.ts
2649
+ var DEFAULT_SHEET_INSTANCE_ID2 = "default";
2650
+ var REGISTRY_KEY2 = "__unseenco_theatre_gsap_scrollTriggerRegistry__";
2651
+ function sheetAddressKey(address) {
2652
+ const sheetInstanceId = address.sheetInstanceId ?? DEFAULT_SHEET_INSTANCE_ID2;
2653
+ return `${address.projectId}|${address.sheetId}|${sheetInstanceId}`;
2654
+ }
2655
+ function getStore3() {
2656
+ const g = globalThis;
2657
+ if (!g[REGISTRY_KEY2]) {
2658
+ g[REGISTRY_KEY2] = { bySheetAddress: /* @__PURE__ */ new Map() };
2659
+ }
2660
+ return g[REGISTRY_KEY2];
2661
+ }
2662
+ function getSheetMap(key) {
2663
+ const store = getStore3();
2664
+ let map = store.bySheetAddress.get(key);
2665
+ if (!map) {
2666
+ map = /* @__PURE__ */ new Map();
2667
+ store.bySheetAddress.set(key, map);
2668
+ }
2669
+ return map;
2670
+ }
2671
+ function registerScrollTriggerInRegistry(sheetKey, entry) {
2672
+ const map = getSheetMap(sheetKey);
2673
+ for (const existing of map.values()) {
2674
+ if (existing.scrollTrigger === entry.scrollTrigger) {
2675
+ return "duplicate";
2676
+ }
2677
+ if (existing.id === entry.id) {
2678
+ return "duplicate";
2679
+ }
2680
+ }
2681
+ map.set(entry.id, entry);
2682
+ bumpGsapStudioRegistryRevision();
2683
+ return "registered";
2684
+ }
2685
+ function findScrollTriggerEntryByInstance(sheetKey, scrollTrigger) {
2686
+ const map = getStore3().bySheetAddress.get(sheetKey);
2687
+ if (!map)
2688
+ return void 0;
2689
+ for (const entry of map.values()) {
2690
+ if (entry.scrollTrigger === scrollTrigger) {
2691
+ return entry;
2692
+ }
2693
+ }
2694
+ return void 0;
2695
+ }
2696
+ function updateScrollTriggerLayoutInRegistry(sheetKey, id, patch) {
2697
+ const existing = getSheetMap(sheetKey).get(id);
2698
+ if (!existing)
2699
+ return;
2700
+ getSheetMap(sheetKey).set(id, { ...existing, ...patch });
2701
+ bumpGsapStudioRegistryRevision();
2702
+ }
2703
+ function listScrollTriggerEntriesForSheet(sheetKey) {
2704
+ const map = getStore3().bySheetAddress.get(sheetKey);
2705
+ if (!map)
2706
+ return [];
2707
+ return [...map.values()].sort((a, b) => a.layout.start - b.layout.start);
2708
+ }
2709
+
2710
+ // src/attachTheatrePageScroll.ts
2329
2711
  var import_theatre_core = require("@unseenco/theatre-core");
2712
+ function applyScrollTriggerDefaultsFromGsapConfig() {
2713
+ const { pageScroll } = getTheatreGsapConfig();
2714
+ if (!pageScroll)
2715
+ return;
2716
+ const ScrollTrigger = getGsapScrollTriggerPlugin();
2717
+ if (!ScrollTrigger?.defaults)
2718
+ return;
2719
+ const axis = pageScroll.axis ?? defaultPageScrollContext.axis ?? "vertical";
2720
+ ScrollTrigger.defaults({
2721
+ scroller: pageScroll.scroller ?? void 0,
2722
+ ...axis === "horizontal" ? { horizontal: true } : {}
2723
+ });
2724
+ }
2725
+ function getTheatrePageScrollContext() {
2726
+ applyScrollTriggerDefaultsFromGsapConfig();
2727
+ const pageScroll = getTheatreGsapConfig().pageScroll;
2728
+ if (pageScroll) {
2729
+ const ctx = {
2730
+ scroller: pageScroll.scroller ?? defaultPageScrollContext.scroller,
2731
+ axis: pageScroll.axis ?? defaultPageScrollContext.axis
2732
+ };
2733
+ setActivePageScrollContext(ctx);
2734
+ return ctx;
2735
+ }
2736
+ return (0, import_theatre_core.getTheatrePageScrollContext)();
2737
+ }
2738
+ function createDefaultPageScrollDriver(scroller = getTheatrePageScrollContext().scroller) {
2739
+ const ctx = getTheatrePageScrollContext();
2740
+ return (0, import_theatre_core.createDefaultPageScrollDriver)(scroller, resolvePageScrollAxis(ctx));
2741
+ }
2742
+ function attachTheatrePageScroll(sheet, options = {}) {
2743
+ applyScrollTriggerDefaultsFromGsapConfig();
2744
+ return (0, import_theatre_core.attachTheatrePageScroll)(sheet, options);
2745
+ }
2746
+
2747
+ // ../../theatre/shared/src/gsap/scrollTriggerGlobal.ts
2748
+ function refreshGsapScrollTriggersFromGlobal() {
2749
+ const ScrollTrigger = globalThis.ScrollTrigger;
2750
+ ScrollTrigger?.refresh?.();
2751
+ }
2752
+
2753
+ // ../../theatre/shared/src/gsap/refreshScrollTriggerLayoutsForSheet.ts
2754
+ function refreshScrollTriggerLayoutsForSheet(sheetKey, sequenceLength, pageScrollContext = defaultPageScrollContext) {
2755
+ refreshGsapScrollTriggersFromGlobal();
2756
+ for (const entry of listScrollTriggerEntriesForSheet(sheetKey)) {
2757
+ const extracted = extractScrollTriggerLayout(entry.scrollTrigger, {
2758
+ sequenceLength,
2759
+ id: entry.id,
2760
+ label: entry.label,
2761
+ pageScrollContext
2762
+ });
2763
+ if (!extracted.ok)
2764
+ continue;
2765
+ updateScrollTriggerLayoutInRegistry(sheetKey, entry.id, {
2766
+ layout: extracted.value.layout,
2767
+ kind: extracted.value.kind,
2768
+ animationSpanSeconds: extracted.value.animationSpanSeconds,
2769
+ timelineChildren: extracted.value.timelineChildren
2770
+ });
2771
+ }
2772
+ }
2773
+
2774
+ // src/registerGsapScrollTrigger.ts
2775
+ function assertPageMode(sheet) {
2776
+ if (sheet.getSequenceMode() !== "page") {
2777
+ throw new Error(
2778
+ 'registerGsapScrollTrigger() requires the sheet to use sequenceMode "page".'
2779
+ );
2780
+ }
2781
+ }
2782
+ function sequenceLengthForSheet(sheet) {
2783
+ return (0, import_privateAPIs3.privateAPI)(sheet).getSequence().length;
2784
+ }
2785
+ function scrollTriggerObjectKey(namespace, label) {
2786
+ return buildGsapSheetObjectKey(namespace, `ScrollTriggers / ${label}`);
2787
+ }
2788
+ function registerOneGsapScrollTriggerOnSheet(sheet, st, options, fallbackIndex) {
2789
+ const config = getTheatreGsapConfig();
2790
+ const namespace = options.namespace ?? config.namespace ?? "GSAP";
2791
+ const sheetInternal = (0, import_privateAPIs3.privateAPI)(sheet);
2792
+ const sheetKey = sheetAddressKey(sheetInternal.address);
2793
+ const sequenceLength = sequenceLengthForSheet(sheet);
2794
+ const existingByInstance = findScrollTriggerEntryByInstance(sheetKey, st);
2795
+ if (existingByInstance?.sheetObject) {
2796
+ console.warn(
2797
+ `[theatre-gsap] ScrollTrigger "${options.label}" is already registered for this sheet (id "${existingByInstance.id}"). Skipping duplicate registration.`
2798
+ );
2799
+ return {
2800
+ id: existingByInstance.id,
2801
+ sheetObject: existingByInstance.sheetObject.publicApi
2802
+ };
2803
+ }
2804
+ refreshGsapScrollTriggers();
2805
+ const pageScrollContext = getTheatrePageScrollContext();
2806
+ const extracted = extractScrollTriggerLayout(st, {
2807
+ sequenceLength,
2808
+ id: options.id,
2809
+ label: options.label,
2810
+ fallbackIndex,
2811
+ pageScrollContext
2812
+ });
2813
+ if (!extracted.ok) {
2814
+ if (extracted.reason === "unsupported_scroller") {
2815
+ console.warn(
2816
+ `[theatre-gsap] Skipped ScrollTrigger "${options.label}": scroller or scroll axis does not match configured page scroll (see configureTheatreGsap pageScroll scroller and axis).`
2817
+ );
2818
+ } else {
2819
+ console.warn(
2820
+ `[theatre-gsap] Skipped ScrollTrigger "${options.label}": no linked tween or timeline found.`
2821
+ );
2822
+ }
2823
+ return null;
2824
+ }
2825
+ const { value } = extracted;
2826
+ const objectKey = scrollTriggerObjectKey(namespace, value.label);
2827
+ const id = options.id ?? value.id;
2828
+ const sheetObjectPublic = sheet.object(objectKey, {}, { reconfigure: false });
2829
+ const sheetObjectInternal = (0, import_privateAPIs3.privateAPI)(sheetObjectPublic);
2830
+ if (config.outlineNamespace) {
2831
+ (0, import_privateAPIs3.privateAPI)(sheet).template.setOutlineNamespaceConfig(
2832
+ formatOutlineNamespacePathKey([namespace]),
2833
+ config.outlineNamespace
2834
+ );
2835
+ }
2836
+ const entry = {
2837
+ id,
2838
+ label: value.label,
2839
+ scrollTrigger: st,
2840
+ sheetObject: sheetObjectInternal,
2841
+ layout: value.layout,
2842
+ kind: value.kind,
2843
+ animationSpanSeconds: value.animationSpanSeconds,
2844
+ timelineChildren: value.timelineChildren
2845
+ };
2846
+ registerScrollTriggerInRegistry(sheetKey, entry);
2847
+ return { id, sheetObject: sheetObjectPublic };
2848
+ }
2849
+ function registerGsapScrollTrigger(scrollTrigger, sheet, options) {
2850
+ assertPageMode(sheet);
2851
+ requireGsapScrollTriggerPlugin();
2852
+ const result = registerOneGsapScrollTriggerOnSheet(
2853
+ sheet,
2854
+ scrollTrigger,
2855
+ options,
2856
+ 0
2857
+ );
2858
+ if (!result) {
2859
+ throw new Error(
2860
+ `Could not register ScrollTrigger "${options.label}". See console warnings for details.`
2861
+ );
2862
+ }
2863
+ scheduleGsapTickerRafWarningCheck();
2864
+ return result;
2865
+ }
2866
+ function refreshRegisteredGsapScrollTriggerLayouts(sheet) {
2867
+ if (sheet.getSequenceMode() !== "page")
2868
+ return;
2869
+ const sheetInternal = (0, import_privateAPIs3.privateAPI)(sheet);
2870
+ const sheetKey = sheetAddressKey(sheetInternal.address);
2871
+ refreshScrollTriggerLayoutsForSheet(
2872
+ sheetKey,
2873
+ sequenceLengthForSheet(sheet),
2874
+ getTheatrePageScrollContext()
2875
+ );
2876
+ }
2877
+
2878
+ // src/registerAllGsapScrollTriggers.ts
2879
+ var import_privateAPIs4 = require("@unseenco/theatre-core/privateAPIs");
2880
+ function registerAllGsapScrollTriggers(sheet) {
2881
+ if (sheet.getSequenceMode() !== "page") {
2882
+ throw new Error(
2883
+ 'registerAllGsapScrollTriggers() requires the sheet to use sequenceMode "page".'
2884
+ );
2885
+ }
2886
+ const ScrollTrigger = requireGsapScrollTriggerPlugin();
2887
+ refreshGsapScrollTriggers();
2888
+ const all = ScrollTrigger.getAll();
2889
+ const sheetKey = sheetAddressKey((0, import_privateAPIs4.privateAPI)(sheet).address);
2890
+ const registered = [];
2891
+ let skipped = 0;
2892
+ all.forEach((st, index) => {
2893
+ const already = findScrollTriggerEntryByInstance(sheetKey, st);
2894
+ const label = defaultScrollTriggerLabel(st, index);
2895
+ const id = typeof st.vars?.id === "string" && st.vars.id.length > 0 ? st.vars.id : void 0;
2896
+ const result = registerOneGsapScrollTriggerOnSheet(
2897
+ sheet,
2898
+ st,
2899
+ { label, id },
2900
+ index
2901
+ );
2902
+ if (!result) {
2903
+ skipped += 1;
2904
+ } else if (already) {
2905
+ skipped += 1;
2906
+ } else {
2907
+ registered.push(result);
2908
+ }
2909
+ });
2910
+ scheduleGsapTickerRafWarningCheck();
2911
+ return { registered, skipped };
2912
+ }
2913
+
2914
+ // src/attachGsapSequenceBridge.ts
2915
+ var import_theatre_core2 = require("@unseenco/theatre-core");
2330
2916
  //# sourceMappingURL=index.js.map