@douxcode/vue-spring-bottom-sheet 1.2.7 → 2.0.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/BottomSheet.d.ts +15 -17
- package/dist/composables/useSnapPoints.d.ts +5 -4
- package/dist/index.mjs +340 -260
- package/dist/style.css +1 -1
- package/dist/types.d.ts +2 -2
- package/dist/utils/heightPercentToPixels.d.ts +1 -0
- package/dist/utils/rubberbandIfOutOfBounds.d.ts +1 -0
- package/package.json +14 -17
- package/LICENSE.txt +0 -21
- package/README.md +0 -166
package/dist/BottomSheet.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BottomSheetProps } from './types
|
|
1
|
+
import { BottomSheetProps } from './types';
|
|
2
2
|
declare function __VLS_template(): {
|
|
3
3
|
attrs: Partial<{}>;
|
|
4
4
|
slots: {
|
|
@@ -7,37 +7,35 @@ declare function __VLS_template(): {
|
|
|
7
7
|
footer?(_: {}): any;
|
|
8
8
|
};
|
|
9
9
|
refs: {
|
|
10
|
-
backdrop:
|
|
11
|
-
sheet:
|
|
12
|
-
sheetHeader:
|
|
10
|
+
backdrop: import('vue').ShallowUnwrapRef<{}> | null;
|
|
11
|
+
sheet: import('vue').ShallowUnwrapRef<{}> | null;
|
|
12
|
+
sheetHeader: import('vue').ShallowUnwrapRef<{}> | null;
|
|
13
13
|
sheetScroll: HTMLDivElement;
|
|
14
|
-
sheetContentWrapper:
|
|
14
|
+
sheetContentWrapper: import('vue').ShallowUnwrapRef<{}> | null;
|
|
15
15
|
sheetContent: HTMLDivElement;
|
|
16
|
-
sheetFooter:
|
|
16
|
+
sheetFooter: import('vue').ShallowUnwrapRef<{}> | null;
|
|
17
17
|
};
|
|
18
18
|
rootEl: any;
|
|
19
19
|
};
|
|
20
20
|
type __VLS_TemplateResult = ReturnType<typeof __VLS_template>;
|
|
21
21
|
declare const __VLS_component: import('vue').DefineComponent<BottomSheetProps, {
|
|
22
|
-
open: () => void
|
|
22
|
+
open: () => Promise<void>;
|
|
23
23
|
close: () => void;
|
|
24
|
-
snapToPoint: (
|
|
24
|
+
snapToPoint: (index: number) => void;
|
|
25
25
|
}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {} & {
|
|
26
26
|
opened: () => any;
|
|
27
27
|
closed: () => any;
|
|
28
28
|
ready: () => any;
|
|
29
29
|
"dragging-up": () => any;
|
|
30
30
|
"dragging-down": () => any;
|
|
31
|
-
|
|
32
|
-
maxHeight: (maxSheetHeight: number) => any;
|
|
31
|
+
instinctHeight: (instinctHeight: number) => any;
|
|
33
32
|
}, string, import('vue').PublicProps, Readonly<BottomSheetProps> & Readonly<{
|
|
34
33
|
onOpened?: (() => any) | undefined;
|
|
35
34
|
onClosed?: (() => any) | undefined;
|
|
36
35
|
onReady?: (() => any) | undefined;
|
|
37
36
|
"onDragging-up"?: (() => any) | undefined;
|
|
38
37
|
"onDragging-down"?: (() => any) | undefined;
|
|
39
|
-
|
|
40
|
-
onMaxHeight?: ((maxSheetHeight: number) => any) | undefined;
|
|
38
|
+
onInstinctHeight?: ((instinctHeight: number) => any) | undefined;
|
|
41
39
|
}>, {
|
|
42
40
|
duration: number;
|
|
43
41
|
blocking: boolean;
|
|
@@ -45,13 +43,13 @@ declare const __VLS_component: import('vue').DefineComponent<BottomSheetProps, {
|
|
|
45
43
|
canBackdropClose: boolean;
|
|
46
44
|
expandOnContentDrag: boolean;
|
|
47
45
|
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {
|
|
48
|
-
backdrop:
|
|
49
|
-
sheet:
|
|
50
|
-
sheetHeader:
|
|
46
|
+
backdrop: import('vue').ShallowUnwrapRef<{}> | null;
|
|
47
|
+
sheet: import('vue').ShallowUnwrapRef<{}> | null;
|
|
48
|
+
sheetHeader: import('vue').ShallowUnwrapRef<{}> | null;
|
|
51
49
|
sheetScroll: HTMLDivElement;
|
|
52
|
-
sheetContentWrapper:
|
|
50
|
+
sheetContentWrapper: import('vue').ShallowUnwrapRef<{}> | null;
|
|
53
51
|
sheetContent: HTMLDivElement;
|
|
54
|
-
sheetFooter:
|
|
52
|
+
sheetFooter: import('vue').ShallowUnwrapRef<{}> | null;
|
|
55
53
|
}, any>;
|
|
56
54
|
declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, __VLS_TemplateResult["slots"]>;
|
|
57
55
|
export default _default;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Ref } from 'vue';
|
|
2
|
-
export declare function useSnapPoints(snapPoints: Ref<number
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
export declare function useSnapPoints(snapPoints: Ref<Array<number | `${number}%`>>, height: Ref<number>, windowHeight: Ref<number>): {
|
|
3
|
+
currentSnapPointIndex: Ref<number, number>;
|
|
4
|
+
flattenedSnapPoints: import('vue').ComputedRef<number[]>;
|
|
5
|
+
minSnapPoint: import('vue').ComputedRef<number>;
|
|
6
|
+
maxSnapPoint: import('vue').ComputedRef<number>;
|
|
6
7
|
closestSnapPointIndex: import('vue').ComputedRef<number>;
|
|
7
8
|
};
|
package/dist/index.mjs
CHANGED
|
@@ -1,303 +1,383 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
return a === void 0 ? e : Object.assign(e, { lazy: a, lazyArgs: u });
|
|
1
|
+
import { ref as y, computed as B, defineComponent as xe, toRefs as _e, watch as J, onUnmounted as Me, createBlock as X, openBlock as Z, Teleport as Oe, createElementVNode as ee, createVNode as $, unref as k, withCtx as E, createCommentVNode as ce, normalizeStyle as Ie, renderSlot as te, nextTick as q } from "vue";
|
|
2
|
+
import { useMotionValue as fe, animate as O, AnimatePresence as he, Motion as A } from "motion-v";
|
|
3
|
+
import { useWindowSize as Ee, useElementBounding as N, useScrollLock as pe } from "@vueuse/core";
|
|
4
|
+
import { useFocusTrap as Be } from "@vueuse/integrations/useFocusTrap";
|
|
5
|
+
function Q(n, a) {
|
|
6
|
+
const o = parseFloat(n);
|
|
7
|
+
return a * o / 100;
|
|
9
8
|
}
|
|
10
|
-
function
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
function De(n, a, o) {
|
|
10
|
+
const e = y(0), v = B(() => n.value.map((f) => typeof f == "string" ? Q(f, o.value) : f)), S = B(() => Math.min(...v.value)), i = B(() => Math.max(...v.value)), p = B(() => {
|
|
11
|
+
const f = v.value.reduce(
|
|
12
|
+
(g, x) => Math.abs(x - a.value) < Math.abs(g - a.value) ? x : g
|
|
13
|
+
);
|
|
14
|
+
return v.value.indexOf(f);
|
|
15
|
+
});
|
|
16
|
+
return {
|
|
17
|
+
currentSnapPointIndex: e,
|
|
18
|
+
flattenedSnapPoints: v,
|
|
19
|
+
minSnapPoint: S,
|
|
20
|
+
maxSnapPoint: i,
|
|
21
|
+
closestSnapPointIndex: p
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
function He(n, a, o) {
|
|
25
|
+
let e = (v) => n(v, ...a);
|
|
26
|
+
return o === void 0 ? e : Object.assign(e, { lazy: o, lazyArgs: a });
|
|
27
|
+
}
|
|
28
|
+
function Re(n, a, o) {
|
|
29
|
+
let e = n.length - a.length;
|
|
30
|
+
if (e === 0) return n(...a);
|
|
31
|
+
if (e === 1) return He(n, a, o);
|
|
14
32
|
throw new Error("Wrong number of arguments");
|
|
15
33
|
}
|
|
16
|
-
function
|
|
17
|
-
let
|
|
18
|
-
let
|
|
19
|
-
|
|
34
|
+
function Fe(n, { triggerAt: a = "end", minQuietPeriodMs: o, maxBurstDurationMs: e, minGapMs: v, reducer: S = $e }) {
|
|
35
|
+
let i, p, f, g, x = () => {
|
|
36
|
+
let r = f;
|
|
37
|
+
r !== void 0 && (f = void 0, n(r), v !== void 0 && (p = setTimeout(D, v)));
|
|
38
|
+
}, D = () => {
|
|
39
|
+
clearTimeout(p), p = void 0, i === void 0 && x();
|
|
20
40
|
}, H = () => {
|
|
21
|
-
clearTimeout(
|
|
22
|
-
}, w = () => {
|
|
23
|
-
clearTimeout(s), s = void 0, S = void 0, r === void 0 && C();
|
|
41
|
+
clearTimeout(i), i = void 0, g = void 0, p === void 0 && x();
|
|
24
42
|
};
|
|
25
|
-
return { call: (...
|
|
26
|
-
let
|
|
27
|
-
if ((
|
|
28
|
-
if (
|
|
29
|
-
clearTimeout(
|
|
30
|
-
let
|
|
31
|
-
|
|
32
|
-
let W = e === void 0 ?
|
|
33
|
-
|
|
43
|
+
return { call: (...r) => {
|
|
44
|
+
let d = i === void 0 && p === void 0;
|
|
45
|
+
if ((a !== "start" || d) && (f = S(f, ...r)), !(i === void 0 && !d)) {
|
|
46
|
+
if (o !== void 0 || e !== void 0 || v === void 0) {
|
|
47
|
+
clearTimeout(i);
|
|
48
|
+
let w = Date.now();
|
|
49
|
+
g ?? (g = w);
|
|
50
|
+
let W = e === void 0 ? o ?? 0 : Math.min(o ?? e, e - (w - g));
|
|
51
|
+
i = setTimeout(H, W);
|
|
34
52
|
}
|
|
35
|
-
|
|
53
|
+
a !== "end" && d && x();
|
|
36
54
|
}
|
|
37
55
|
}, cancel: () => {
|
|
38
|
-
clearTimeout(
|
|
56
|
+
clearTimeout(i), i = void 0, g = void 0, clearTimeout(p), p = void 0, f = void 0;
|
|
39
57
|
}, flush: () => {
|
|
40
|
-
|
|
58
|
+
H(), D();
|
|
41
59
|
}, get isIdle() {
|
|
42
|
-
return
|
|
60
|
+
return i === void 0 && p === void 0;
|
|
43
61
|
} };
|
|
44
62
|
}
|
|
45
|
-
var
|
|
46
|
-
function
|
|
47
|
-
return
|
|
63
|
+
var $e = () => "";
|
|
64
|
+
function m(...n) {
|
|
65
|
+
return Re(Ae, n);
|
|
48
66
|
}
|
|
49
|
-
var
|
|
50
|
-
function
|
|
51
|
-
|
|
52
|
-
const s = a.value.reduce(
|
|
53
|
-
(r, f) => Math.abs(f - u.value) < Math.abs(r - u.value) ? f : r
|
|
54
|
-
);
|
|
55
|
-
return a.value.indexOf(s);
|
|
56
|
-
});
|
|
57
|
-
return {
|
|
58
|
-
minSnap: e,
|
|
59
|
-
maxSnap: n,
|
|
60
|
-
snapPoints: o,
|
|
61
|
-
closestSnapPointIndex: c
|
|
62
|
-
};
|
|
67
|
+
var Ae = (n, { min: a, max: o }) => a !== void 0 && n < a ? a : o !== void 0 && n > o ? o : n;
|
|
68
|
+
function We(n, a, o) {
|
|
69
|
+
return Math.max(a, Math.min(n, o));
|
|
63
70
|
}
|
|
64
|
-
|
|
71
|
+
function Le(n, a) {
|
|
72
|
+
return Math.pow(n, a * 5);
|
|
73
|
+
}
|
|
74
|
+
function ge(n, a, o) {
|
|
75
|
+
return a === 0 || Math.abs(a) === 1 / 0 ? Le(n, o) : n * a * o / (a + o * n);
|
|
76
|
+
}
|
|
77
|
+
function ae(n, a, o, e = 0.15) {
|
|
78
|
+
return e === 0 ? We(n, a, o) : n < a ? -ge(a - n, o - a, e) + a : n > o ? +ge(n - o, o - a, e) + o : n;
|
|
79
|
+
}
|
|
80
|
+
const Ve = { "data-vsbs-container": "" }, ze = /* @__PURE__ */ xe({
|
|
65
81
|
__name: "BottomSheet",
|
|
66
82
|
props: {
|
|
67
83
|
duration: { default: 250 },
|
|
68
84
|
snapPoints: {},
|
|
69
|
-
|
|
85
|
+
initialSnapPoint: {},
|
|
70
86
|
blocking: { type: Boolean, default: !0 },
|
|
71
87
|
canSwipeClose: { type: Boolean, default: !0 },
|
|
72
88
|
canBackdropClose: { type: Boolean, default: !0 },
|
|
73
89
|
expandOnContentDrag: { type: Boolean, default: !0 }
|
|
74
90
|
},
|
|
75
|
-
emits: ["opened", "closed", "ready", "dragging-up", "dragging-down", "
|
|
76
|
-
setup(
|
|
77
|
-
|
|
78
|
-
"
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
91
|
+
emits: ["opened", "closed", "ready", "dragging-up", "dragging-down", "instinctHeight"],
|
|
92
|
+
setup(n, { expose: a, emit: o }) {
|
|
93
|
+
const e = n, v = o, S = y(!1), i = y(), p = y(null), f = y(null), g = y(null), x = y(null), D = y(null), H = y(null), r = y(e.expandOnContentDrag), { height: d } = Ee({
|
|
94
|
+
type: "visual"
|
|
95
|
+
}), { height: w } = N(i), { height: W } = N(p), { height: ne } = N(D), { height: oe } = N(f), G = B({
|
|
96
|
+
get() {
|
|
97
|
+
return m(
|
|
98
|
+
Math.ceil(ne.value + W.value + oe.value),
|
|
99
|
+
{
|
|
100
|
+
max: d.value
|
|
101
|
+
}
|
|
102
|
+
);
|
|
103
|
+
},
|
|
104
|
+
set(t) {
|
|
105
|
+
[W.value, ne.value, oe.value] = t;
|
|
106
|
+
}
|
|
107
|
+
}), l = y(0), s = y(0), P = fe(0), b = fe(0), { snapPoints: me } = _e(e), h = B(() => me.value ?? [G.value]), {
|
|
108
|
+
flattenedSnapPoints: K,
|
|
109
|
+
currentSnapPointIndex: I,
|
|
110
|
+
closestSnapPointIndex: L,
|
|
111
|
+
minSnapPoint: M,
|
|
112
|
+
maxSnapPoint: R
|
|
113
|
+
} = De(h, l, d);
|
|
114
|
+
let _;
|
|
115
|
+
const V = pe(document.body), z = pe(document.documentElement), U = Be([i, H], {
|
|
82
116
|
immediate: !1,
|
|
83
|
-
fallbackFocus: () =>
|
|
84
|
-
})
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
D,
|
|
88
|
-
{},
|
|
89
|
-
{ push: x, motionValues: O, stop: le }
|
|
90
|
-
), t = g(0), l = g(0), { snapPoints: ie } = he(e), se = y(() => ie.value ?? [k.value]), {
|
|
91
|
-
minSnap: P,
|
|
92
|
-
maxSnap: _,
|
|
93
|
-
snapPoints: T,
|
|
94
|
-
closestSnapPointIndex: F
|
|
95
|
-
} = Ie(se, t), L = te(document.body), V = te(document.documentElement), K = (i) => {
|
|
96
|
-
i.key === "Escape" && E();
|
|
97
|
-
}, re = () => {
|
|
98
|
-
c.value && (t.value = Math.min(e.defaultSnapPoint ?? P.value, h.value), M({
|
|
99
|
-
height: t.value,
|
|
100
|
-
y: t.value
|
|
101
|
-
}), x("y", 0, D, {
|
|
102
|
-
type: "tween",
|
|
103
|
-
easings: "easeInOut",
|
|
104
|
-
bounce: 0,
|
|
105
|
-
duration: e.duration
|
|
106
|
-
}), w.value = !0, window.addEventListener("keydown", K), e.blocking && setTimeout(() => {
|
|
107
|
-
O.value.y.get() - 0 < 0.1 && (n("opened"), Q.activate());
|
|
108
|
-
}, e.duration));
|
|
109
|
-
}, E = () => {
|
|
110
|
-
c.value && (x("y", p.value, D, {
|
|
111
|
-
type: "tween",
|
|
112
|
-
bounce: 0,
|
|
113
|
-
duration: e.duration
|
|
114
|
-
}), w.value = !1, e.blocking && Q.deactivate(), window.removeEventListener("keydown", K), setTimeout(() => {
|
|
115
|
-
O.value.y.get() - p.value < 0.1 && n("closed");
|
|
116
|
-
}, e.duration));
|
|
117
|
-
}, ve = () => {
|
|
118
|
-
e.canBackdropClose && E();
|
|
119
|
-
};
|
|
120
|
-
function U(i) {
|
|
121
|
-
v.value = !0, q(i);
|
|
117
|
+
fallbackFocus: () => i.value || document.body
|
|
118
|
+
});
|
|
119
|
+
function le(t) {
|
|
120
|
+
r.value = !0, ue(t);
|
|
122
121
|
}
|
|
123
|
-
function
|
|
124
|
-
|
|
122
|
+
function ue(t) {
|
|
123
|
+
r.value && t.preventDefault();
|
|
125
124
|
}
|
|
126
|
-
const
|
|
127
|
-
t.
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
125
|
+
const ie = (t) => {
|
|
126
|
+
t.key === "Escape" && j();
|
|
127
|
+
}, be = () => {
|
|
128
|
+
e.canBackdropClose && j();
|
|
129
|
+
}, ye = async () => {
|
|
130
|
+
S.value = !0, e.blocking && (V.value = !0, z.value = !0), await q();
|
|
131
|
+
const t = i.value.$el;
|
|
132
|
+
w.value = t.getBoundingClientRect().height;
|
|
133
|
+
const u = t.querySelector("[data-vsbs-content]"), c = t.querySelector("[data-vsbs-header]"), C = t.querySelector("[data-vsbs-footer]");
|
|
134
|
+
if (G.value = [
|
|
135
|
+
c.getBoundingClientRect().height,
|
|
136
|
+
u.getBoundingClientRect().height,
|
|
137
|
+
C.getBoundingClientRect().height
|
|
138
|
+
], await q(), I.value = K.value.findIndex(
|
|
139
|
+
(T) => T === M.value
|
|
140
|
+
), e.initialSnapPoint) {
|
|
141
|
+
const T = e.initialSnapPoint;
|
|
142
|
+
if (T < 0 || T >= h.value.length) {
|
|
143
|
+
console.warn("Index out of bounds");
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
let F;
|
|
147
|
+
typeof h.value[T] == "number" ? F = m(h.value[T], {
|
|
148
|
+
max: d.value
|
|
149
|
+
}) : F = Q(h.value[T], d.value), l.value = F;
|
|
150
|
+
} else
|
|
151
|
+
l.value = m(M.value, {
|
|
152
|
+
max: d.value
|
|
153
|
+
});
|
|
154
|
+
s.value = l.value, P.set(l.value), b.set(l.value), _ = O(P, l.value, {
|
|
155
|
+
duration: e.duration / 1e3,
|
|
156
|
+
ease: "easeInOut"
|
|
157
|
+
}), _ = O(b, 0, {
|
|
158
|
+
duration: e.duration / 1e3,
|
|
159
|
+
ease: "easeInOut"
|
|
160
|
+
}), window.addEventListener("keydown", ie), e.blocking && setTimeout(() => {
|
|
161
|
+
P.get() < 1 && (v("opened"), U.activate());
|
|
162
|
+
}, e.duration);
|
|
163
|
+
}, j = () => {
|
|
164
|
+
S.value = !1, e.blocking && (V.value = !1, z.value = !1), window.removeEventListener("keydown", ie), e.blocking && U.deactivate(), setTimeout(() => {
|
|
165
|
+
v("closed");
|
|
166
|
+
}, e.duration);
|
|
167
|
+
}, re = (t) => {
|
|
168
|
+
if (!h.value) return;
|
|
169
|
+
if (t < 0 || t >= h.value.length) {
|
|
170
|
+
console.warn("Index out of bounds");
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
I.value = t;
|
|
174
|
+
let u;
|
|
175
|
+
typeof h.value[t] == "number" ? u = m(h.value[t], {
|
|
176
|
+
max: d.value
|
|
177
|
+
}) : u = Q(h.value[t], d.value), l.value = u, _ = O(P, l.value, {
|
|
178
|
+
duration: e.duration / 1e3,
|
|
179
|
+
ease: "easeInOut"
|
|
132
180
|
});
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
181
|
+
};
|
|
182
|
+
function se(t) {
|
|
183
|
+
t > 0 ? v("dragging-down") : t < 0 && v("dragging-up");
|
|
184
|
+
}
|
|
185
|
+
const ve = () => {
|
|
186
|
+
l.value = w.value, s.value = b.get(), P.jump(l.value), b.jump(s.value);
|
|
187
|
+
}, de = async (t, u) => {
|
|
188
|
+
await q(), i.value && (s.value <= 0 && (l.value -= u.delta.y), l.value <= M.value && (l.value = M.value, s.value += u.delta.y, b.set(
|
|
189
|
+
e.canSwipeClose ? m(s.value, { min: 0 }) : m(ae(s.value, -w.value, 0, 0.5), {
|
|
190
|
+
min: 0
|
|
191
|
+
})
|
|
192
|
+
)), P.set(
|
|
193
|
+
m(ae(l.value, 0, R.value, 0.25), {
|
|
141
194
|
min: 0,
|
|
142
|
-
max:
|
|
195
|
+
max: d.value
|
|
143
196
|
})
|
|
144
|
-
|
|
145
|
-
},
|
|
146
|
-
|
|
147
|
-
(
|
|
148
|
-
) : 0,
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
197
|
+
), se(u.delta.y));
|
|
198
|
+
}, Y = () => {
|
|
199
|
+
s.value = e.canSwipeClose ? [0, l.value].reduce(
|
|
200
|
+
(u, c) => Math.abs(c - s.value) < Math.abs(u - s.value) ? c : u
|
|
201
|
+
) : 0, _ = O(b, s.value, {
|
|
202
|
+
duration: e.duration / 1e3,
|
|
203
|
+
ease: "easeInOut"
|
|
204
|
+
}), s.value === l.value && (s.value = 0, j()), I.value = L.value;
|
|
205
|
+
let t;
|
|
206
|
+
typeof h.value[L.value] == "number" ? t = m(h.value[L.value], {
|
|
207
|
+
max: d.value
|
|
208
|
+
}) : t = Q(
|
|
209
|
+
h.value[L.value],
|
|
210
|
+
d.value
|
|
211
|
+
), l.value = t, _ = O(P, l.value, {
|
|
212
|
+
duration: e.duration / 1e3,
|
|
213
|
+
ease: "easeInOut"
|
|
214
|
+
}), _ = O(b, 0, {
|
|
215
|
+
duration: e.duration / 1e3,
|
|
216
|
+
ease: "easeInOut"
|
|
158
217
|
});
|
|
159
|
-
},
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
{
|
|
169
|
-
|
|
170
|
-
|
|
218
|
+
}, Se = (t, u) => {
|
|
219
|
+
if (l.value = w.value, s.value = b.get(), _.stop(), !g.value) return;
|
|
220
|
+
const c = g.value.scrollTop === 0, C = u.delta.y > 0, T = K.value.length === 1, F = 0.5 > Math.abs(l.value - R.value);
|
|
221
|
+
if (T) {
|
|
222
|
+
if (!e.expandOnContentDrag) {
|
|
223
|
+
r.value = !1;
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
b.get() === 0 && c && C && (r.value = !0), b.get() === 0 && c && !C && (r.value = !1);
|
|
227
|
+
} else {
|
|
228
|
+
if (!e.expandOnContentDrag) {
|
|
229
|
+
r.value = !1;
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
r.value = !0, F && (C && c && (r.value = !0), !C && c && (r.value = !1), c || (r.value = !1));
|
|
171
233
|
}
|
|
172
|
-
|
|
173
|
-
{
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
onDragEnd: A
|
|
177
|
-
},
|
|
178
|
-
{
|
|
179
|
-
domTarget: r,
|
|
180
|
-
drag: { filterTaps: !0 }
|
|
181
|
-
}
|
|
182
|
-
), N(
|
|
183
|
-
{
|
|
184
|
-
onDragStart: ({ direction: [i, d] }) => {
|
|
185
|
-
L.value = !0, V.value = !0, t.value = p.value, l.value = O.value.y.get(), j();
|
|
186
|
-
const B = f.value.scrollTop === 0, m = d > 0;
|
|
187
|
-
T.value.length === 1 ? l.value === 0 && B && (v.value = m) : (e.expandOnContentDrag && t.value !== _.value && (v.value = !0), t.value === _.value && B && (v.value = m));
|
|
188
|
-
},
|
|
189
|
-
onDrag: ({ delta: [i, d], direction: [B, m] }) => {
|
|
190
|
-
if (!e.expandOnContentDrag) {
|
|
191
|
-
v.value = !1;
|
|
192
|
-
return;
|
|
193
|
-
}
|
|
194
|
-
if (!c.value) return;
|
|
195
|
-
l.value === 0 && v.value && e.expandOnContentDrag && (t.value -= d), t.value <= P.value && (t.value = P.value, v.value && e.expandOnContentDrag && (l.value += d), l.value = $(l.value, { min: 0, max: P.value }), M({
|
|
196
|
-
y: e.canSwipeClose ? l.value : G(l.value, -p.value, 0, 0.5)
|
|
197
|
-
})), t.value > _.value && (t.value = _.value), t.value = Math.min(t.value, h.value);
|
|
198
|
-
const Y = f.value.scrollTop === 0;
|
|
199
|
-
T.value.length === 1 ? d < 0 && l.value === 0 && Y && (v.value = !1) : t.value === _.value && (v.value = !1), M({
|
|
200
|
-
height: t.value
|
|
201
|
-
}), m > 0 ? n("dragging-down") : m < 0 && n("dragging-up");
|
|
202
|
-
},
|
|
203
|
-
onDragEnd: A
|
|
204
|
-
},
|
|
205
|
-
{
|
|
206
|
-
domTarget: S,
|
|
207
|
-
drag: { filterTaps: !0 }
|
|
234
|
+
}, Pe = async (t, u) => {
|
|
235
|
+
if (await q(), !e.expandOnContentDrag) {
|
|
236
|
+
r.value = !1;
|
|
237
|
+
return;
|
|
208
238
|
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
)
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
239
|
+
if (!i.value) return;
|
|
240
|
+
s.value === 0 && r.value && e.expandOnContentDrag && (l.value -= u.delta.y), l.value <= M.value && (l.value = M.value, r.value && e.expandOnContentDrag && (s.value += u.delta.y), s.value = m(s.value, { min: 0, max: M.value }), b.set(
|
|
241
|
+
e.canSwipeClose ? m(s.value, { min: 0 }) : m(ae(s.value, -w.value, 0, 0.5), {
|
|
242
|
+
min: 0
|
|
243
|
+
})
|
|
244
|
+
)), l.value > R.value && (l.value = R.value), l.value = m(l.value, { max: d.value }), K.value.length === 1 || l.value === R.value && (r.value = !1), P.set(l.value), se(u.delta.y);
|
|
245
|
+
}, ke = () => {
|
|
246
|
+
e.blocking || (V.value = !0, z.value = !0);
|
|
247
|
+
}, we = () => {
|
|
248
|
+
e.blocking || (V.value = !1, z.value = !1);
|
|
249
|
+
}, Ce = () => {
|
|
250
|
+
if (!g.value) return;
|
|
251
|
+
const t = g.value.scrollTop === 0;
|
|
252
|
+
r.value = t;
|
|
253
|
+
}, Te = Fe((t) => re(t), {
|
|
254
|
+
minQuietPeriodMs: e.duration,
|
|
255
|
+
reducer: (t, u) => u
|
|
256
|
+
});
|
|
257
|
+
return J(h, (t, u) => {
|
|
258
|
+
if (S.value === !1 || !t || !u) return;
|
|
259
|
+
const c = t[I.value], C = u[I.value];
|
|
260
|
+
typeof c != "string" && typeof C != "string" && (l.value = m(c, {
|
|
261
|
+
max: d.value
|
|
262
|
+
}), c !== C && (_ = O(P, l.value, {
|
|
263
|
+
duration: e.duration / 1e3,
|
|
264
|
+
ease: "easeInOut"
|
|
265
|
+
})));
|
|
266
|
+
}), J(d, () => {
|
|
267
|
+
Te.call(I.value);
|
|
268
|
+
}), J(G, (t) => {
|
|
269
|
+
v("instinctHeight", t);
|
|
270
|
+
}), Me(() => {
|
|
271
|
+
U.deactivate();
|
|
272
|
+
}), a({ open: ye, close: j, snapToPoint: re }), (t, u) => (Z(), X(Oe, { to: "body" }, [
|
|
273
|
+
ee("div", Ve, [
|
|
274
|
+
$(k(he), null, {
|
|
275
|
+
default: E(() => [
|
|
276
|
+
S.value && t.blocking ? (Z(), X(k(A), {
|
|
277
|
+
key: 0,
|
|
236
278
|
ref_key: "backdrop",
|
|
237
279
|
ref: H,
|
|
238
280
|
"data-vsbs-backdrop": "",
|
|
239
|
-
onClick:
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
281
|
+
onClick: u[0] || (u[0] = (c) => be()),
|
|
282
|
+
transition: {
|
|
283
|
+
ease: "easeInOut",
|
|
284
|
+
duration: t.duration / 1e3
|
|
285
|
+
},
|
|
286
|
+
initial: { opacity: 0 },
|
|
287
|
+
animate: { opacity: 1 },
|
|
288
|
+
exit: { opacity: 0 }
|
|
289
|
+
}, null, 8, ["transition"])) : ce("", !0)
|
|
243
290
|
]),
|
|
244
291
|
_: 1
|
|
245
292
|
}),
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
293
|
+
$(k(he), null, {
|
|
294
|
+
default: E(() => [
|
|
295
|
+
S.value ? (Z(), X(k(A), {
|
|
296
|
+
key: 0,
|
|
297
|
+
ref_key: "sheet",
|
|
298
|
+
ref: i,
|
|
299
|
+
exit: { y: "100%", height: k(w) },
|
|
300
|
+
initial: { y: "100%" },
|
|
301
|
+
style: Ie({ y: k(b), height: k(P) }),
|
|
302
|
+
"data-vsbs-shadow": !t.blocking,
|
|
303
|
+
"data-vsbs-sheet-show": S.value,
|
|
304
|
+
"aria-modal": "true",
|
|
305
|
+
"data-vsbs-sheet": "",
|
|
306
|
+
tabindex: "-1",
|
|
307
|
+
onTouchstart: ke,
|
|
308
|
+
onTouchend: we
|
|
309
|
+
}, {
|
|
310
|
+
default: E(() => [
|
|
311
|
+
$(k(A), {
|
|
312
|
+
ref_key: "sheetHeader",
|
|
313
|
+
ref: p,
|
|
314
|
+
"data-vsbs-header": "",
|
|
315
|
+
onPanStart: ve,
|
|
316
|
+
onPan: de,
|
|
317
|
+
onPanEnd: Y,
|
|
318
|
+
onTouchmove: le
|
|
319
|
+
}, {
|
|
320
|
+
default: E(() => [
|
|
321
|
+
te(t.$slots, "header", {}, void 0, !0)
|
|
322
|
+
]),
|
|
323
|
+
_: 3
|
|
324
|
+
}, 512),
|
|
325
|
+
ee("div", {
|
|
326
|
+
ref_key: "sheetScroll",
|
|
327
|
+
ref: g,
|
|
328
|
+
"data-vsbs-scroll": "",
|
|
329
|
+
onScrollend: Ce
|
|
330
|
+
}, [
|
|
331
|
+
$(k(A), {
|
|
332
|
+
ref_key: "sheetContentWrapper",
|
|
333
|
+
ref: x,
|
|
334
|
+
"data-vsbs-content-wrapper": "",
|
|
335
|
+
onPanStart: Se,
|
|
336
|
+
onPan: Pe,
|
|
337
|
+
onPanEnd: Y,
|
|
338
|
+
onTouchmove: ue
|
|
339
|
+
}, {
|
|
340
|
+
default: E(() => [
|
|
341
|
+
ee("div", {
|
|
342
|
+
ref_key: "sheetContent",
|
|
343
|
+
ref: D,
|
|
344
|
+
"data-vsbs-content": ""
|
|
345
|
+
}, [
|
|
346
|
+
te(t.$slots, "default", {}, void 0, !0)
|
|
347
|
+
], 512)
|
|
348
|
+
]),
|
|
349
|
+
_: 3
|
|
350
|
+
}, 512)
|
|
351
|
+
], 544),
|
|
352
|
+
$(k(A), {
|
|
353
|
+
ref_key: "sheetFooter",
|
|
354
|
+
ref: f,
|
|
355
|
+
"data-vsbs-footer": "",
|
|
356
|
+
onPanStart: ve,
|
|
357
|
+
onPan: de,
|
|
358
|
+
onPanEnd: Y,
|
|
359
|
+
onTouchmove: le
|
|
360
|
+
}, {
|
|
361
|
+
default: E(() => [
|
|
362
|
+
te(t.$slots, "footer", {}, void 0, !0)
|
|
363
|
+
]),
|
|
364
|
+
_: 3
|
|
365
|
+
}, 512)
|
|
366
|
+
]),
|
|
367
|
+
_: 3
|
|
368
|
+
}, 8, ["exit", "style", "data-vsbs-shadow", "data-vsbs-sheet-show"])) : ce("", !0)
|
|
369
|
+
]),
|
|
370
|
+
_: 3
|
|
371
|
+
})
|
|
292
372
|
])
|
|
293
373
|
]));
|
|
294
374
|
}
|
|
295
|
-
}),
|
|
296
|
-
const
|
|
297
|
-
for (const [e,
|
|
298
|
-
|
|
299
|
-
return
|
|
300
|
-
},
|
|
375
|
+
}), je = (n, a) => {
|
|
376
|
+
const o = n.__vccOpts || n;
|
|
377
|
+
for (const [e, v] of a)
|
|
378
|
+
o[e] = v;
|
|
379
|
+
return o;
|
|
380
|
+
}, Ke = /* @__PURE__ */ je(ze, [["__scopeId", "data-v-92db83a2"]]);
|
|
301
381
|
export {
|
|
302
|
-
|
|
382
|
+
Ke as default
|
|
303
383
|
};
|
package/dist/style.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
[data-vsbs-container][data-v-
|
|
1
|
+
[data-vsbs-container][data-v-92db83a2]{position:fixed;top:0;right:0;bottom:0;left:0;overflow:hidden;pointer-events:none;z-index:9999;visibility:visible}[data-vsbs-backdrop][data-v-92db83a2]{background-color:var(--vsbs-backdrop-bg, rgba(0, 0, 0, .5));top:0;right:0;bottom:0;left:0;pointer-events:auto;position:fixed;-webkit-user-select:none;user-select:none;will-change:opacity;z-index:1}[data-vsbs-shadow=true][data-v-92db83a2]:before{content:"";z-index:-1;position:absolute;top:0;height:100lvh;width:100%;border-radius:var(--vsbs-border-radius, 16px);box-shadow:0 -5px 60px 0 var(--vsbs-shadow-color, rgba(89, 89, 89, .2))}[data-vsbs-sheet][data-v-92db83a2]{background-color:var(--vsbs-background, #fff);border-top-left-radius:var(--vsbs-border-radius, 16px);border-top-right-radius:var(--vsbs-border-radius, 16px);bottom:0;display:flex;flex-direction:column;left:0;margin-left:auto;margin-right:auto;max-height:inherit;max-width:var(--vsbs-max-width, 640px);pointer-events:all;position:fixed;right:0;width:100%;will-change:height;z-index:2}[data-vsbs-sheet-show=true][data-v-92db83a2]{visibility:visible}[data-vsbs-header][data-v-92db83a2]{box-shadow:0 1px 0 var(--vsbs-border-color, rgba(46, 59, 66, .125));flex-shrink:0;padding:20px var(--vsbs-padding-x, 16px) 8px;-webkit-user-select:none;user-select:none;z-index:3}[data-vsbs-header][data-v-92db83a2]:before{background-color:var(--vsbs-handle-background, rgba(0, 0, 0, .28));border-radius:2px;content:"";display:block;height:4px;left:50%;position:absolute;top:8px;transform:translate(-50%);width:36px}[data-vsbs-header][data-v-92db83a2]:empty{box-shadow:none;padding:14px var(--vsbs-padding-x, 16px) 10px}[data-vsbs-footer][data-v-92db83a2]{box-shadow:0 -1px 0 var(--vsbs-border-color, rgba(46, 59, 66, .125));flex-grow:0;flex-shrink:0;padding:16px var(--vsbs-padding-x, 16px);-webkit-user-select:none;user-select:none}[data-vsbs-footer][data-v-92db83a2]:empty{display:none}[data-vsbs-scroll][data-v-92db83a2]{flex-grow:1;overflow-y:auto;overscroll-behavior:contain}[data-vsbs-content-wrapper][data-v-92db83a2]{height:100%}[data-vsbs-content][data-v-92db83a2]{display:grid;padding:8px var(--vsbs-padding-x, 16px);-webkit-user-select:none;user-select:none}
|
package/dist/types.d.ts
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function heightPercentToPixels(heightStr: string, windowHeight: number): number;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function rubberbandIfOutOfBounds(position: number, min: number, max: number, constant?: number): number;
|
package/package.json
CHANGED
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"url": "https://github.com/megaarmos/vue-spring-bottom-sheet/issues"
|
|
33
33
|
},
|
|
34
34
|
"private": false,
|
|
35
|
-
"version": "
|
|
35
|
+
"version": "2.0.0",
|
|
36
36
|
"type": "module",
|
|
37
37
|
"exports": {
|
|
38
38
|
".": {
|
|
@@ -48,40 +48,37 @@
|
|
|
48
48
|
"types": "dist/index.d.ts",
|
|
49
49
|
"scripts": {
|
|
50
50
|
"build": "vue-tsc -b && vite build",
|
|
51
|
-
"
|
|
51
|
+
"dev": "vite build --watch",
|
|
52
52
|
"type-check": "vue-tsc --build",
|
|
53
53
|
"lint": "eslint . --fix",
|
|
54
54
|
"format": "prettier --write src/",
|
|
55
55
|
"release": "npm run build && npm publish --access public"
|
|
56
56
|
},
|
|
57
57
|
"peerDependencies": {
|
|
58
|
-
"@vueuse/gesture": "^2.0.0",
|
|
59
|
-
"@vueuse/motion": "^2.2.6",
|
|
60
58
|
"vue": ">=3.3"
|
|
61
59
|
},
|
|
62
60
|
"dependencies": {
|
|
63
|
-
"@vueuse/core": "^
|
|
64
|
-
"@vueuse/
|
|
65
|
-
"@vueuse/integrations": "^12.5.0",
|
|
66
|
-
"@vueuse/motion": "^2.2.6",
|
|
61
|
+
"@vueuse/core": "^13.0.0",
|
|
62
|
+
"@vueuse/integrations": "^13.0.0",
|
|
67
63
|
"focus-trap": "^7.6.4",
|
|
68
|
-
"
|
|
64
|
+
"motion-v": "0.13.1",
|
|
65
|
+
"remeda": "^2.21.2",
|
|
69
66
|
"vue": "^3.5.13"
|
|
70
67
|
},
|
|
71
68
|
"devDependencies": {
|
|
72
|
-
"@types/node": "^22.
|
|
69
|
+
"@types/node": "^22.13.11",
|
|
73
70
|
"@vitejs/plugin-vue": "^5.2.1",
|
|
74
71
|
"@vue/eslint-config-prettier": "^10.2.0",
|
|
75
|
-
"@vue/eslint-config-typescript": "^14.
|
|
72
|
+
"@vue/eslint-config-typescript": "^14.5.0",
|
|
76
73
|
"@vue/tsconfig": "^0.7.0",
|
|
77
74
|
"ajv": "^8.17.1",
|
|
78
|
-
"eslint": "^9.
|
|
79
|
-
"eslint-plugin-vue": "^
|
|
80
|
-
"prettier": "^3.
|
|
75
|
+
"eslint": "^9.23.0",
|
|
76
|
+
"eslint-plugin-vue": "^10.0.0",
|
|
77
|
+
"prettier": "^3.5.3",
|
|
81
78
|
"typescript": "~5.6.3",
|
|
82
|
-
"vite": "^6.
|
|
83
|
-
"vite-plugin-dts": "
|
|
84
|
-
"vue-tsc": "^2.2.
|
|
79
|
+
"vite": "^6.2.2",
|
|
80
|
+
"vite-plugin-dts": "4.5.3",
|
|
81
|
+
"vue-tsc": "^2.2.8"
|
|
85
82
|
},
|
|
86
83
|
"files": [
|
|
87
84
|
"dist",
|
package/LICENSE.txt
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2024 megaarmos
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
package/README.md
DELETED
|
@@ -1,166 +0,0 @@
|
|
|
1
|
-
# Vue Spring Bottom Sheet
|
|
2
|
-
|
|
3
|
-
**vue-spring-bottom-sheet** is built on top of **[@vueuse/gesture]** and **[@vueuse/motion]**.
|
|
4
|
-
|
|
5
|
-
😎 **Modern** and 🚀 **Performant** Bottom Sheet for Vue.js
|
|
6
|
-
|
|
7
|
-
[Demo](https://vue-spring-bottom-sheet.douxcode.com/) 👀
|
|
8
|
-
|
|
9
|
-
|  |  |  |  |
|
|
10
|
-
| :-----------------------------------------------------------------: | :----------------------------------------------------------------: | :--------------------------------------------------------------------: | :------------------------------------------------------------------: |
|
|
11
|
-
|
|
12
|
-
# Installation
|
|
13
|
-
|
|
14
|
-
```
|
|
15
|
-
npm install @douxcode/vue-spring-bottom-sheet
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
```
|
|
19
|
-
bun install @douxcode/vue-spring-bottom-sheet
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
# Getting started
|
|
23
|
-
|
|
24
|
-
## Basic usage
|
|
25
|
-
|
|
26
|
-
```vue
|
|
27
|
-
<script setup>
|
|
28
|
-
import BottomSheet from '@douxcode/vue-spring-bottom-sheet'
|
|
29
|
-
import '@douxcode/vue-spring-bottom-sheet/dist/style.css'
|
|
30
|
-
import { ref } from 'vue'
|
|
31
|
-
|
|
32
|
-
const bottomSheet = ref(null)
|
|
33
|
-
|
|
34
|
-
const open = () => {
|
|
35
|
-
bottomSheet.value.open()
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const close = () => {
|
|
39
|
-
bottomSheet.value.close()
|
|
40
|
-
}
|
|
41
|
-
</script>
|
|
42
|
-
|
|
43
|
-
<template>
|
|
44
|
-
<BottomSheet ref="bottomSheet"> Your awesome content </BottomSheet>
|
|
45
|
-
</template>
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
## Basic usage `setup` + TS
|
|
49
|
-
|
|
50
|
-
```vue
|
|
51
|
-
<script setup lang="ts">
|
|
52
|
-
import BottomSheet from '@douxcode/vue-spring-bottom-sheet'
|
|
53
|
-
import '@douxcode/vue-spring-bottom-sheet/dist/style.css'
|
|
54
|
-
import { ref } from 'vue'
|
|
55
|
-
|
|
56
|
-
const bottomSheet = ref<InstanceType<typeof BottomSheet>>()
|
|
57
|
-
|
|
58
|
-
const open = () => {
|
|
59
|
-
bottomSheet.value.open()
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
const close = () => {
|
|
63
|
-
bottomSheet.value.close()
|
|
64
|
-
}
|
|
65
|
-
</script>
|
|
66
|
-
|
|
67
|
-
<template>
|
|
68
|
-
<BottomSheet ref="bottomSheet"> Your content </BottomSheet>
|
|
69
|
-
</template>
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
## Usage in Nuxt 3
|
|
73
|
-
|
|
74
|
-
For Nuxt 3, just wrap component in `<ClientOnly>`
|
|
75
|
-
|
|
76
|
-
```vue
|
|
77
|
-
<template>
|
|
78
|
-
<ClientOnly>
|
|
79
|
-
<BottomSheet ref="bottomSheet"> Your awesome content </BottomSheet>
|
|
80
|
-
</ClientOnly>
|
|
81
|
-
</template>
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
## Slots
|
|
85
|
-
|
|
86
|
-
```vue
|
|
87
|
-
<template>
|
|
88
|
-
<BottomSheet ref="bottomSheet">
|
|
89
|
-
<template #header> Header </template>
|
|
90
|
-
<div>Your content</div>
|
|
91
|
-
<template #footer> Footer </template>
|
|
92
|
-
</BottomSheet>
|
|
93
|
-
</template>
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
## CSS Custom Properties
|
|
97
|
-
|
|
98
|
-
```css
|
|
99
|
-
--vsbs-backdrop-bg: rgba(0, 0, 0, 0.5);
|
|
100
|
-
--vsbs-shadow-color: rgba(89, 89, 89, 0.2);
|
|
101
|
-
--vsbs-background: #fff;
|
|
102
|
-
--vsbs-border-radius: 16px;
|
|
103
|
-
--vsbs-max-width: 640px;
|
|
104
|
-
--vsbs-border-color: rgba(46, 59, 66, 0.125);
|
|
105
|
-
--vsbs-padding-x: 16px;
|
|
106
|
-
--vsbs-handle-background: rgba(0, 0, 0, 0.28);
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
## Props
|
|
110
|
-
|
|
111
|
-
### Prop Definitions
|
|
112
|
-
|
|
113
|
-
| Prop | Type | Description | Example |
|
|
114
|
-
| ------------------- | -------- | --------------------------------------------------------------------------------------------------- | -------------------------------- |
|
|
115
|
-
| duration | Number | Defines the duration open and close animations. | `:duration="250"` |
|
|
116
|
-
| snapPoints | Number[] | Defines custom snapping positions for the bottom sheet | `:snapPoints="[300, 600, 900]"` |
|
|
117
|
-
| defaultSnapPoint | Number | Specifies the default snap point. Note that at least one snapPoint must be specified for it to work | `:default-snap-point="600"` |
|
|
118
|
-
| blocking | Boolean | Controls whether the bottom sheet blocks interactions with underlying content | `:blocking="true"` |
|
|
119
|
-
| canSwipeClose | Boolean | Enables or disables swipe gestures for closing the sheet | `:can-swipe-close="true"` |
|
|
120
|
-
| canOverlayClose | Boolean | Allows tapping the overlay to close the sheet | `:can-overlay-close="true"` |
|
|
121
|
-
| expandOnContentDrag | Boolean | Enables expanding the sheet by dragging its content | `:expand-on-content-drag="true"` |
|
|
122
|
-
|
|
123
|
-
### Default Values
|
|
124
|
-
|
|
125
|
-
| Prop | Default |
|
|
126
|
-
| ------------------- | -------------------------- |
|
|
127
|
-
| duration | `250` |
|
|
128
|
-
| snapPoints | `minHeight` |
|
|
129
|
-
| defaultSnapPoint | `minHeight / minSnapPoint` |
|
|
130
|
-
| blocking | `true` |
|
|
131
|
-
| canSwipeClose | `true` |
|
|
132
|
-
| canOverlayClose | `true` |
|
|
133
|
-
| expandOnContentDrag | `true` |
|
|
134
|
-
|
|
135
|
-
## Exposed methods
|
|
136
|
-
|
|
137
|
-
Assuming there is `const bottomSheet = ref()`
|
|
138
|
-
|
|
139
|
-
| Method | Description | Example |
|
|
140
|
-
| ----------- | ------------------------------------ | ------------------------------------ |
|
|
141
|
-
| snapToPoint | Snaps the sheet to a specified point | `bottomSheet.value.snapToPoint(300)` |
|
|
142
|
-
| open | Opens the bottom sheet | `bottomSheet.value.open()` |
|
|
143
|
-
| close | Closes the bottom sheet | `bottomSheet.value.close()` |
|
|
144
|
-
|
|
145
|
-
## Events
|
|
146
|
-
|
|
147
|
-
| Event | Description | Example |
|
|
148
|
-
| ------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------- |
|
|
149
|
-
| min-height | Fires when the minimum height of the sheet changes. Passes the value as an argument. | `@min-height="(n) => {}"` |
|
|
150
|
-
| max-height | Fires when the height of the window changes. Passes the value as an argument. Note that this value is throttled to prevent excessive updates. | `@max-height="(n) => {}"` |
|
|
151
|
-
| dragging-up | Fires when the bottom sheet is being dragged up | `@dragging-up="() => {}"` |
|
|
152
|
-
| dragging-down | Fires when the bottom sheet is being dragged down | `@dragging-down="() => {}"` |
|
|
153
|
-
| opened | Fires when the bottom sheet is opened | `@opened="() => {}"` |
|
|
154
|
-
| closed | Fires when the bottom sheet is closed | `@closed="() => {}"` |
|
|
155
|
-
|
|
156
|
-
## Acknowledgments
|
|
157
|
-
|
|
158
|
-
This project was inspired by the following:
|
|
159
|
-
|
|
160
|
-
- [react-spring-bottom-sheet]: Accessible ♿️, Delightful ✨, & Fast 🚀
|
|
161
|
-
- [@webzlodimir/vue-bottom-sheet]: 🔥 A nice clean and touch-friendly bottom sheet component based on Vue.js and Hammer.js for Vue 3
|
|
162
|
-
|
|
163
|
-
[@vueuse/gesture]: https://gesture.vueuse.org/
|
|
164
|
-
[@vueuse/motion]: https://motion.vueuse.org/
|
|
165
|
-
[react-spring-bottom-sheet]: https://react-spring.bottom-sheet.dev/
|
|
166
|
-
[@webzlodimir/vue-bottom-sheet]: https://github.com/vaban-ru/vue-bottom-sheet
|