@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.
@@ -1,4 +1,4 @@
1
- import { BottomSheetProps } from './types.ts';
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: HTMLDivElement;
11
- sheet: HTMLDivElement;
12
- sheetHeader: HTMLDivElement;
10
+ backdrop: import('vue').ShallowUnwrapRef<{}> | null;
11
+ sheet: import('vue').ShallowUnwrapRef<{}> | null;
12
+ sheetHeader: import('vue').ShallowUnwrapRef<{}> | null;
13
13
  sheetScroll: HTMLDivElement;
14
- sheetContentWrapper: HTMLDivElement;
14
+ sheetContentWrapper: import('vue').ShallowUnwrapRef<{}> | null;
15
15
  sheetContent: HTMLDivElement;
16
- sheetFooter: HTMLDivElement;
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: (snapPoint: number) => void;
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
- minHeight: (minSheetHeight: number) => any;
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
- onMinHeight?: ((minSheetHeight: number) => any) | undefined;
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: HTMLDivElement;
49
- sheet: HTMLDivElement;
50
- sheetHeader: HTMLDivElement;
46
+ backdrop: import('vue').ShallowUnwrapRef<{}> | null;
47
+ sheet: import('vue').ShallowUnwrapRef<{}> | null;
48
+ sheetHeader: import('vue').ShallowUnwrapRef<{}> | null;
51
49
  sheetScroll: HTMLDivElement;
52
- sheetContentWrapper: HTMLDivElement;
50
+ sheetContentWrapper: import('vue').ShallowUnwrapRef<{}> | null;
53
51
  sheetContent: HTMLDivElement;
54
- sheetFooter: HTMLDivElement;
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[]>, height: Ref<number>): {
3
- minSnap: import('vue').ComputedRef<number>;
4
- maxSnap: import('vue').ComputedRef<number>;
5
- snapPoints: Ref<number[], number[]>;
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 { computed as y, defineComponent as ce, useCssVars as fe, ref as g, toRefs as he, watch as ee, nextTick as R, onMounted as ge, openBlock as pe, createBlock as me, Teleport as be, createElementVNode as b, createVNode as ye, Transition as Se, withCtx as we, withDirectives as ke, vShow as Te, renderSlot as z } from "vue";
2
- import { useWindowSize as Ce, useElementBounding as I, useScrollLock as te } from "@vueuse/core";
3
- import { useGesture as N, rubberbandIfOutOfBounds as G } from "@vueuse/gesture";
4
- import { useMotionProperties as De, useMotionTransitions as xe, useMotionControls as Me } from "@vueuse/motion";
5
- import { useFocusTrap as Pe } from "@vueuse/integrations/useFocusTrap";
6
- function _e(o, u, a) {
7
- let e = (n) => o(n, ...u);
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 He(o, u, a) {
11
- let e = o.length - u.length;
12
- if (e === 0) return o(...u);
13
- if (e === 1) return _e(o, u, a);
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 Oe(o, { triggerAt: u = "end", minQuietPeriodMs: a, maxBurstDurationMs: e, minGapMs: n, reducer: c = Be }) {
17
- let s, r, f, S, C = () => {
18
- let v = f;
19
- v !== void 0 && (f = void 0, o(v), n !== void 0 && (r = setTimeout(H, n)));
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(r), r = void 0, s === void 0 && C();
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: (...v) => {
26
- let h = s === void 0 && r === void 0;
27
- if ((u !== "start" || h) && (f = c(f, ...v)), !(s === void 0 && !h)) {
28
- if (a !== void 0 || e !== void 0 || n === void 0) {
29
- clearTimeout(s);
30
- let p = Date.now();
31
- S ?? (S = p);
32
- let W = e === void 0 ? a ?? 0 : Math.min(a ?? e, e - (p - S));
33
- s = setTimeout(w, W);
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
- u !== "end" && h && C();
53
+ a !== "end" && d && x();
36
54
  }
37
55
  }, cancel: () => {
38
- clearTimeout(s), s = void 0, S = void 0, clearTimeout(r), r = void 0, f = void 0;
56
+ clearTimeout(i), i = void 0, g = void 0, clearTimeout(p), p = void 0, f = void 0;
39
57
  }, flush: () => {
40
- w(), H();
58
+ H(), D();
41
59
  }, get isIdle() {
42
- return s === void 0 && r === void 0;
60
+ return i === void 0 && p === void 0;
43
61
  } };
44
62
  }
45
- var Be = () => "";
46
- function $(...o) {
47
- return He(Ee, o);
63
+ var $e = () => "";
64
+ function m(...n) {
65
+ return Re(Ae, n);
48
66
  }
49
- var Ee = (o, { min: u, max: a }) => u !== void 0 && o < u ? u : a !== void 0 && o > a ? a : o;
50
- function Ie(o, u) {
51
- const a = y(() => o.value.sort((s, r) => s - r)), e = y(() => a.value[0]), n = y(() => a.value[a.value.length - 1]), c = y(() => {
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
- const $e = { "data-vsbs-container": "" }, We = ["data-vsbs-shadow", "data-vsbs-sheet-show"], Fe = /* @__PURE__ */ ce({
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
- defaultSnapPoint: {},
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", "minHeight", "maxHeight"],
76
- setup(o, { expose: u, emit: a }) {
77
- fe((i) => ({
78
- "02470502": ne.value,
79
- "3c3cbcbe": ue.value
80
- }));
81
- const e = o, n = a, c = g(null), s = g(null), r = g(null), f = g(null), S = g(null), C = g(null), H = g(null), w = g(!1), v = g(e.expandOnContentDrag), { height: h } = Ce(), { height: p } = I(c), { height: W } = I(s), { height: ae } = I(r), { height: oe } = I(C), Q = Pe([c, H], {
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: () => c.value || document.body
84
- }), k = y(
85
- () => Math.ceil(oe.value + W.value + ae.value)
86
- ), ne = y(() => `visibility ${e.duration}ms ease-in-out`), ue = y(() => `opacity ${e.duration}ms ease-in-out`), { motionProperties: D } = De(c), { push: x, stop: le, motionValues: O } = xe(), { set: M, stop: j } = Me(
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 q(i) {
124
- v.value && i.preventDefault();
122
+ function ue(t) {
123
+ r.value && t.preventDefault();
125
124
  }
126
- const X = (i) => {
127
- t.value = i, x("height", t.value, D, {
128
- type: "tween",
129
- easings: "easeInOut",
130
- bounce: 0,
131
- duration: e.duration
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
- }, J = ({
134
- delta: [i, d],
135
- direction: [B, m]
136
- }) => {
137
- c.value && (l.value <= 0 && (t.value -= d), t.value <= P.value && (t.value = P.value, l.value += d, M({
138
- y: e.canSwipeClose ? $(l.value, { min: 0 }) : $(G(l.value, -p.value, 0, 0.5), { min: 0 })
139
- })), M({
140
- height: $(G(t.value, 0, _.value, 0.25), {
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: h.value
195
+ max: d.value
143
196
  })
144
- }), m > 0 ? n("dragging-down") : m < 0 && n("dragging-up"));
145
- }, A = () => {
146
- L.value = !1, V.value = !1, l.value = e.canSwipeClose ? [0, t.value].reduce(
147
- (i, d) => Math.abs(d - l.value) < Math.abs(i - l.value) ? d : i
148
- ) : 0, x("y", l.value, D, {
149
- type: "tween",
150
- easings: "easeInOut",
151
- bounce: 0,
152
- duration: e.duration
153
- }), l.value === t.value && (l.value = 0, E()), t.value = Math.min(T.value[F.value], h.value), x("height", t.value, D, {
154
- type: "tween",
155
- easings: "easeInOut",
156
- bounce: 0,
157
- duration: e.duration
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
- }, Z = () => {
160
- L.value = !0, V.value = !0, t.value = p.value, l.value = O.value.y.get(), j();
161
- };
162
- N(
163
- {
164
- onDragStart: Z,
165
- onDrag: J,
166
- onDragEnd: A
167
- },
168
- {
169
- domTarget: s,
170
- drag: { filterTaps: !0 }
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
- ), N(
173
- {
174
- onDragStart: Z,
175
- onDrag: J,
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
- const de = Oe(
211
- () => {
212
- n("maxHeight", h.value), R(() => {
213
- t.value = T.value[F.value], X(T.value[F.value]);
214
- });
215
- },
216
- { minQuietPeriodMs: 50 }
217
- );
218
- return ee(h, () => {
219
- de.call();
220
- }), ee(k, () => {
221
- n("minHeight", k.value), T.value.length === 1 && R(() => {
222
- T.value[0] === k.value && X(Math.min(k.value, h.value));
223
- });
224
- }), ge(() => {
225
- n("minHeight", k.value), n("maxHeight", h.value), t.value = e.defaultSnapPoint ?? Number(k.value), M({
226
- height: t.value,
227
- y: t.value
228
- }), R(() => {
229
- n("ready");
230
- });
231
- }), u({ open: re, close: E, snapToPoint: X }), (i, d) => (pe(), me(be, { to: "body" }, [
232
- b("div", $e, [
233
- ye(Se, { name: "fade" }, {
234
- default: we(() => [
235
- ke(b("div", {
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: d[0] || (d[0] = (B) => ve())
240
- }, null, 512), [
241
- [Te, w.value && i.blocking]
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
- b("div", {
247
- ref_key: "sheet",
248
- ref: c,
249
- "data-vsbs-shadow": !i.blocking,
250
- "data-vsbs-sheet-show": w.value,
251
- "aria-modal": "true",
252
- "data-vsbs-sheet": "",
253
- tabindex: "-1"
254
- }, [
255
- b("div", {
256
- ref_key: "sheetHeader",
257
- ref: s,
258
- "data-vsbs-header": "",
259
- onTouchmove: U
260
- }, [
261
- z(i.$slots, "header", {}, void 0, !0)
262
- ], 544),
263
- b("div", {
264
- ref_key: "sheetScroll",
265
- ref: f,
266
- "data-vsbs-scroll": "",
267
- onTouchmove: q
268
- }, [
269
- b("div", {
270
- ref_key: "sheetContentWrapper",
271
- ref: S,
272
- "data-vsbs-content-wrapper": ""
273
- }, [
274
- b("div", {
275
- ref_key: "sheetContent",
276
- ref: C,
277
- "data-vsbs-content": ""
278
- }, [
279
- z(i.$slots, "default", {}, void 0, !0)
280
- ], 512)
281
- ], 512)
282
- ], 544),
283
- b("div", {
284
- ref_key: "sheetFooter",
285
- ref: r,
286
- "data-vsbs-footer": "",
287
- onTouchmove: U
288
- }, [
289
- z(i.$slots, "footer", {}, void 0, !0)
290
- ], 544)
291
- ], 8, We)
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
- }), Le = (o, u) => {
296
- const a = o.__vccOpts || o;
297
- for (const [e, n] of u)
298
- a[e] = n;
299
- return a;
300
- }, Ne = /* @__PURE__ */ Le(Fe, [["__scopeId", "data-v-42bd48db"]]);
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
- Ne as default
382
+ Ke as default
303
383
  };
package/dist/style.css CHANGED
@@ -1 +1 @@
1
- [data-vsbs-container][data-v-42bd48db]{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-42bd48db]{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-42bd48db]{box-shadow:0 -5px 60px 0 var(--vsbs-shadow-color, rgba(89, 89, 89, .2))}[data-vsbs-sheet][data-v-42bd48db]{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;transition:var(--02470502);visibility:hidden;width:100%;will-change:height;z-index:2}[data-vsbs-sheet-show=true][data-v-42bd48db]{visibility:visible}[data-vsbs-header][data-v-42bd48db]{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-42bd48db]: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-42bd48db]:empty{box-shadow:none;padding:12px var(--vsbs-padding-x, 16px) 8px}[data-vsbs-footer][data-v-42bd48db]{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-42bd48db]:empty{display:none}[data-vsbs-scroll][data-v-42bd48db]{flex-grow:1;overflow-y:auto;overscroll-behavior:contain}[data-vsbs-content-wrapper][data-v-42bd48db]{height:100%}[data-vsbs-content][data-v-42bd48db]{display:grid;padding:1vh var(--vsbs-padding-x, 16px);-webkit-user-select:none;user-select:none}.fade-enter-active[data-v-42bd48db],.fade-leave-active[data-v-42bd48db]{transition:var(--3c3cbcbe)}.fade-enter-from[data-v-42bd48db],.fade-leave-to[data-v-42bd48db]{opacity:0}
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
@@ -1,7 +1,7 @@
1
1
  export interface BottomSheetProps {
2
2
  duration?: number;
3
- snapPoints?: number[];
4
- defaultSnapPoint?: number;
3
+ snapPoints?: Array<number | `${number}%`>;
4
+ initialSnapPoint?: number;
5
5
  blocking?: boolean;
6
6
  canSwipeClose?: boolean;
7
7
  canBackdropClose?: boolean;
@@ -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": "1.2.7",
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
- "build:watch": "vite build --watch",
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": "^12.5.0",
64
- "@vueuse/gesture": "^2.0.0",
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
- "remeda": "^2.20.0",
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.10.10",
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.3.0",
72
+ "@vue/eslint-config-typescript": "^14.5.0",
76
73
  "@vue/tsconfig": "^0.7.0",
77
74
  "ajv": "^8.17.1",
78
- "eslint": "^9.19.0",
79
- "eslint-plugin-vue": "^9.32.0",
80
- "prettier": "^3.4.2",
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.0.11",
83
- "vite-plugin-dts": "^4.5.0",
84
- "vue-tsc": "^2.2.0"
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
- | ![](https://vue-spring-bottom-sheet.douxcode.com/example_basic.png) | ![](https://vue-spring-bottom-sheet.douxcode.com/example_snap.png) | ![](https://vue-spring-bottom-sheet.douxcode.com/example_blocking.png) | ![](https://vue-spring-bottom-sheet.douxcode.com/example_sticky.png) |
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