@surdeddd/bottom-sheet 0.5.0 → 0.6.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/react.cjs CHANGED
@@ -3437,6 +3437,38 @@ var BottomSheetEngine = class {
3437
3437
  }
3438
3438
  };
3439
3439
 
3440
+ // src/core/features/teleport.ts
3441
+ var resolveTeleportTarget = (target) => {
3442
+ if (!target) return null;
3443
+ if (typeof target !== "string") return target;
3444
+ if (typeof document === "undefined") return null;
3445
+ if (target === "body") return document.body;
3446
+ return document.querySelector(target);
3447
+ };
3448
+ var teleportElements = (els, target) => {
3449
+ const records = [];
3450
+ for (const el of els) {
3451
+ if (!el || el.parentNode === target) continue;
3452
+ records.push({ el, parent: el.parentNode, next: el.nextSibling });
3453
+ target.appendChild(el);
3454
+ }
3455
+ return () => {
3456
+ for (let i = records.length - 1; i >= 0; i--) {
3457
+ const { el, parent, next } = records[i];
3458
+ if (parent && parent.isConnected) {
3459
+ const before = next && next.parentNode === parent ? next : null;
3460
+ try {
3461
+ parent.insertBefore(el, before);
3462
+ } catch {
3463
+ el.parentNode?.removeChild(el);
3464
+ }
3465
+ } else {
3466
+ el.parentNode?.removeChild(el);
3467
+ }
3468
+ }
3469
+ };
3470
+ };
3471
+
3440
3472
  // src/react/useBottomSheet.ts
3441
3473
  var useIsomorphicLayoutEffect = typeof window !== "undefined" ? react.useLayoutEffect : react.useEffect;
3442
3474
  var SSR_STATE = Object.freeze({
@@ -3470,6 +3502,17 @@ function useBottomSheet(opts) {
3470
3502
  scrim: screenRef.current ?? void 0
3471
3503
  });
3472
3504
  engineRef.current = engine;
3505
+ const target = resolveTeleportTarget(optsRef.current.teleportTo);
3506
+ const restoreTeleport = target ? teleportElements(
3507
+ [backdropRef.current, screenRef.current, sheetRef.current],
3508
+ target
3509
+ ) : null;
3510
+ if (optsRef.current.backdropColor !== void 0) {
3511
+ engine.setScrimColor(optsRef.current.backdropColor);
3512
+ }
3513
+ if (optsRef.current.backdropOpacity !== void 0) {
3514
+ engine.setBackdropRange([0, optsRef.current.backdropOpacity]);
3515
+ }
3473
3516
  cachedSnapshotRef.current = { ...engine.state };
3474
3517
  setMounted((n) => n + 1);
3475
3518
  const refresh = () => {
@@ -3501,6 +3544,7 @@ function useBottomSheet(opts) {
3501
3544
  ];
3502
3545
  return () => {
3503
3546
  offs.forEach((off) => off());
3547
+ restoreTeleport?.();
3504
3548
  engine.destroy();
3505
3549
  engineRef.current = null;
3506
3550
  cachedSnapshotRef.current = SSR_STATE;
@@ -3516,6 +3560,18 @@ function useBottomSheet(opts) {
3516
3560
  const ids = opts.allowed ? Array.from(opts.allowed) : opts.snapPoints.map((p) => p.id);
3517
3561
  engineRef.current.setAllowed(ids);
3518
3562
  }, [allowedKey, snapKey]);
3563
+ react.useEffect(() => {
3564
+ if (!engineRef.current) return;
3565
+ if (opts.backdropColor !== void 0) {
3566
+ engineRef.current.setScrimColor(opts.backdropColor);
3567
+ }
3568
+ }, [opts.backdropColor]);
3569
+ react.useEffect(() => {
3570
+ if (!engineRef.current) return;
3571
+ if (opts.backdropOpacity !== void 0) {
3572
+ engineRef.current.setBackdropRange([0, opts.backdropOpacity]);
3573
+ }
3574
+ }, [opts.backdropOpacity]);
3519
3575
  const subscribe = react.useCallback((fn) => {
3520
3576
  subscribersRef.current.add(fn);
3521
3577
  return () => subscribersRef.current.delete(fn);
package/dist/react.d.cts CHANGED
@@ -84,6 +84,8 @@ declare const BottomSheet: react.ForwardRefExoticComponent<EngineOptionsForProps
84
84
  noSSR?: boolean;
85
85
  } & react.RefAttributes<BottomSheetHandle<string>>>;
86
86
 
87
+ type TeleportTarget = HTMLElement | string | null | undefined;
88
+
87
89
  type UseBottomSheetRefs = {
88
90
  sheetRef: React.RefObject<HTMLElement | null>;
89
91
  handleRef: React.RefObject<HTMLElement | null>;
@@ -113,6 +115,9 @@ type HookOpts<TId extends string> = Omit<EngineOptions, "element" | "handle" | "
113
115
  snapPoints: SnapPointDef<TId>[] | ReadonlyArray<SnapPointDef<TId>>;
114
116
  allowed?: TId[] | ReadonlyArray<TId>;
115
117
  initial?: TId;
118
+ teleportTo?: TeleportTarget;
119
+ backdropColor?: string;
120
+ backdropOpacity?: number;
116
121
  onSnap?: (id: TId) => void;
117
122
  onBeforeClose?: (payload: SheetEventMap["before-close"]) => void;
118
123
  onOpened?: (id: TId) => void;
package/dist/react.d.ts CHANGED
@@ -84,6 +84,8 @@ declare const BottomSheet: react.ForwardRefExoticComponent<EngineOptionsForProps
84
84
  noSSR?: boolean;
85
85
  } & react.RefAttributes<BottomSheetHandle<string>>>;
86
86
 
87
+ type TeleportTarget = HTMLElement | string | null | undefined;
88
+
87
89
  type UseBottomSheetRefs = {
88
90
  sheetRef: React.RefObject<HTMLElement | null>;
89
91
  handleRef: React.RefObject<HTMLElement | null>;
@@ -113,6 +115,9 @@ type HookOpts<TId extends string> = Omit<EngineOptions, "element" | "handle" | "
113
115
  snapPoints: SnapPointDef<TId>[] | ReadonlyArray<SnapPointDef<TId>>;
114
116
  allowed?: TId[] | ReadonlyArray<TId>;
115
117
  initial?: TId;
118
+ teleportTo?: TeleportTarget;
119
+ backdropColor?: string;
120
+ backdropOpacity?: number;
116
121
  onSnap?: (id: TId) => void;
117
122
  onBeforeClose?: (payload: SheetEventMap["before-close"]) => void;
118
123
  onOpened?: (id: TId) => void;
package/dist/react.js CHANGED
@@ -3435,6 +3435,38 @@ var BottomSheetEngine = class {
3435
3435
  }
3436
3436
  };
3437
3437
 
3438
+ // src/core/features/teleport.ts
3439
+ var resolveTeleportTarget = (target) => {
3440
+ if (!target) return null;
3441
+ if (typeof target !== "string") return target;
3442
+ if (typeof document === "undefined") return null;
3443
+ if (target === "body") return document.body;
3444
+ return document.querySelector(target);
3445
+ };
3446
+ var teleportElements = (els, target) => {
3447
+ const records = [];
3448
+ for (const el of els) {
3449
+ if (!el || el.parentNode === target) continue;
3450
+ records.push({ el, parent: el.parentNode, next: el.nextSibling });
3451
+ target.appendChild(el);
3452
+ }
3453
+ return () => {
3454
+ for (let i = records.length - 1; i >= 0; i--) {
3455
+ const { el, parent, next } = records[i];
3456
+ if (parent && parent.isConnected) {
3457
+ const before = next && next.parentNode === parent ? next : null;
3458
+ try {
3459
+ parent.insertBefore(el, before);
3460
+ } catch {
3461
+ el.parentNode?.removeChild(el);
3462
+ }
3463
+ } else {
3464
+ el.parentNode?.removeChild(el);
3465
+ }
3466
+ }
3467
+ };
3468
+ };
3469
+
3438
3470
  // src/react/useBottomSheet.ts
3439
3471
  var useIsomorphicLayoutEffect = typeof window !== "undefined" ? useLayoutEffect : useEffect;
3440
3472
  var SSR_STATE = Object.freeze({
@@ -3468,6 +3500,17 @@ function useBottomSheet(opts) {
3468
3500
  scrim: screenRef.current ?? void 0
3469
3501
  });
3470
3502
  engineRef.current = engine;
3503
+ const target = resolveTeleportTarget(optsRef.current.teleportTo);
3504
+ const restoreTeleport = target ? teleportElements(
3505
+ [backdropRef.current, screenRef.current, sheetRef.current],
3506
+ target
3507
+ ) : null;
3508
+ if (optsRef.current.backdropColor !== void 0) {
3509
+ engine.setScrimColor(optsRef.current.backdropColor);
3510
+ }
3511
+ if (optsRef.current.backdropOpacity !== void 0) {
3512
+ engine.setBackdropRange([0, optsRef.current.backdropOpacity]);
3513
+ }
3471
3514
  cachedSnapshotRef.current = { ...engine.state };
3472
3515
  setMounted((n) => n + 1);
3473
3516
  const refresh = () => {
@@ -3499,6 +3542,7 @@ function useBottomSheet(opts) {
3499
3542
  ];
3500
3543
  return () => {
3501
3544
  offs.forEach((off) => off());
3545
+ restoreTeleport?.();
3502
3546
  engine.destroy();
3503
3547
  engineRef.current = null;
3504
3548
  cachedSnapshotRef.current = SSR_STATE;
@@ -3514,6 +3558,18 @@ function useBottomSheet(opts) {
3514
3558
  const ids = opts.allowed ? Array.from(opts.allowed) : opts.snapPoints.map((p) => p.id);
3515
3559
  engineRef.current.setAllowed(ids);
3516
3560
  }, [allowedKey, snapKey]);
3561
+ useEffect(() => {
3562
+ if (!engineRef.current) return;
3563
+ if (opts.backdropColor !== void 0) {
3564
+ engineRef.current.setScrimColor(opts.backdropColor);
3565
+ }
3566
+ }, [opts.backdropColor]);
3567
+ useEffect(() => {
3568
+ if (!engineRef.current) return;
3569
+ if (opts.backdropOpacity !== void 0) {
3570
+ engineRef.current.setBackdropRange([0, opts.backdropOpacity]);
3571
+ }
3572
+ }, [opts.backdropOpacity]);
3517
3573
  const subscribe = useCallback((fn) => {
3518
3574
  subscribersRef.current.add(fn);
3519
3575
  return () => subscribersRef.current.delete(fn);
@@ -3429,6 +3429,38 @@ var BottomSheetEngine = class {
3429
3429
  }
3430
3430
  };
3431
3431
 
3432
+ // src/core/features/teleport.ts
3433
+ var resolveTeleportTarget = (target) => {
3434
+ if (!target) return null;
3435
+ if (typeof target !== "string") return target;
3436
+ if (typeof document === "undefined") return null;
3437
+ if (target === "body") return document.body;
3438
+ return document.querySelector(target);
3439
+ };
3440
+ var teleportElements = (els, target) => {
3441
+ const records = [];
3442
+ for (const el of els) {
3443
+ if (!el || el.parentNode === target) continue;
3444
+ records.push({ el, parent: el.parentNode, next: el.nextSibling });
3445
+ target.appendChild(el);
3446
+ }
3447
+ return () => {
3448
+ for (let i = records.length - 1; i >= 0; i--) {
3449
+ const { el, parent, next } = records[i];
3450
+ if (parent && parent.isConnected) {
3451
+ const before = next && next.parentNode === parent ? next : null;
3452
+ try {
3453
+ parent.insertBefore(el, before);
3454
+ } catch {
3455
+ el.parentNode?.removeChild(el);
3456
+ }
3457
+ } else {
3458
+ el.parentNode?.removeChild(el);
3459
+ }
3460
+ }
3461
+ };
3462
+ };
3463
+
3432
3464
  // src/svelte/useBottomSheet.svelte.ts
3433
3465
  var SSR_STATE = Object.freeze({
3434
3466
  size: 0,
@@ -3442,9 +3474,21 @@ function createBottomSheet(opts) {
3442
3474
  const pending = [];
3443
3475
  const attach = (refs) => {
3444
3476
  if (engine) engine.destroy();
3445
- const { onSnap, ...engineOpts } = opts;
3477
+ const {
3478
+ onSnap,
3479
+ teleportTo,
3480
+ backdropColor,
3481
+ backdropOpacity,
3482
+ ...engineOpts
3483
+ } = opts;
3446
3484
  const created = new BottomSheetEngine({ ...engineOpts, ...refs });
3447
3485
  engine = created;
3486
+ const target = resolveTeleportTarget(teleportTo);
3487
+ const restoreTeleport = target ? teleportElements([refs.backdrop, refs.scrim, refs.element], target) : null;
3488
+ if (backdropColor !== void 0) created.setScrimColor(backdropColor);
3489
+ if (backdropOpacity !== void 0) {
3490
+ created.setBackdropRange([0, backdropOpacity]);
3491
+ }
3448
3492
  if (onSnap) {
3449
3493
  created.on("snap", (payload) => onSnap(payload.id));
3450
3494
  }
@@ -3453,6 +3497,7 @@ function createBottomSheet(opts) {
3453
3497
  }
3454
3498
  pending.length = 0;
3455
3499
  return () => {
3500
+ restoreTeleport?.();
3456
3501
  created.destroy();
3457
3502
  if (engine === created) engine = null;
3458
3503
  };
@@ -3427,6 +3427,38 @@ var BottomSheetEngine = class {
3427
3427
  }
3428
3428
  };
3429
3429
 
3430
+ // src/core/features/teleport.ts
3431
+ var resolveTeleportTarget = (target) => {
3432
+ if (!target) return null;
3433
+ if (typeof target !== "string") return target;
3434
+ if (typeof document === "undefined") return null;
3435
+ if (target === "body") return document.body;
3436
+ return document.querySelector(target);
3437
+ };
3438
+ var teleportElements = (els, target) => {
3439
+ const records = [];
3440
+ for (const el of els) {
3441
+ if (!el || el.parentNode === target) continue;
3442
+ records.push({ el, parent: el.parentNode, next: el.nextSibling });
3443
+ target.appendChild(el);
3444
+ }
3445
+ return () => {
3446
+ for (let i = records.length - 1; i >= 0; i--) {
3447
+ const { el, parent, next } = records[i];
3448
+ if (parent && parent.isConnected) {
3449
+ const before = next && next.parentNode === parent ? next : null;
3450
+ try {
3451
+ parent.insertBefore(el, before);
3452
+ } catch {
3453
+ el.parentNode?.removeChild(el);
3454
+ }
3455
+ } else {
3456
+ el.parentNode?.removeChild(el);
3457
+ }
3458
+ }
3459
+ };
3460
+ };
3461
+
3430
3462
  // src/svelte/useBottomSheet.svelte.ts
3431
3463
  var SSR_STATE = Object.freeze({
3432
3464
  size: 0,
@@ -3440,9 +3472,21 @@ function createBottomSheet(opts) {
3440
3472
  const pending = [];
3441
3473
  const attach = (refs) => {
3442
3474
  if (engine) engine.destroy();
3443
- const { onSnap, ...engineOpts } = opts;
3475
+ const {
3476
+ onSnap,
3477
+ teleportTo,
3478
+ backdropColor,
3479
+ backdropOpacity,
3480
+ ...engineOpts
3481
+ } = opts;
3444
3482
  const created = new BottomSheetEngine({ ...engineOpts, ...refs });
3445
3483
  engine = created;
3484
+ const target = resolveTeleportTarget(teleportTo);
3485
+ const restoreTeleport = target ? teleportElements([refs.backdrop, refs.scrim, refs.element], target) : null;
3486
+ if (backdropColor !== void 0) created.setScrimColor(backdropColor);
3487
+ if (backdropOpacity !== void 0) {
3488
+ created.setBackdropRange([0, backdropOpacity]);
3489
+ }
3446
3490
  if (onSnap) {
3447
3491
  created.on("snap", (payload) => onSnap(payload.id));
3448
3492
  }
@@ -3451,6 +3495,7 @@ function createBottomSheet(opts) {
3451
3495
  }
3452
3496
  pending.length = 0;
3453
3497
  return () => {
3498
+ restoreTeleport?.();
3454
3499
  created.destroy();
3455
3500
  if (engine === created) engine = null;
3456
3501
  };
package/dist/svelte.cjs CHANGED
@@ -3451,6 +3451,38 @@ var BottomSheetEngine = class {
3451
3451
  }
3452
3452
  };
3453
3453
 
3454
+ // src/core/features/teleport.ts
3455
+ var resolveTeleportTarget = (target) => {
3456
+ if (!target) return null;
3457
+ if (typeof target !== "string") return target;
3458
+ if (typeof document === "undefined") return null;
3459
+ if (target === "body") return document.body;
3460
+ return document.querySelector(target);
3461
+ };
3462
+ var teleportElements = (els, target) => {
3463
+ const records = [];
3464
+ for (const el of els) {
3465
+ if (!el || el.parentNode === target) continue;
3466
+ records.push({ el, parent: el.parentNode, next: el.nextSibling });
3467
+ target.appendChild(el);
3468
+ }
3469
+ return () => {
3470
+ for (let i = records.length - 1; i >= 0; i--) {
3471
+ const { el, parent, next } = records[i];
3472
+ if (parent && parent.isConnected) {
3473
+ const before = next && next.parentNode === parent ? next : null;
3474
+ try {
3475
+ parent.insertBefore(el, before);
3476
+ } catch {
3477
+ el.parentNode?.removeChild(el);
3478
+ }
3479
+ } else {
3480
+ el.parentNode?.removeChild(el);
3481
+ }
3482
+ }
3483
+ };
3484
+ };
3485
+
3454
3486
  // src/svelte/useBottomSheet.svelte.ts
3455
3487
  var SSR_STATE = Object.freeze({
3456
3488
  size: 0,
@@ -3464,9 +3496,21 @@ function createBottomSheet(opts) {
3464
3496
  const pending = [];
3465
3497
  const attach = (refs) => {
3466
3498
  if (engine) engine.destroy();
3467
- const { onSnap, ...engineOpts } = opts;
3499
+ const {
3500
+ onSnap,
3501
+ teleportTo,
3502
+ backdropColor,
3503
+ backdropOpacity,
3504
+ ...engineOpts
3505
+ } = opts;
3468
3506
  const created = new BottomSheetEngine({ ...engineOpts, ...refs });
3469
3507
  engine = created;
3508
+ const target = resolveTeleportTarget(teleportTo);
3509
+ const restoreTeleport = target ? teleportElements([refs.backdrop, refs.scrim, refs.element], target) : null;
3510
+ if (backdropColor !== void 0) created.setScrimColor(backdropColor);
3511
+ if (backdropOpacity !== void 0) {
3512
+ created.setBackdropRange([0, backdropOpacity]);
3513
+ }
3470
3514
  if (onSnap) {
3471
3515
  created.on("snap", (payload) => onSnap(payload.id));
3472
3516
  }
@@ -3475,6 +3519,7 @@ function createBottomSheet(opts) {
3475
3519
  }
3476
3520
  pending.length = 0;
3477
3521
  return () => {
3522
+ restoreTeleport?.();
3478
3523
  created.destroy();
3479
3524
  if (engine === created) engine = null;
3480
3525
  };
package/dist/svelte.js CHANGED
@@ -3429,6 +3429,38 @@ var BottomSheetEngine = class {
3429
3429
  }
3430
3430
  };
3431
3431
 
3432
+ // src/core/features/teleport.ts
3433
+ var resolveTeleportTarget = (target) => {
3434
+ if (!target) return null;
3435
+ if (typeof target !== "string") return target;
3436
+ if (typeof document === "undefined") return null;
3437
+ if (target === "body") return document.body;
3438
+ return document.querySelector(target);
3439
+ };
3440
+ var teleportElements = (els, target) => {
3441
+ const records = [];
3442
+ for (const el of els) {
3443
+ if (!el || el.parentNode === target) continue;
3444
+ records.push({ el, parent: el.parentNode, next: el.nextSibling });
3445
+ target.appendChild(el);
3446
+ }
3447
+ return () => {
3448
+ for (let i = records.length - 1; i >= 0; i--) {
3449
+ const { el, parent, next } = records[i];
3450
+ if (parent && parent.isConnected) {
3451
+ const before = next && next.parentNode === parent ? next : null;
3452
+ try {
3453
+ parent.insertBefore(el, before);
3454
+ } catch {
3455
+ el.parentNode?.removeChild(el);
3456
+ }
3457
+ } else {
3458
+ el.parentNode?.removeChild(el);
3459
+ }
3460
+ }
3461
+ };
3462
+ };
3463
+
3432
3464
  // src/svelte/useBottomSheet.svelte.ts
3433
3465
  var SSR_STATE = Object.freeze({
3434
3466
  size: 0,
@@ -3442,9 +3474,21 @@ function createBottomSheet(opts) {
3442
3474
  const pending = [];
3443
3475
  const attach = (refs) => {
3444
3476
  if (engine) engine.destroy();
3445
- const { onSnap, ...engineOpts } = opts;
3477
+ const {
3478
+ onSnap,
3479
+ teleportTo,
3480
+ backdropColor,
3481
+ backdropOpacity,
3482
+ ...engineOpts
3483
+ } = opts;
3446
3484
  const created = new BottomSheetEngine({ ...engineOpts, ...refs });
3447
3485
  engine = created;
3486
+ const target = resolveTeleportTarget(teleportTo);
3487
+ const restoreTeleport = target ? teleportElements([refs.backdrop, refs.scrim, refs.element], target) : null;
3488
+ if (backdropColor !== void 0) created.setScrimColor(backdropColor);
3489
+ if (backdropOpacity !== void 0) {
3490
+ created.setBackdropRange([0, backdropOpacity]);
3491
+ }
3448
3492
  if (onSnap) {
3449
3493
  created.on("snap", (payload) => onSnap(payload.id));
3450
3494
  }
@@ -3453,6 +3497,7 @@ function createBottomSheet(opts) {
3453
3497
  }
3454
3498
  pending.length = 0;
3455
3499
  return () => {
3500
+ restoreTeleport?.();
3456
3501
  created.destroy();
3457
3502
  if (engine === created) engine = null;
3458
3503
  };
package/dist/vue.cjs CHANGED
@@ -3429,6 +3429,38 @@ var BottomSheetEngine = class {
3429
3429
  }
3430
3430
  };
3431
3431
 
3432
+ // src/core/features/teleport.ts
3433
+ var resolveTeleportTarget = (target) => {
3434
+ if (!target) return null;
3435
+ if (typeof target !== "string") return target;
3436
+ if (typeof document === "undefined") return null;
3437
+ if (target === "body") return document.body;
3438
+ return document.querySelector(target);
3439
+ };
3440
+ var teleportElements = (els, target) => {
3441
+ const records = [];
3442
+ for (const el of els) {
3443
+ if (!el || el.parentNode === target) continue;
3444
+ records.push({ el, parent: el.parentNode, next: el.nextSibling });
3445
+ target.appendChild(el);
3446
+ }
3447
+ return () => {
3448
+ for (let i = records.length - 1; i >= 0; i--) {
3449
+ const { el, parent, next } = records[i];
3450
+ if (parent && parent.isConnected) {
3451
+ const before = next && next.parentNode === parent ? next : null;
3452
+ try {
3453
+ parent.insertBefore(el, before);
3454
+ } catch {
3455
+ el.parentNode?.removeChild(el);
3456
+ }
3457
+ } else {
3458
+ el.parentNode?.removeChild(el);
3459
+ }
3460
+ }
3461
+ };
3462
+ };
3463
+
3432
3464
  // src/vue/useBottomSheet.ts
3433
3465
  function useBottomSheet(opts) {
3434
3466
  const sheetRef = vue.ref(null);
@@ -3445,13 +3477,20 @@ function useBottomSheet(opts) {
3445
3477
  isAnimating: false,
3446
3478
  progress: 0
3447
3479
  });
3480
+ let restoreTeleport = null;
3448
3481
  const sync = () => {
3449
3482
  if (!engine) return;
3450
3483
  Object.assign(state, engine.state);
3451
3484
  };
3452
3485
  vue.onMounted(() => {
3453
3486
  if (!sheetRef.value) return;
3454
- const { onSnap, ...engineOpts } = opts;
3487
+ const {
3488
+ onSnap,
3489
+ teleportTo,
3490
+ backdropColor,
3491
+ backdropOpacity,
3492
+ ...engineOpts
3493
+ } = opts;
3455
3494
  engine = new BottomSheetEngine({
3456
3495
  ...engineOpts,
3457
3496
  element: sheetRef.value,
@@ -3461,6 +3500,17 @@ function useBottomSheet(opts) {
3461
3500
  scrim: screenRef.value ?? void 0
3462
3501
  });
3463
3502
  sync();
3503
+ const target = resolveTeleportTarget(teleportTo);
3504
+ if (target) {
3505
+ restoreTeleport = teleportElements(
3506
+ [backdropRef.value, screenRef.value, sheetRef.value],
3507
+ target
3508
+ );
3509
+ }
3510
+ if (backdropColor !== void 0) engine.setScrimColor(backdropColor);
3511
+ if (backdropOpacity !== void 0) {
3512
+ engine.setBackdropRange([0, backdropOpacity]);
3513
+ }
3464
3514
  engine.on("snap", (payload) => {
3465
3515
  sync();
3466
3516
  onSnap?.(payload.id);
@@ -3476,6 +3526,8 @@ function useBottomSheet(opts) {
3476
3526
  pending.length = 0;
3477
3527
  });
3478
3528
  vue.onBeforeUnmount(() => {
3529
+ restoreTeleport?.();
3530
+ restoreTeleport = null;
3479
3531
  engine?.destroy();
3480
3532
  engine = null;
3481
3533
  });
@@ -3704,6 +3756,23 @@ var _sfc_main = /* @__PURE__ */ vue.defineComponent({
3704
3756
  type: null,
3705
3757
  required: false
3706
3758
  },
3759
+ teleportTo: {
3760
+ type: [
3761
+ String,
3762
+ null,
3763
+ Object
3764
+ ],
3765
+ required: false,
3766
+ default: "body"
3767
+ },
3768
+ backdropColor: {
3769
+ type: String,
3770
+ required: false
3771
+ },
3772
+ backdropOpacity: {
3773
+ type: Number,
3774
+ required: false
3775
+ },
3707
3776
  onSnap: {
3708
3777
  type: Function,
3709
3778
  required: false
@@ -3736,11 +3805,6 @@ var _sfc_main = /* @__PURE__ */ vue.defineComponent({
3736
3805
  required: false,
3737
3806
  default: true
3738
3807
  },
3739
- teleportTo: {
3740
- type: null,
3741
- required: false,
3742
- default: "body"
3743
- },
3744
3808
  anchors: {
3745
3809
  type: Array,
3746
3810
  required: false
@@ -3748,14 +3812,6 @@ var _sfc_main = /* @__PURE__ */ vue.defineComponent({
3748
3812
  scrimStages: {
3749
3813
  type: [Object, null],
3750
3814
  required: false
3751
- },
3752
- backdropColor: {
3753
- type: String,
3754
- required: false
3755
- },
3756
- backdropOpacity: {
3757
- type: Number,
3758
- required: false
3759
3815
  }
3760
3816
  },
3761
3817
  emits: [
package/dist/vue.js CHANGED
@@ -3427,6 +3427,38 @@ var BottomSheetEngine = class {
3427
3427
  }
3428
3428
  };
3429
3429
 
3430
+ // src/core/features/teleport.ts
3431
+ var resolveTeleportTarget = (target) => {
3432
+ if (!target) return null;
3433
+ if (typeof target !== "string") return target;
3434
+ if (typeof document === "undefined") return null;
3435
+ if (target === "body") return document.body;
3436
+ return document.querySelector(target);
3437
+ };
3438
+ var teleportElements = (els, target) => {
3439
+ const records = [];
3440
+ for (const el of els) {
3441
+ if (!el || el.parentNode === target) continue;
3442
+ records.push({ el, parent: el.parentNode, next: el.nextSibling });
3443
+ target.appendChild(el);
3444
+ }
3445
+ return () => {
3446
+ for (let i = records.length - 1; i >= 0; i--) {
3447
+ const { el, parent, next } = records[i];
3448
+ if (parent && parent.isConnected) {
3449
+ const before = next && next.parentNode === parent ? next : null;
3450
+ try {
3451
+ parent.insertBefore(el, before);
3452
+ } catch {
3453
+ el.parentNode?.removeChild(el);
3454
+ }
3455
+ } else {
3456
+ el.parentNode?.removeChild(el);
3457
+ }
3458
+ }
3459
+ };
3460
+ };
3461
+
3430
3462
  // src/vue/useBottomSheet.ts
3431
3463
  function useBottomSheet(opts) {
3432
3464
  const sheetRef = ref(null);
@@ -3443,13 +3475,20 @@ function useBottomSheet(opts) {
3443
3475
  isAnimating: false,
3444
3476
  progress: 0
3445
3477
  });
3478
+ let restoreTeleport = null;
3446
3479
  const sync = () => {
3447
3480
  if (!engine) return;
3448
3481
  Object.assign(state, engine.state);
3449
3482
  };
3450
3483
  onMounted(() => {
3451
3484
  if (!sheetRef.value) return;
3452
- const { onSnap, ...engineOpts } = opts;
3485
+ const {
3486
+ onSnap,
3487
+ teleportTo,
3488
+ backdropColor,
3489
+ backdropOpacity,
3490
+ ...engineOpts
3491
+ } = opts;
3453
3492
  engine = new BottomSheetEngine({
3454
3493
  ...engineOpts,
3455
3494
  element: sheetRef.value,
@@ -3459,6 +3498,17 @@ function useBottomSheet(opts) {
3459
3498
  scrim: screenRef.value ?? void 0
3460
3499
  });
3461
3500
  sync();
3501
+ const target = resolveTeleportTarget(teleportTo);
3502
+ if (target) {
3503
+ restoreTeleport = teleportElements(
3504
+ [backdropRef.value, screenRef.value, sheetRef.value],
3505
+ target
3506
+ );
3507
+ }
3508
+ if (backdropColor !== void 0) engine.setScrimColor(backdropColor);
3509
+ if (backdropOpacity !== void 0) {
3510
+ engine.setBackdropRange([0, backdropOpacity]);
3511
+ }
3462
3512
  engine.on("snap", (payload) => {
3463
3513
  sync();
3464
3514
  onSnap?.(payload.id);
@@ -3474,6 +3524,8 @@ function useBottomSheet(opts) {
3474
3524
  pending.length = 0;
3475
3525
  });
3476
3526
  onBeforeUnmount(() => {
3527
+ restoreTeleport?.();
3528
+ restoreTeleport = null;
3477
3529
  engine?.destroy();
3478
3530
  engine = null;
3479
3531
  });
@@ -3702,6 +3754,23 @@ var _sfc_main = /* @__PURE__ */ defineComponent({
3702
3754
  type: null,
3703
3755
  required: false
3704
3756
  },
3757
+ teleportTo: {
3758
+ type: [
3759
+ String,
3760
+ null,
3761
+ Object
3762
+ ],
3763
+ required: false,
3764
+ default: "body"
3765
+ },
3766
+ backdropColor: {
3767
+ type: String,
3768
+ required: false
3769
+ },
3770
+ backdropOpacity: {
3771
+ type: Number,
3772
+ required: false
3773
+ },
3705
3774
  onSnap: {
3706
3775
  type: Function,
3707
3776
  required: false
@@ -3734,11 +3803,6 @@ var _sfc_main = /* @__PURE__ */ defineComponent({
3734
3803
  required: false,
3735
3804
  default: true
3736
3805
  },
3737
- teleportTo: {
3738
- type: null,
3739
- required: false,
3740
- default: "body"
3741
- },
3742
3806
  anchors: {
3743
3807
  type: Array,
3744
3808
  required: false
@@ -3746,14 +3810,6 @@ var _sfc_main = /* @__PURE__ */ defineComponent({
3746
3810
  scrimStages: {
3747
3811
  type: [Object, null],
3748
3812
  required: false
3749
- },
3750
- backdropColor: {
3751
- type: String,
3752
- required: false
3753
- },
3754
- backdropOpacity: {
3755
- type: Number,
3756
- required: false
3757
3813
  }
3758
3814
  },
3759
3815
  emits: [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@surdeddd/bottom-sheet",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "Universal, headless bottom sheet — framework-agnostic core with React, Vue 3, Svelte, Solid, Qwik, Preact, Lit and Custom Element adapters. Pointer Events, snap points, momentum, a11y, SSR-safe.",
5
5
  "type": "module",
6
6
  "license": "MIT",