@surdeddd/bottom-sheet 0.4.1 → 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/{BottomSheetEngine-L05jGZvU.d.ts → BottomSheetEngine-BHjKFtnM.d.ts} +2 -0
- package/dist/{BottomSheetEngine-BJrH7qY3.d.cts → BottomSheetEngine-CqiCz64W.d.cts} +2 -0
- package/dist/element.cjs +111 -12
- package/dist/element.d.cts +1 -1
- package/dist/element.d.ts +1 -1
- package/dist/element.iife.global.js +2 -2
- package/dist/element.js +111 -12
- package/dist/index.cjs +91 -8
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +91 -8
- package/dist/integrations/formik.d.cts +1 -1
- package/dist/integrations/formik.d.ts +1 -1
- package/dist/integrations/react-hook-form.d.cts +1 -1
- package/dist/integrations/react-hook-form.d.ts +1 -1
- package/dist/preact.d.cts +1 -1
- package/dist/preact.d.ts +1 -1
- package/dist/qwik.cjs +94 -10
- package/dist/qwik.d.cts +2 -2
- package/dist/qwik.d.ts +2 -2
- package/dist/qwik.js +94 -10
- package/dist/react.cjs +151 -10
- package/dist/react.d.cts +9 -2
- package/dist/react.d.ts +9 -2
- package/dist/react.js +151 -10
- package/dist/solid.cjs +122 -18
- package/dist/solid.d.cts +3 -0
- package/dist/solid.d.ts +3 -0
- package/dist/solid.js +124 -20
- package/dist/solid.source.jsx +100 -12
- package/dist/styles.css +17 -0
- package/dist/svelte-core.cjs +137 -9
- package/dist/svelte-core.js +137 -9
- package/dist/svelte-src/BottomSheet.svelte +5 -3
- package/dist/svelte.cjs +189 -46
- package/dist/svelte.d.cts +1 -0
- package/dist/svelte.d.ts +1 -0
- package/dist/svelte.js +189 -46
- package/dist/vue.cjs +176 -32
- package/dist/vue.js +176 -32
- package/package.json +1 -1
package/dist/vue.cjs
CHANGED
|
@@ -2897,11 +2897,54 @@ var BottomSheetEngine = class {
|
|
|
2897
2897
|
this.updateAriaSlider();
|
|
2898
2898
|
}
|
|
2899
2899
|
}
|
|
2900
|
+
contentTargets() {
|
|
2901
|
+
const scroller = this.scrollContainer;
|
|
2902
|
+
if (!scroller) return [];
|
|
2903
|
+
const hasSlot = typeof HTMLSlotElement !== "undefined";
|
|
2904
|
+
const out = [];
|
|
2905
|
+
for (const child of Array.from(scroller.children)) {
|
|
2906
|
+
if (hasSlot && child instanceof HTMLSlotElement) {
|
|
2907
|
+
for (const el of child.assignedElements()) out.push(el);
|
|
2908
|
+
} else {
|
|
2909
|
+
out.push(child);
|
|
2910
|
+
}
|
|
2911
|
+
}
|
|
2912
|
+
return out;
|
|
2913
|
+
}
|
|
2914
|
+
measureContentExtent(vertical) {
|
|
2915
|
+
const content = this.scrollContainer;
|
|
2916
|
+
if (!content) return 0;
|
|
2917
|
+
const targets = this.contentTargets();
|
|
2918
|
+
if (targets.length === 0) {
|
|
2919
|
+
return vertical ? content.scrollHeight : content.scrollWidth;
|
|
2920
|
+
}
|
|
2921
|
+
let min = Infinity;
|
|
2922
|
+
let max = -Infinity;
|
|
2923
|
+
for (const el of targets) {
|
|
2924
|
+
const r = el.getBoundingClientRect();
|
|
2925
|
+
if (vertical) {
|
|
2926
|
+
if (r.top < min) min = r.top;
|
|
2927
|
+
if (r.bottom > max) max = r.bottom;
|
|
2928
|
+
} else {
|
|
2929
|
+
if (r.left < min) min = r.left;
|
|
2930
|
+
if (r.right > max) max = r.right;
|
|
2931
|
+
}
|
|
2932
|
+
}
|
|
2933
|
+
if (!isFinite(min) || !isFinite(max) || max <= min) {
|
|
2934
|
+
return vertical ? content.scrollHeight : content.scrollWidth;
|
|
2935
|
+
}
|
|
2936
|
+
let pad = 0;
|
|
2937
|
+
if (typeof getComputedStyle !== "undefined") {
|
|
2938
|
+
const cs = getComputedStyle(content);
|
|
2939
|
+
pad = vertical ? (parseFloat(cs.paddingTop) || 0) + (parseFloat(cs.paddingBottom) || 0) : (parseFloat(cs.paddingLeft) || 0) + (parseFloat(cs.paddingRight) || 0);
|
|
2940
|
+
}
|
|
2941
|
+
return max - min + pad;
|
|
2942
|
+
}
|
|
2900
2943
|
measureFitSize() {
|
|
2901
2944
|
const vertical = layoutAxis(this.mode) === "height";
|
|
2902
2945
|
const handleSize = vertical ? this.handle.offsetHeight : this.handle.offsetWidth;
|
|
2903
2946
|
const content = this.scrollContainer;
|
|
2904
|
-
const natural = content ? handleSize + (vertical
|
|
2947
|
+
const natural = content ? handleSize + this.measureContentExtent(vertical) : handleSize;
|
|
2905
2948
|
if (typeof window === "undefined") return natural;
|
|
2906
2949
|
const viewport = vertical ? window.innerHeight : window.innerWidth;
|
|
2907
2950
|
return viewport > 0 ? Math.min(natural, viewport) : natural;
|
|
@@ -2910,22 +2953,62 @@ var BottomSheetEngine = class {
|
|
|
2910
2953
|
if (typeof ResizeObserver === "undefined") return;
|
|
2911
2954
|
if (!this.snapPointsRaw.some((p) => p.size === "fit" || p.size === "content"))
|
|
2912
2955
|
return;
|
|
2913
|
-
const targets = [this.handle];
|
|
2914
|
-
if (this.scrollContainer && this.scrollContainer !== this.handle) {
|
|
2915
|
-
targets.push(this.scrollContainer);
|
|
2916
|
-
}
|
|
2917
2956
|
let raf = 0;
|
|
2918
|
-
const
|
|
2957
|
+
const schedule = () => {
|
|
2919
2958
|
if (raf) return;
|
|
2920
2959
|
raf = requestAnimationFrame(() => {
|
|
2921
2960
|
raf = 0;
|
|
2922
2961
|
if (this.destroyed || this.gesture?.isDragging) return;
|
|
2923
2962
|
this.recompute();
|
|
2924
2963
|
});
|
|
2925
|
-
}
|
|
2926
|
-
|
|
2964
|
+
};
|
|
2965
|
+
const ro = new ResizeObserver(schedule);
|
|
2966
|
+
ro.observe(this.handle);
|
|
2967
|
+
const scroller = this.scrollContainer;
|
|
2968
|
+
const observed = /* @__PURE__ */ new Set();
|
|
2969
|
+
const slots = /* @__PURE__ */ new Set();
|
|
2970
|
+
const hasSlot = typeof HTMLSlotElement !== "undefined";
|
|
2971
|
+
const onSlotChange = () => resync();
|
|
2972
|
+
const trackSlots = () => {
|
|
2973
|
+
if (!scroller || !hasSlot) return;
|
|
2974
|
+
for (const child of Array.from(scroller.children)) {
|
|
2975
|
+
if (child instanceof HTMLSlotElement && !slots.has(child)) {
|
|
2976
|
+
child.addEventListener("slotchange", onSlotChange);
|
|
2977
|
+
slots.add(child);
|
|
2978
|
+
}
|
|
2979
|
+
}
|
|
2980
|
+
};
|
|
2981
|
+
const resync = () => {
|
|
2982
|
+
trackSlots();
|
|
2983
|
+
const targets = this.contentTargets();
|
|
2984
|
+
for (const el of observed) {
|
|
2985
|
+
if (!targets.includes(el)) {
|
|
2986
|
+
ro.unobserve(el);
|
|
2987
|
+
observed.delete(el);
|
|
2988
|
+
}
|
|
2989
|
+
}
|
|
2990
|
+
for (const el of targets) {
|
|
2991
|
+
if (!observed.has(el)) {
|
|
2992
|
+
ro.observe(el);
|
|
2993
|
+
observed.add(el);
|
|
2994
|
+
}
|
|
2995
|
+
}
|
|
2996
|
+
schedule();
|
|
2997
|
+
};
|
|
2998
|
+
let mo;
|
|
2999
|
+
if (scroller) {
|
|
3000
|
+
resync();
|
|
3001
|
+
if (typeof MutationObserver !== "undefined") {
|
|
3002
|
+
mo = new MutationObserver(resync);
|
|
3003
|
+
mo.observe(scroller, { childList: true });
|
|
3004
|
+
}
|
|
3005
|
+
}
|
|
2927
3006
|
this.teardowns.add(() => {
|
|
2928
3007
|
ro.disconnect();
|
|
3008
|
+
mo?.disconnect();
|
|
3009
|
+
for (const slot of slots) {
|
|
3010
|
+
slot.removeEventListener("slotchange", onSlotChange);
|
|
3011
|
+
}
|
|
2929
3012
|
if (raf) cancelAnimationFrame(raf);
|
|
2930
3013
|
});
|
|
2931
3014
|
}
|
|
@@ -3346,6 +3429,38 @@ var BottomSheetEngine = class {
|
|
|
3346
3429
|
}
|
|
3347
3430
|
};
|
|
3348
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
|
+
|
|
3349
3464
|
// src/vue/useBottomSheet.ts
|
|
3350
3465
|
function useBottomSheet(opts) {
|
|
3351
3466
|
const sheetRef = vue.ref(null);
|
|
@@ -3362,13 +3477,20 @@ function useBottomSheet(opts) {
|
|
|
3362
3477
|
isAnimating: false,
|
|
3363
3478
|
progress: 0
|
|
3364
3479
|
});
|
|
3480
|
+
let restoreTeleport = null;
|
|
3365
3481
|
const sync = () => {
|
|
3366
3482
|
if (!engine) return;
|
|
3367
3483
|
Object.assign(state, engine.state);
|
|
3368
3484
|
};
|
|
3369
3485
|
vue.onMounted(() => {
|
|
3370
3486
|
if (!sheetRef.value) return;
|
|
3371
|
-
const {
|
|
3487
|
+
const {
|
|
3488
|
+
onSnap,
|
|
3489
|
+
teleportTo,
|
|
3490
|
+
backdropColor,
|
|
3491
|
+
backdropOpacity,
|
|
3492
|
+
...engineOpts
|
|
3493
|
+
} = opts;
|
|
3372
3494
|
engine = new BottomSheetEngine({
|
|
3373
3495
|
...engineOpts,
|
|
3374
3496
|
element: sheetRef.value,
|
|
@@ -3378,6 +3500,17 @@ function useBottomSheet(opts) {
|
|
|
3378
3500
|
scrim: screenRef.value ?? void 0
|
|
3379
3501
|
});
|
|
3380
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
|
+
}
|
|
3381
3514
|
engine.on("snap", (payload) => {
|
|
3382
3515
|
sync();
|
|
3383
3516
|
onSnap?.(payload.id);
|
|
@@ -3393,6 +3526,8 @@ function useBottomSheet(opts) {
|
|
|
3393
3526
|
pending.length = 0;
|
|
3394
3527
|
});
|
|
3395
3528
|
vue.onBeforeUnmount(() => {
|
|
3529
|
+
restoreTeleport?.();
|
|
3530
|
+
restoreTeleport = null;
|
|
3396
3531
|
engine?.destroy();
|
|
3397
3532
|
engine = null;
|
|
3398
3533
|
});
|
|
@@ -3621,6 +3756,23 @@ var _sfc_main = /* @__PURE__ */ vue.defineComponent({
|
|
|
3621
3756
|
type: null,
|
|
3622
3757
|
required: false
|
|
3623
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
|
+
},
|
|
3624
3776
|
onSnap: {
|
|
3625
3777
|
type: Function,
|
|
3626
3778
|
required: false
|
|
@@ -3653,11 +3805,6 @@ var _sfc_main = /* @__PURE__ */ vue.defineComponent({
|
|
|
3653
3805
|
required: false,
|
|
3654
3806
|
default: true
|
|
3655
3807
|
},
|
|
3656
|
-
teleportTo: {
|
|
3657
|
-
type: null,
|
|
3658
|
-
required: false,
|
|
3659
|
-
default: "body"
|
|
3660
|
-
},
|
|
3661
3808
|
anchors: {
|
|
3662
3809
|
type: Array,
|
|
3663
3810
|
required: false
|
|
@@ -3665,14 +3812,6 @@ var _sfc_main = /* @__PURE__ */ vue.defineComponent({
|
|
|
3665
3812
|
scrimStages: {
|
|
3666
3813
|
type: [Object, null],
|
|
3667
3814
|
required: false
|
|
3668
|
-
},
|
|
3669
|
-
backdropColor: {
|
|
3670
|
-
type: String,
|
|
3671
|
-
required: false
|
|
3672
|
-
},
|
|
3673
|
-
backdropOpacity: {
|
|
3674
|
-
type: Number,
|
|
3675
|
-
required: false
|
|
3676
3815
|
}
|
|
3677
3816
|
},
|
|
3678
3817
|
emits: [
|
|
@@ -3900,23 +4039,27 @@ var _hoisted_4 = [
|
|
|
3900
4039
|
"aria-valuetext"
|
|
3901
4040
|
];
|
|
3902
4041
|
var _hoisted_5 = {
|
|
4042
|
+
key: 0,
|
|
4043
|
+
class: "bs-header"
|
|
4044
|
+
};
|
|
4045
|
+
var _hoisted_6 = {
|
|
3903
4046
|
ref: "contentRef",
|
|
3904
4047
|
class: "bs-content",
|
|
3905
4048
|
tabindex: "0",
|
|
3906
4049
|
role: "region",
|
|
3907
4050
|
"aria-label": "Sheet content"
|
|
3908
4051
|
};
|
|
3909
|
-
var
|
|
3910
|
-
key:
|
|
4052
|
+
var _hoisted_7 = {
|
|
4053
|
+
key: 1,
|
|
3911
4054
|
class: "bs-footer"
|
|
3912
4055
|
};
|
|
3913
|
-
var
|
|
4056
|
+
var _hoisted_8 = {
|
|
3914
4057
|
class: "bs-sr-only",
|
|
3915
4058
|
role: "status",
|
|
3916
4059
|
"aria-live": "polite"
|
|
3917
4060
|
};
|
|
3918
|
-
var _hoisted_8 = ["data-mode"];
|
|
3919
4061
|
var _hoisted_9 = ["data-mode"];
|
|
4062
|
+
var _hoisted_10 = ["data-mode"];
|
|
3920
4063
|
function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
|
|
3921
4064
|
return vue.openBlock(), vue.createBlock(vue.Teleport, {
|
|
3922
4065
|
to: $props.teleportTo,
|
|
@@ -3962,18 +4105,19 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
3962
4105
|
"aria-valuenow": $setup.activeIdx,
|
|
3963
4106
|
"aria-valuetext": $setup.state.activeId,
|
|
3964
4107
|
"aria-label": "Resize sheet"
|
|
3965
|
-
},
|
|
4108
|
+
}, null, 8, _hoisted_4),
|
|
4109
|
+
_ctx.$slots.header ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_5, [vue.renderSlot(_ctx.$slots, "header", { state: $setup.state })])) : vue.createCommentVNode("v-if", true),
|
|
3966
4110
|
vue.createElementVNode(
|
|
3967
4111
|
"div",
|
|
3968
|
-
|
|
4112
|
+
_hoisted_6,
|
|
3969
4113
|
[vue.renderSlot(_ctx.$slots, "default")],
|
|
3970
4114
|
512
|
|
3971
4115
|
/* NEED_PATCH */
|
|
3972
4116
|
),
|
|
3973
|
-
_ctx.$slots.footer ? (vue.openBlock(), vue.createElementBlock("div",
|
|
4117
|
+
_ctx.$slots.footer ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_7, [vue.renderSlot(_ctx.$slots, "footer", { state: $setup.state })])) : vue.createCommentVNode("v-if", true),
|
|
3974
4118
|
vue.createElementVNode(
|
|
3975
4119
|
"span",
|
|
3976
|
-
|
|
4120
|
+
_hoisted_8,
|
|
3977
4121
|
vue.toDisplayString($setup.state.activeId),
|
|
3978
4122
|
1
|
|
3979
4123
|
/* TEXT */
|
|
@@ -3984,13 +4128,13 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
3984
4128
|
class: "bs-button-slot",
|
|
3985
4129
|
"data-side": "left",
|
|
3986
4130
|
"data-mode": $setup.props.mode ?? "bottom"
|
|
3987
|
-
}, [vue.renderSlot(_ctx.$slots, "button-left")], 8,
|
|
4131
|
+
}, [vue.renderSlot(_ctx.$slots, "button-left")], 8, _hoisted_9)) : vue.createCommentVNode("v-if", true),
|
|
3988
4132
|
_ctx.$slots["button-right"] ? (vue.openBlock(), vue.createElementBlock("div", {
|
|
3989
4133
|
key: 2,
|
|
3990
4134
|
class: "bs-button-slot",
|
|
3991
4135
|
"data-side": "right",
|
|
3992
4136
|
"data-mode": $setup.props.mode ?? "bottom"
|
|
3993
|
-
}, [vue.renderSlot(_ctx.$slots, "button-right")], 8,
|
|
4137
|
+
}, [vue.renderSlot(_ctx.$slots, "button-right")], 8, _hoisted_10)) : vue.createCommentVNode("v-if", true)
|
|
3994
4138
|
]), (vue.openBlock(true), vue.createElementBlock(
|
|
3995
4139
|
vue.Fragment,
|
|
3996
4140
|
null,
|
package/dist/vue.js
CHANGED
|
@@ -2895,11 +2895,54 @@ var BottomSheetEngine = class {
|
|
|
2895
2895
|
this.updateAriaSlider();
|
|
2896
2896
|
}
|
|
2897
2897
|
}
|
|
2898
|
+
contentTargets() {
|
|
2899
|
+
const scroller = this.scrollContainer;
|
|
2900
|
+
if (!scroller) return [];
|
|
2901
|
+
const hasSlot = typeof HTMLSlotElement !== "undefined";
|
|
2902
|
+
const out = [];
|
|
2903
|
+
for (const child of Array.from(scroller.children)) {
|
|
2904
|
+
if (hasSlot && child instanceof HTMLSlotElement) {
|
|
2905
|
+
for (const el of child.assignedElements()) out.push(el);
|
|
2906
|
+
} else {
|
|
2907
|
+
out.push(child);
|
|
2908
|
+
}
|
|
2909
|
+
}
|
|
2910
|
+
return out;
|
|
2911
|
+
}
|
|
2912
|
+
measureContentExtent(vertical) {
|
|
2913
|
+
const content = this.scrollContainer;
|
|
2914
|
+
if (!content) return 0;
|
|
2915
|
+
const targets = this.contentTargets();
|
|
2916
|
+
if (targets.length === 0) {
|
|
2917
|
+
return vertical ? content.scrollHeight : content.scrollWidth;
|
|
2918
|
+
}
|
|
2919
|
+
let min = Infinity;
|
|
2920
|
+
let max = -Infinity;
|
|
2921
|
+
for (const el of targets) {
|
|
2922
|
+
const r = el.getBoundingClientRect();
|
|
2923
|
+
if (vertical) {
|
|
2924
|
+
if (r.top < min) min = r.top;
|
|
2925
|
+
if (r.bottom > max) max = r.bottom;
|
|
2926
|
+
} else {
|
|
2927
|
+
if (r.left < min) min = r.left;
|
|
2928
|
+
if (r.right > max) max = r.right;
|
|
2929
|
+
}
|
|
2930
|
+
}
|
|
2931
|
+
if (!isFinite(min) || !isFinite(max) || max <= min) {
|
|
2932
|
+
return vertical ? content.scrollHeight : content.scrollWidth;
|
|
2933
|
+
}
|
|
2934
|
+
let pad = 0;
|
|
2935
|
+
if (typeof getComputedStyle !== "undefined") {
|
|
2936
|
+
const cs = getComputedStyle(content);
|
|
2937
|
+
pad = vertical ? (parseFloat(cs.paddingTop) || 0) + (parseFloat(cs.paddingBottom) || 0) : (parseFloat(cs.paddingLeft) || 0) + (parseFloat(cs.paddingRight) || 0);
|
|
2938
|
+
}
|
|
2939
|
+
return max - min + pad;
|
|
2940
|
+
}
|
|
2898
2941
|
measureFitSize() {
|
|
2899
2942
|
const vertical = layoutAxis(this.mode) === "height";
|
|
2900
2943
|
const handleSize = vertical ? this.handle.offsetHeight : this.handle.offsetWidth;
|
|
2901
2944
|
const content = this.scrollContainer;
|
|
2902
|
-
const natural = content ? handleSize + (vertical
|
|
2945
|
+
const natural = content ? handleSize + this.measureContentExtent(vertical) : handleSize;
|
|
2903
2946
|
if (typeof window === "undefined") return natural;
|
|
2904
2947
|
const viewport = vertical ? window.innerHeight : window.innerWidth;
|
|
2905
2948
|
return viewport > 0 ? Math.min(natural, viewport) : natural;
|
|
@@ -2908,22 +2951,62 @@ var BottomSheetEngine = class {
|
|
|
2908
2951
|
if (typeof ResizeObserver === "undefined") return;
|
|
2909
2952
|
if (!this.snapPointsRaw.some((p) => p.size === "fit" || p.size === "content"))
|
|
2910
2953
|
return;
|
|
2911
|
-
const targets = [this.handle];
|
|
2912
|
-
if (this.scrollContainer && this.scrollContainer !== this.handle) {
|
|
2913
|
-
targets.push(this.scrollContainer);
|
|
2914
|
-
}
|
|
2915
2954
|
let raf = 0;
|
|
2916
|
-
const
|
|
2955
|
+
const schedule = () => {
|
|
2917
2956
|
if (raf) return;
|
|
2918
2957
|
raf = requestAnimationFrame(() => {
|
|
2919
2958
|
raf = 0;
|
|
2920
2959
|
if (this.destroyed || this.gesture?.isDragging) return;
|
|
2921
2960
|
this.recompute();
|
|
2922
2961
|
});
|
|
2923
|
-
}
|
|
2924
|
-
|
|
2962
|
+
};
|
|
2963
|
+
const ro = new ResizeObserver(schedule);
|
|
2964
|
+
ro.observe(this.handle);
|
|
2965
|
+
const scroller = this.scrollContainer;
|
|
2966
|
+
const observed = /* @__PURE__ */ new Set();
|
|
2967
|
+
const slots = /* @__PURE__ */ new Set();
|
|
2968
|
+
const hasSlot = typeof HTMLSlotElement !== "undefined";
|
|
2969
|
+
const onSlotChange = () => resync();
|
|
2970
|
+
const trackSlots = () => {
|
|
2971
|
+
if (!scroller || !hasSlot) return;
|
|
2972
|
+
for (const child of Array.from(scroller.children)) {
|
|
2973
|
+
if (child instanceof HTMLSlotElement && !slots.has(child)) {
|
|
2974
|
+
child.addEventListener("slotchange", onSlotChange);
|
|
2975
|
+
slots.add(child);
|
|
2976
|
+
}
|
|
2977
|
+
}
|
|
2978
|
+
};
|
|
2979
|
+
const resync = () => {
|
|
2980
|
+
trackSlots();
|
|
2981
|
+
const targets = this.contentTargets();
|
|
2982
|
+
for (const el of observed) {
|
|
2983
|
+
if (!targets.includes(el)) {
|
|
2984
|
+
ro.unobserve(el);
|
|
2985
|
+
observed.delete(el);
|
|
2986
|
+
}
|
|
2987
|
+
}
|
|
2988
|
+
for (const el of targets) {
|
|
2989
|
+
if (!observed.has(el)) {
|
|
2990
|
+
ro.observe(el);
|
|
2991
|
+
observed.add(el);
|
|
2992
|
+
}
|
|
2993
|
+
}
|
|
2994
|
+
schedule();
|
|
2995
|
+
};
|
|
2996
|
+
let mo;
|
|
2997
|
+
if (scroller) {
|
|
2998
|
+
resync();
|
|
2999
|
+
if (typeof MutationObserver !== "undefined") {
|
|
3000
|
+
mo = new MutationObserver(resync);
|
|
3001
|
+
mo.observe(scroller, { childList: true });
|
|
3002
|
+
}
|
|
3003
|
+
}
|
|
2925
3004
|
this.teardowns.add(() => {
|
|
2926
3005
|
ro.disconnect();
|
|
3006
|
+
mo?.disconnect();
|
|
3007
|
+
for (const slot of slots) {
|
|
3008
|
+
slot.removeEventListener("slotchange", onSlotChange);
|
|
3009
|
+
}
|
|
2927
3010
|
if (raf) cancelAnimationFrame(raf);
|
|
2928
3011
|
});
|
|
2929
3012
|
}
|
|
@@ -3344,6 +3427,38 @@ var BottomSheetEngine = class {
|
|
|
3344
3427
|
}
|
|
3345
3428
|
};
|
|
3346
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
|
+
|
|
3347
3462
|
// src/vue/useBottomSheet.ts
|
|
3348
3463
|
function useBottomSheet(opts) {
|
|
3349
3464
|
const sheetRef = ref(null);
|
|
@@ -3360,13 +3475,20 @@ function useBottomSheet(opts) {
|
|
|
3360
3475
|
isAnimating: false,
|
|
3361
3476
|
progress: 0
|
|
3362
3477
|
});
|
|
3478
|
+
let restoreTeleport = null;
|
|
3363
3479
|
const sync = () => {
|
|
3364
3480
|
if (!engine) return;
|
|
3365
3481
|
Object.assign(state, engine.state);
|
|
3366
3482
|
};
|
|
3367
3483
|
onMounted(() => {
|
|
3368
3484
|
if (!sheetRef.value) return;
|
|
3369
|
-
const {
|
|
3485
|
+
const {
|
|
3486
|
+
onSnap,
|
|
3487
|
+
teleportTo,
|
|
3488
|
+
backdropColor,
|
|
3489
|
+
backdropOpacity,
|
|
3490
|
+
...engineOpts
|
|
3491
|
+
} = opts;
|
|
3370
3492
|
engine = new BottomSheetEngine({
|
|
3371
3493
|
...engineOpts,
|
|
3372
3494
|
element: sheetRef.value,
|
|
@@ -3376,6 +3498,17 @@ function useBottomSheet(opts) {
|
|
|
3376
3498
|
scrim: screenRef.value ?? void 0
|
|
3377
3499
|
});
|
|
3378
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
|
+
}
|
|
3379
3512
|
engine.on("snap", (payload) => {
|
|
3380
3513
|
sync();
|
|
3381
3514
|
onSnap?.(payload.id);
|
|
@@ -3391,6 +3524,8 @@ function useBottomSheet(opts) {
|
|
|
3391
3524
|
pending.length = 0;
|
|
3392
3525
|
});
|
|
3393
3526
|
onBeforeUnmount(() => {
|
|
3527
|
+
restoreTeleport?.();
|
|
3528
|
+
restoreTeleport = null;
|
|
3394
3529
|
engine?.destroy();
|
|
3395
3530
|
engine = null;
|
|
3396
3531
|
});
|
|
@@ -3619,6 +3754,23 @@ var _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
3619
3754
|
type: null,
|
|
3620
3755
|
required: false
|
|
3621
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
|
+
},
|
|
3622
3774
|
onSnap: {
|
|
3623
3775
|
type: Function,
|
|
3624
3776
|
required: false
|
|
@@ -3651,11 +3803,6 @@ var _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
3651
3803
|
required: false,
|
|
3652
3804
|
default: true
|
|
3653
3805
|
},
|
|
3654
|
-
teleportTo: {
|
|
3655
|
-
type: null,
|
|
3656
|
-
required: false,
|
|
3657
|
-
default: "body"
|
|
3658
|
-
},
|
|
3659
3806
|
anchors: {
|
|
3660
3807
|
type: Array,
|
|
3661
3808
|
required: false
|
|
@@ -3663,14 +3810,6 @@ var _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
3663
3810
|
scrimStages: {
|
|
3664
3811
|
type: [Object, null],
|
|
3665
3812
|
required: false
|
|
3666
|
-
},
|
|
3667
|
-
backdropColor: {
|
|
3668
|
-
type: String,
|
|
3669
|
-
required: false
|
|
3670
|
-
},
|
|
3671
|
-
backdropOpacity: {
|
|
3672
|
-
type: Number,
|
|
3673
|
-
required: false
|
|
3674
3813
|
}
|
|
3675
3814
|
},
|
|
3676
3815
|
emits: [
|
|
@@ -3898,23 +4037,27 @@ var _hoisted_4 = [
|
|
|
3898
4037
|
"aria-valuetext"
|
|
3899
4038
|
];
|
|
3900
4039
|
var _hoisted_5 = {
|
|
4040
|
+
key: 0,
|
|
4041
|
+
class: "bs-header"
|
|
4042
|
+
};
|
|
4043
|
+
var _hoisted_6 = {
|
|
3901
4044
|
ref: "contentRef",
|
|
3902
4045
|
class: "bs-content",
|
|
3903
4046
|
tabindex: "0",
|
|
3904
4047
|
role: "region",
|
|
3905
4048
|
"aria-label": "Sheet content"
|
|
3906
4049
|
};
|
|
3907
|
-
var
|
|
3908
|
-
key:
|
|
4050
|
+
var _hoisted_7 = {
|
|
4051
|
+
key: 1,
|
|
3909
4052
|
class: "bs-footer"
|
|
3910
4053
|
};
|
|
3911
|
-
var
|
|
4054
|
+
var _hoisted_8 = {
|
|
3912
4055
|
class: "bs-sr-only",
|
|
3913
4056
|
role: "status",
|
|
3914
4057
|
"aria-live": "polite"
|
|
3915
4058
|
};
|
|
3916
|
-
var _hoisted_8 = ["data-mode"];
|
|
3917
4059
|
var _hoisted_9 = ["data-mode"];
|
|
4060
|
+
var _hoisted_10 = ["data-mode"];
|
|
3918
4061
|
function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
|
|
3919
4062
|
return openBlock(), createBlock(Teleport, {
|
|
3920
4063
|
to: $props.teleportTo,
|
|
@@ -3960,18 +4103,19 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
3960
4103
|
"aria-valuenow": $setup.activeIdx,
|
|
3961
4104
|
"aria-valuetext": $setup.state.activeId,
|
|
3962
4105
|
"aria-label": "Resize sheet"
|
|
3963
|
-
},
|
|
4106
|
+
}, null, 8, _hoisted_4),
|
|
4107
|
+
_ctx.$slots.header ? (openBlock(), createElementBlock("div", _hoisted_5, [renderSlot(_ctx.$slots, "header", { state: $setup.state })])) : createCommentVNode("v-if", true),
|
|
3964
4108
|
createElementVNode(
|
|
3965
4109
|
"div",
|
|
3966
|
-
|
|
4110
|
+
_hoisted_6,
|
|
3967
4111
|
[renderSlot(_ctx.$slots, "default")],
|
|
3968
4112
|
512
|
|
3969
4113
|
/* NEED_PATCH */
|
|
3970
4114
|
),
|
|
3971
|
-
_ctx.$slots.footer ? (openBlock(), createElementBlock("div",
|
|
4115
|
+
_ctx.$slots.footer ? (openBlock(), createElementBlock("div", _hoisted_7, [renderSlot(_ctx.$slots, "footer", { state: $setup.state })])) : createCommentVNode("v-if", true),
|
|
3972
4116
|
createElementVNode(
|
|
3973
4117
|
"span",
|
|
3974
|
-
|
|
4118
|
+
_hoisted_8,
|
|
3975
4119
|
toDisplayString($setup.state.activeId),
|
|
3976
4120
|
1
|
|
3977
4121
|
/* TEXT */
|
|
@@ -3982,13 +4126,13 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
3982
4126
|
class: "bs-button-slot",
|
|
3983
4127
|
"data-side": "left",
|
|
3984
4128
|
"data-mode": $setup.props.mode ?? "bottom"
|
|
3985
|
-
}, [renderSlot(_ctx.$slots, "button-left")], 8,
|
|
4129
|
+
}, [renderSlot(_ctx.$slots, "button-left")], 8, _hoisted_9)) : createCommentVNode("v-if", true),
|
|
3986
4130
|
_ctx.$slots["button-right"] ? (openBlock(), createElementBlock("div", {
|
|
3987
4131
|
key: 2,
|
|
3988
4132
|
class: "bs-button-slot",
|
|
3989
4133
|
"data-side": "right",
|
|
3990
4134
|
"data-mode": $setup.props.mode ?? "bottom"
|
|
3991
|
-
}, [renderSlot(_ctx.$slots, "button-right")], 8,
|
|
4135
|
+
}, [renderSlot(_ctx.$slots, "button-right")], 8, _hoisted_10)) : createCommentVNode("v-if", true)
|
|
3992
4136
|
]), (openBlock(true), createElementBlock(
|
|
3993
4137
|
Fragment,
|
|
3994
4138
|
null,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@surdeddd/bottom-sheet",
|
|
3
|
-
"version": "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",
|