@maas/vue-equipment 0.14.3 → 0.15.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/nuxt/module.json +1 -1
- package/dist/plugins/MagicDrawer/src/components/MagicDrawer.vue +89 -33
- package/dist/plugins/MagicDrawer/src/composables/private/useDrawerCallback.d.ts +1 -0
- package/dist/plugins/MagicDrawer/src/composables/private/useDrawerCallback.mjs +3 -1
- package/dist/plugins/MagicDrawer/src/composables/private/useDrawerDrag.d.ts +6 -0
- package/dist/plugins/MagicDrawer/src/composables/private/useDrawerDrag.mjs +194 -43
- package/dist/plugins/MagicDrawer/src/composables/private/useDrawerSnap.d.ts +22 -0
- package/dist/plugins/MagicDrawer/src/composables/private/useDrawerSnap.mjs +135 -0
- package/dist/plugins/MagicDrawer/src/types/index.d.ts +8 -0
- package/dist/plugins/MagicDrawer/src/utils/defaultOptions.mjs +9 -2
- package/dist/plugins/MagicModal/src/components/MagicModal.vue +6 -0
- package/dist/plugins/MagicScroll/src/components/MagicScrollMotion.vue +1 -1
- package/dist/utils/index.js +13 -18
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/index.mjs +13 -18
- package/dist/utils/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/nuxt/module.json
CHANGED
|
@@ -19,19 +19,20 @@
|
|
|
19
19
|
>
|
|
20
20
|
<transition
|
|
21
21
|
v-if="mappedOptions.backdrop || !!$slots.backdrop"
|
|
22
|
-
:name="
|
|
22
|
+
:name="backdropTransition"
|
|
23
23
|
>
|
|
24
24
|
<div
|
|
25
25
|
v-show="innerActive"
|
|
26
26
|
class="magic-drawer__backdrop"
|
|
27
|
-
@click.self="
|
|
27
|
+
@click.self="closeIfAllowed"
|
|
28
28
|
>
|
|
29
29
|
<slot name="backdrop" />
|
|
30
30
|
</div>
|
|
31
31
|
</transition>
|
|
32
|
-
|
|
32
|
+
|
|
33
|
+
<div class="magic-drawer__wrapper" ref="wrapperRef">
|
|
33
34
|
<transition
|
|
34
|
-
:name="
|
|
35
|
+
:name="contentTransition"
|
|
35
36
|
@before-leave="onBeforeLeave"
|
|
36
37
|
@leave="onLeave"
|
|
37
38
|
@after-leave="onAfterLeave"
|
|
@@ -39,20 +40,21 @@
|
|
|
39
40
|
@enter="onEnter"
|
|
40
41
|
@after-enter="onAfterEnter"
|
|
41
42
|
>
|
|
42
|
-
<div
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
43
|
+
<div v-show="innerActive" class="magic-drawer__content">
|
|
44
|
+
<div
|
|
45
|
+
ref="elRef"
|
|
46
|
+
class="magic-drawer__drag"
|
|
47
|
+
:style="style"
|
|
48
|
+
@pointerdown="onPointerdown"
|
|
49
|
+
>
|
|
50
|
+
<component
|
|
51
|
+
v-if="component"
|
|
52
|
+
v-bind="props"
|
|
53
|
+
:is="component"
|
|
54
|
+
@close="closeIfAllowed"
|
|
55
|
+
/>
|
|
56
|
+
<slot v-else />
|
|
57
|
+
</div>
|
|
56
58
|
</div>
|
|
57
59
|
</transition>
|
|
58
60
|
</div>
|
|
@@ -65,8 +67,11 @@
|
|
|
65
67
|
import {
|
|
66
68
|
ref,
|
|
67
69
|
watch,
|
|
70
|
+
computed,
|
|
68
71
|
nextTick,
|
|
69
72
|
toValue,
|
|
73
|
+
onBeforeMount,
|
|
74
|
+
onBeforeUnmount,
|
|
70
75
|
type Component,
|
|
71
76
|
type MaybeRef,
|
|
72
77
|
} from 'vue'
|
|
@@ -90,9 +95,9 @@ import '@maas/vue-equipment/utils/css/animations/slide-rtl-out.css'
|
|
|
90
95
|
import '@maas/vue-equipment/utils/css/animations/slide-ttb-out.css'
|
|
91
96
|
import '@maas/vue-equipment/utils/css/animations/slide-btt-out.css'
|
|
92
97
|
|
|
93
|
-
// Prevent
|
|
98
|
+
// Prevent deep merge of certain options
|
|
94
99
|
const customDefu = createDefu((obj, key, value) => {
|
|
95
|
-
if (key === 'keys') {
|
|
100
|
+
if (key === 'keys' || key === 'snapPoints') {
|
|
96
101
|
obj[key] = value
|
|
97
102
|
return true
|
|
98
103
|
}
|
|
@@ -112,17 +117,20 @@ const props = withDefaults(defineProps<MagicDrawerProps>(), {
|
|
|
112
117
|
|
|
113
118
|
const elRef = ref<HTMLDivElement | undefined>(undefined)
|
|
114
119
|
const drawerRef = ref<HTMLElement | undefined>(undefined)
|
|
120
|
+
const wrapperRef = ref<HTMLDivElement | undefined>(undefined)
|
|
115
121
|
const drawerApi = useDrawerApi(props.id, { focusTarget: drawerRef })
|
|
122
|
+
|
|
116
123
|
const mappedOptions: typeof defaultOptions = customDefu(
|
|
117
124
|
props.options,
|
|
118
125
|
defaultOptions
|
|
119
126
|
)
|
|
120
127
|
|
|
121
128
|
const overshoot = ref(0)
|
|
122
|
-
const { position, threshold } = mappedOptions
|
|
129
|
+
const { position, threshold, snapPoints, snapPoint, canClose } = mappedOptions
|
|
123
130
|
|
|
124
131
|
const {
|
|
125
132
|
isActive,
|
|
133
|
+
open,
|
|
126
134
|
close,
|
|
127
135
|
trapFocus,
|
|
128
136
|
releaseFocus,
|
|
@@ -133,16 +141,21 @@ const {
|
|
|
133
141
|
} = drawerApi
|
|
134
142
|
|
|
135
143
|
const { onPointerdown, dragging, style } = useDrawerDrag({
|
|
144
|
+
elRef,
|
|
145
|
+
wrapperRef,
|
|
136
146
|
position,
|
|
137
147
|
threshold,
|
|
138
148
|
overshoot,
|
|
139
|
-
|
|
149
|
+
snapPoints,
|
|
150
|
+
snapPoint,
|
|
151
|
+
canClose,
|
|
140
152
|
close,
|
|
141
153
|
})
|
|
142
154
|
|
|
143
155
|
// Split isActive into two values to animate drawer smoothly
|
|
144
156
|
const innerActive = ref(false)
|
|
145
157
|
const wrapperActive = ref(false)
|
|
158
|
+
const wasActive = ref(false)
|
|
146
159
|
|
|
147
160
|
const {
|
|
148
161
|
onBeforeEnter,
|
|
@@ -161,19 +174,32 @@ const {
|
|
|
161
174
|
trapFocus,
|
|
162
175
|
releaseFocus,
|
|
163
176
|
wrapperActive,
|
|
177
|
+
wasActive,
|
|
164
178
|
})
|
|
165
179
|
|
|
166
|
-
//
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
180
|
+
// Surpress animation on initial mount if the options call for it
|
|
181
|
+
// To achive this, the transition names are set to undefined
|
|
182
|
+
const surpressTransition = computed(() => {
|
|
183
|
+
return (
|
|
184
|
+
mappedOptions.beforeMount.open &&
|
|
185
|
+
!mappedOptions.beforeMount.animate &&
|
|
186
|
+
!wasActive.value
|
|
187
|
+
)
|
|
188
|
+
})
|
|
172
189
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
190
|
+
const backdropTransition = computed(() => {
|
|
191
|
+
return surpressTransition.value
|
|
192
|
+
? undefined
|
|
193
|
+
: mappedOptions.transitions?.backdrop
|
|
194
|
+
})
|
|
195
|
+
|
|
196
|
+
const contentTransition = computed(() => {
|
|
197
|
+
return surpressTransition.value
|
|
198
|
+
? undefined
|
|
199
|
+
: mappedOptions.transitions?.content
|
|
200
|
+
})
|
|
176
201
|
|
|
202
|
+
// Private functions
|
|
177
203
|
function convertToPixels(value: string) {
|
|
178
204
|
const regex = /^(\d*\.?\d+)\s*(rem|px)$/
|
|
179
205
|
|
|
@@ -199,6 +225,23 @@ function convertToPixels(value: string) {
|
|
|
199
225
|
}
|
|
200
226
|
}
|
|
201
227
|
|
|
228
|
+
async function onOpen() {
|
|
229
|
+
wrapperActive.value = true
|
|
230
|
+
await nextTick()
|
|
231
|
+
innerActive.value = true
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function onClose() {
|
|
235
|
+
innerActive.value = false
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// Public functions
|
|
239
|
+
function closeIfAllowed() {
|
|
240
|
+
if (canClose) {
|
|
241
|
+
close()
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
202
245
|
function saveOvershoot() {
|
|
203
246
|
const element = unrefElement(drawerRef)
|
|
204
247
|
const overshootVar = getComputedStyle(element!).getPropertyValue(
|
|
@@ -208,7 +251,8 @@ function saveOvershoot() {
|
|
|
208
251
|
overshoot.value = convertToPixels(overshootVar) || 0
|
|
209
252
|
}
|
|
210
253
|
|
|
211
|
-
|
|
254
|
+
// Lifecycle hooks and listeners
|
|
255
|
+
if (mappedOptions.keys && canClose) {
|
|
212
256
|
for (const key of mappedOptions.keys) {
|
|
213
257
|
onKeyStroke(key, (e) => {
|
|
214
258
|
e.preventDefault()
|
|
@@ -229,8 +273,20 @@ watch(isActive, async (value) => {
|
|
|
229
273
|
watch(innerActive, () => {
|
|
230
274
|
saveOvershoot()
|
|
231
275
|
})
|
|
276
|
+
|
|
277
|
+
onBeforeMount(async () => {
|
|
278
|
+
// Force open
|
|
279
|
+
if (mappedOptions.beforeMount.open) {
|
|
280
|
+
open()
|
|
281
|
+
}
|
|
282
|
+
})
|
|
283
|
+
|
|
284
|
+
// Reset state on unmount
|
|
285
|
+
onBeforeUnmount(() => {
|
|
286
|
+
close()
|
|
287
|
+
})
|
|
232
288
|
</script>
|
|
233
289
|
|
|
234
290
|
<style>
|
|
235
|
-
:root{--magic-drawer-z-index:999;--magic-drawer-justify-content:center;--magic-drawer-align-items:flex-end;--magic-drawer-backdrop-color:rgba(0,0,0,.5);--magic-drawer-backdrop-filter:unset;--magic-drawer-content-overflow-y:auto;--magic-drawer-handle-wrapper-height:2rem;--magic-drawer-handle-width:3rem;--magic-drawer-handle-height:0.375rem;--magic-drawer-handle-color:#d4d4d8;--magic-drawer-handle-border-radius:0.25rem;--magic-drawer-enter-animation:slide-btt-in 300ms ease;--magic-drawer-leave-animation:slide-btt-out 300ms ease;--magic-drawer-drag-overshoot:4rem;--magic-drawer-drag-overshoot-x:0;--magic-drawer-drag-overshoot-y:0}.magic-drawer{align-items:var(--magic-drawer-align-items);background:transparent;border:none;color:inherit;display:flex;height:100%;inset:0;justify-content:var(--magic-drawer-justify-content);padding:0;position:fixed;width:100%;z-index:var(--magic-drawer-z-index)}.magic-drawer.-bottom{--magic-drawer-drag-overshoot-y:var(--magic-drawer-drag-overshoot)}.magic-drawer.-top{--magic-drawer-enter-animation:slide-ttb-in 300ms ease;--magic-drawer-leave-animation:slide-ttb-out 300ms ease;--magic-drawer-align-items:flex-start;--magic-drawer-drag-overshoot-y:calc(var(--magic-drawer-drag-overshoot)*-1)}.magic-drawer.-right{--magic-drawer-enter-animation:slide-rtl-in 300ms ease;--magic-drawer-leave-animation:slide-rtl-out 300ms ease;--magic-drawer-align-items:center;--magic-drawer-justify-content:flex-end;--magic-drawer-drag-overshoot-x:var(--magic-drawer-drag-overshoot)}.magic-drawer.-left{--magic-drawer-enter-animation:slide-ltr-in 300ms ease;--magic-drawer-leave-animation:slide-ltr-out 300ms ease;--magic-drawer-align-items:center;--magic-drawer-justify-content:flex-start;--magic-drawer-drag-overshoot-x:calc(var(--magic-drawer-drag-overshoot)*-1)}.magic-drawer__wrapper{transform:translate(var(--magic-drawer-drag-overshoot-x),var(--magic-drawer-drag-overshoot-y));width:100%}.magic-drawer__content{-webkit-overflow-scrolling:touch;align-items:var(--magic-drawer-align-items);cursor:grab;display:flex;justify-content:var(--magic-drawer-justify-content);
|
|
291
|
+
:root{--magic-drawer-height:75svh;--magic-drawer-z-index:999;--magic-drawer-justify-content:center;--magic-drawer-align-items:flex-end;--magic-drawer-backdrop-color:rgba(0,0,0,.5);--magic-drawer-backdrop-filter:unset;--magic-drawer-content-overflow-y:auto;--magic-drawer-handle-wrapper-height:2rem;--magic-drawer-handle-width:3rem;--magic-drawer-handle-height:0.375rem;--magic-drawer-handle-color:#d4d4d8;--magic-drawer-handle-border-radius:0.25rem;--magic-drawer-enter-animation:slide-btt-in 300ms ease;--magic-drawer-leave-animation:slide-btt-out 300ms ease;--magic-drawer-drag-overshoot:4rem;--magic-drawer-drag-overshoot-x:0;--magic-drawer-drag-overshoot-y:0}.magic-drawer{align-items:var(--magic-drawer-align-items);background:transparent;border:none;color:inherit;display:flex;height:100%;inset:0;justify-content:var(--magic-drawer-justify-content);padding:0;position:fixed;width:100%;z-index:var(--magic-drawer-z-index)}.magic-drawer.-bottom{--magic-drawer-drag-overshoot-y:var(--magic-drawer-drag-overshoot)}.magic-drawer.-top{--magic-drawer-enter-animation:slide-ttb-in 300ms ease;--magic-drawer-leave-animation:slide-ttb-out 300ms ease;--magic-drawer-align-items:flex-start;--magic-drawer-drag-overshoot-y:calc(var(--magic-drawer-drag-overshoot)*-1)}.magic-drawer.-right{--magic-drawer-enter-animation:slide-rtl-in 300ms ease;--magic-drawer-leave-animation:slide-rtl-out 300ms ease;--magic-drawer-align-items:center;--magic-drawer-justify-content:flex-end;--magic-drawer-drag-overshoot-x:var(--magic-drawer-drag-overshoot)}.magic-drawer.-left{--magic-drawer-enter-animation:slide-ltr-in 300ms ease;--magic-drawer-leave-animation:slide-ltr-out 300ms ease;--magic-drawer-align-items:center;--magic-drawer-justify-content:flex-start;--magic-drawer-drag-overshoot-x:calc(var(--magic-drawer-drag-overshoot)*-1)}.magic-drawer__wrapper{height:calc(var(--magic-drawer-height) + var(--magic-drawer-drag-overshoot));pointer-events:none;transform:translate(var(--magic-drawer-drag-overshoot-x),var(--magic-drawer-drag-overshoot-y));width:100%}.magic-drawer__content{height:100%;max-height:100%;position:relative;width:100%}.magic-drawer__drag{-webkit-overflow-scrolling:touch;align-items:var(--magic-drawer-align-items);cursor:grab;display:flex;height:100%;justify-content:var(--magic-drawer-justify-content);overflow-y:var(--magic-drawer-content-overflow-y);pointer-events:auto;position:relative;scroll-behavior:smooth;width:100%}.magic-drawer.-dragging .magic-drawer__content{cursor:grabbing}.magic-drawer__backdrop{-webkit-backdrop-filter:var(--magic-drawer-backdrop-filter);backdrop-filter:var(--magic-drawer-backdrop-filter);background-color:var(--magic-drawer-backdrop-color);bottom:0;height:100%;left:0;position:fixed;right:0;top:0;width:100%;z-index:-1}.magic-drawer--content-enter-active{animation:var(--magic-drawer-enter-animation)}.magic-drawer--content-leave-active{animation:var(--magic-drawer-leave-animation)}.magic-drawer--backdrop-enter-active{animation:fade-in .3s ease}.magic-drawer--backdrop-leave-active{animation:fade-out .3s ease}
|
|
236
292
|
</style>
|
|
@@ -10,6 +10,7 @@ type UseDrawerCallbackArgs = {
|
|
|
10
10
|
trapFocus: () => void;
|
|
11
11
|
releaseFocus: () => void;
|
|
12
12
|
wrapperActive: Ref<boolean>;
|
|
13
|
+
wasActive: Ref<boolean>;
|
|
13
14
|
};
|
|
14
15
|
export declare function useDrawerCallback(args: UseDrawerCallbackArgs): {
|
|
15
16
|
onBeforeEnter: (_el: Element) => void;
|
|
@@ -10,7 +10,8 @@ export function useDrawerCallback(args) {
|
|
|
10
10
|
unlockScroll,
|
|
11
11
|
trapFocus,
|
|
12
12
|
releaseFocus,
|
|
13
|
-
wrapperActive
|
|
13
|
+
wrapperActive,
|
|
14
|
+
wasActive
|
|
14
15
|
} = args;
|
|
15
16
|
function onBeforeEnter(_el) {
|
|
16
17
|
useDrawerEmitter().emit("beforeEnter", toValue(id));
|
|
@@ -30,6 +31,7 @@ export function useDrawerCallback(args) {
|
|
|
30
31
|
await nextTick();
|
|
31
32
|
trapFocus();
|
|
32
33
|
}
|
|
34
|
+
wasActive.value = true;
|
|
33
35
|
}
|
|
34
36
|
function onBeforeLeave(_el) {
|
|
35
37
|
useDrawerEmitter().emit("beforeLeave", toValue(id));
|
|
@@ -2,13 +2,19 @@ import { type MaybeRef } from 'vue';
|
|
|
2
2
|
import { type DefaultOptions } from '../../utils/defaultOptions.js';
|
|
3
3
|
type UseDrawerDragArgs = {
|
|
4
4
|
elRef: MaybeRef<HTMLDivElement | undefined>;
|
|
5
|
+
wrapperRef: MaybeRef<HTMLDivElement | undefined>;
|
|
5
6
|
position: MaybeRef<DefaultOptions['position']>;
|
|
6
7
|
threshold: MaybeRef<DefaultOptions['threshold']>;
|
|
8
|
+
snapPoints: MaybeRef<DefaultOptions['snapPoints']>;
|
|
9
|
+
snapPoint: MaybeRef<DefaultOptions['snapPoint']>;
|
|
10
|
+
canClose: MaybeRef<DefaultOptions['canClose']>;
|
|
7
11
|
overshoot: MaybeRef<number>;
|
|
8
12
|
close: () => void;
|
|
9
13
|
};
|
|
10
14
|
export declare function useDrawerDrag(args: UseDrawerDragArgs): {
|
|
11
15
|
style: import("vue").ComputedRef<string>;
|
|
16
|
+
draggedX: import("vue").Ref<number>;
|
|
17
|
+
draggedY: import("vue").Ref<number>;
|
|
12
18
|
dragging: import("vue").Ref<boolean>;
|
|
13
19
|
onPointerdown: (e: PointerEvent) => void;
|
|
14
20
|
};
|
|
@@ -4,20 +4,46 @@ import {
|
|
|
4
4
|
onMounted,
|
|
5
5
|
watch,
|
|
6
6
|
onBeforeUnmount,
|
|
7
|
-
toValue
|
|
7
|
+
toValue,
|
|
8
|
+
nextTick
|
|
8
9
|
} from "vue";
|
|
9
10
|
import { useEventListener, unrefElement } from "@vueuse/core";
|
|
10
11
|
import { interpolate } from "@maas/vue-equipment/utils";
|
|
11
12
|
import { useDrawerEmitter } from "../useDrawerEmitter.mjs";
|
|
13
|
+
import { useDrawerSnap } from "./useDrawerSnap.mjs";
|
|
12
14
|
export function useDrawerDrag(args) {
|
|
13
|
-
const {
|
|
15
|
+
const {
|
|
16
|
+
elRef,
|
|
17
|
+
wrapperRef,
|
|
18
|
+
snapPoints,
|
|
19
|
+
position,
|
|
20
|
+
overshoot,
|
|
21
|
+
threshold,
|
|
22
|
+
snapPoint,
|
|
23
|
+
canClose,
|
|
24
|
+
close
|
|
25
|
+
} = args;
|
|
26
|
+
const { findClosestSnapPoint, mapSnapPoint, drawerHeight, drawerWidth } = useDrawerSnap({
|
|
27
|
+
wrapperRef,
|
|
28
|
+
snapPoints,
|
|
29
|
+
canClose,
|
|
30
|
+
position,
|
|
31
|
+
overshoot
|
|
32
|
+
});
|
|
14
33
|
const dragStart = ref(void 0);
|
|
15
|
-
const originX = ref(0);
|
|
16
|
-
const originY = ref(0);
|
|
17
34
|
const dragging = ref(false);
|
|
18
35
|
const shouldClose = ref(false);
|
|
36
|
+
const interpolateTo = ref(void 0);
|
|
19
37
|
const elRect = ref(void 0);
|
|
38
|
+
let cancelPointerup = void 0;
|
|
20
39
|
let cancelPointermove = void 0;
|
|
40
|
+
const originX = ref(0);
|
|
41
|
+
const originY = ref(0);
|
|
42
|
+
const snappedY = ref(0);
|
|
43
|
+
const snappedX = ref(0);
|
|
44
|
+
const directionY = ref("absolute");
|
|
45
|
+
const directionX = ref("absolute");
|
|
46
|
+
const hasSnapPoints = computed(() => toValue(snapPoints).length > 1);
|
|
21
47
|
const draggedX = ref(0);
|
|
22
48
|
const draggedY = ref(0);
|
|
23
49
|
const style = computed(
|
|
@@ -26,53 +52,125 @@ export function useDrawerDrag(args) {
|
|
|
26
52
|
function getSizes() {
|
|
27
53
|
elRect.value = unrefElement(elRef)?.getBoundingClientRect();
|
|
28
54
|
}
|
|
29
|
-
function checkPosition() {
|
|
55
|
+
async function checkPosition() {
|
|
30
56
|
switch (position) {
|
|
31
57
|
case "bottom":
|
|
32
|
-
|
|
33
|
-
|
|
58
|
+
const snapPointB = await findClosestSnapPoint({
|
|
59
|
+
draggedX,
|
|
60
|
+
draggedY,
|
|
61
|
+
direction: directionY.value
|
|
62
|
+
});
|
|
63
|
+
if (draggedY.value > toValue(threshold).distance || hasSnapPoints.value) {
|
|
64
|
+
if (snapPointB === drawerHeight.value) {
|
|
65
|
+
shouldClose.value = true;
|
|
66
|
+
} else {
|
|
67
|
+
interpolateTo.value = snapPointB;
|
|
68
|
+
}
|
|
34
69
|
}
|
|
35
70
|
break;
|
|
36
71
|
case "top":
|
|
37
|
-
|
|
38
|
-
|
|
72
|
+
const snapPointT = await findClosestSnapPoint({
|
|
73
|
+
draggedX,
|
|
74
|
+
draggedY,
|
|
75
|
+
direction: directionY.value
|
|
76
|
+
});
|
|
77
|
+
if (draggedY.value < toValue(threshold).distance * -1 || hasSnapPoints.value) {
|
|
78
|
+
if (snapPointT === drawerHeight.value * -1) {
|
|
79
|
+
shouldClose.value = true;
|
|
80
|
+
} else {
|
|
81
|
+
interpolateTo.value = snapPointT;
|
|
82
|
+
}
|
|
39
83
|
}
|
|
40
84
|
break;
|
|
41
85
|
case "right":
|
|
42
|
-
|
|
43
|
-
|
|
86
|
+
const snapPointR = await findClosestSnapPoint({
|
|
87
|
+
draggedX,
|
|
88
|
+
draggedY,
|
|
89
|
+
direction: directionX.value
|
|
90
|
+
});
|
|
91
|
+
if (draggedX.value > toValue(threshold).distance || hasSnapPoints.value) {
|
|
92
|
+
if (snapPointR === drawerWidth.value) {
|
|
93
|
+
shouldClose.value = true;
|
|
94
|
+
} else {
|
|
95
|
+
interpolateTo.value = snapPointR;
|
|
96
|
+
}
|
|
44
97
|
}
|
|
45
98
|
break;
|
|
46
99
|
case "left":
|
|
47
|
-
|
|
48
|
-
|
|
100
|
+
const snapPointL = await findClosestSnapPoint({
|
|
101
|
+
draggedX,
|
|
102
|
+
draggedY,
|
|
103
|
+
direction: directionX.value
|
|
104
|
+
});
|
|
105
|
+
if (draggedX.value < toValue(threshold).distance * -1 || hasSnapPoints.value) {
|
|
106
|
+
if (snapPointL === drawerWidth.value * -1) {
|
|
107
|
+
shouldClose.value = true;
|
|
108
|
+
} else {
|
|
109
|
+
interpolateTo.value = snapPointL;
|
|
110
|
+
}
|
|
49
111
|
}
|
|
50
112
|
break;
|
|
51
113
|
}
|
|
52
114
|
}
|
|
53
|
-
function checkMomentum({ x, y }) {
|
|
115
|
+
async function checkMomentum({ x, y }) {
|
|
54
116
|
const elapsed = Date.now() - dragStart.value.getTime();
|
|
55
117
|
const velocityX = (x - originX.value) / elapsed;
|
|
56
118
|
const velocityY = (y - originY.value) / elapsed;
|
|
57
119
|
switch (position) {
|
|
58
120
|
case "bottom":
|
|
121
|
+
const snapPointB = await findClosestSnapPoint({
|
|
122
|
+
draggedX,
|
|
123
|
+
draggedY,
|
|
124
|
+
direction: directionY.value
|
|
125
|
+
});
|
|
59
126
|
if (velocityY > toValue(threshold).momentum) {
|
|
60
|
-
|
|
127
|
+
if (snapPointB === drawerHeight.value) {
|
|
128
|
+
shouldClose.value = true;
|
|
129
|
+
} else {
|
|
130
|
+
interpolateTo.value = snapPointB;
|
|
131
|
+
}
|
|
61
132
|
}
|
|
62
133
|
break;
|
|
63
134
|
case "top":
|
|
135
|
+
const snapPointT = await findClosestSnapPoint({
|
|
136
|
+
draggedX,
|
|
137
|
+
draggedY,
|
|
138
|
+
direction: directionY.value
|
|
139
|
+
});
|
|
64
140
|
if (velocityY < toValue(threshold).momentum * -1) {
|
|
65
|
-
|
|
141
|
+
if (snapPointT === drawerHeight.value) {
|
|
142
|
+
shouldClose.value = true;
|
|
143
|
+
} else {
|
|
144
|
+
interpolateTo.value = snapPointT;
|
|
145
|
+
}
|
|
66
146
|
}
|
|
67
147
|
break;
|
|
68
148
|
case "right":
|
|
149
|
+
const snapPointR = await findClosestSnapPoint({
|
|
150
|
+
draggedX,
|
|
151
|
+
draggedY,
|
|
152
|
+
direction: directionX.value
|
|
153
|
+
});
|
|
69
154
|
if (velocityX > toValue(threshold).momentum) {
|
|
70
|
-
|
|
155
|
+
if (snapPointR === drawerWidth.value) {
|
|
156
|
+
shouldClose.value = true;
|
|
157
|
+
} else {
|
|
158
|
+
interpolateTo.value = snapPointR;
|
|
159
|
+
}
|
|
71
160
|
}
|
|
72
161
|
break;
|
|
73
162
|
case "left":
|
|
74
|
-
|
|
75
|
-
|
|
163
|
+
const snapPointL = await findClosestSnapPoint({
|
|
164
|
+
draggedX,
|
|
165
|
+
draggedY,
|
|
166
|
+
direction: directionX.value
|
|
167
|
+
});
|
|
168
|
+
if (velocityX > toValue(threshold).momentum) {
|
|
169
|
+
if (snapPointL === drawerWidth.value) {
|
|
170
|
+
shouldClose.value = true;
|
|
171
|
+
} else {
|
|
172
|
+
interpolateTo.value = snapPointL;
|
|
173
|
+
}
|
|
76
174
|
}
|
|
77
175
|
break;
|
|
78
176
|
}
|
|
@@ -99,59 +197,109 @@ export function useDrawerDrag(args) {
|
|
|
99
197
|
function setDragged({ x, y }) {
|
|
100
198
|
switch (position) {
|
|
101
199
|
case "bottom":
|
|
102
|
-
|
|
200
|
+
const newDraggedB = clamp(y - originY.value, 0, toValue(overshoot) * -1);
|
|
201
|
+
directionY.value = newDraggedB < draggedY.value ? "below" : "above";
|
|
202
|
+
draggedY.value = newDraggedB;
|
|
103
203
|
break;
|
|
104
204
|
case "top":
|
|
105
|
-
|
|
205
|
+
const newDraggedT = clamp(y - originY.value, 0, toValue(overshoot));
|
|
206
|
+
directionY.value = newDraggedT < draggedY.value ? "below" : "above";
|
|
207
|
+
draggedY.value = newDraggedT;
|
|
106
208
|
break;
|
|
107
209
|
case "right":
|
|
108
|
-
|
|
210
|
+
const newDraggedR = clamp(x - originX.value, 0, toValue(overshoot) * -1);
|
|
211
|
+
directionX.value = newDraggedR < draggedX.value ? "below" : "above";
|
|
212
|
+
draggedX.value = newDraggedR;
|
|
109
213
|
break;
|
|
110
214
|
case "left":
|
|
111
|
-
|
|
215
|
+
const newDraggedL = clamp(x - originX.value, 0, toValue(overshoot));
|
|
216
|
+
directionX.value = newDraggedL < draggedX.value ? "below" : "above";
|
|
217
|
+
draggedX.value = newDraggedL;
|
|
218
|
+
break;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
async function setInitial() {
|
|
222
|
+
await nextTick();
|
|
223
|
+
switch (position) {
|
|
224
|
+
case "top":
|
|
225
|
+
case "bottom":
|
|
226
|
+
draggedY.value = await findClosestSnapPoint({
|
|
227
|
+
draggedX,
|
|
228
|
+
draggedY: mapSnapPoint(toValue(snapPoint)) || 0
|
|
229
|
+
}) || 0;
|
|
230
|
+
break;
|
|
231
|
+
case "left":
|
|
232
|
+
case "right":
|
|
233
|
+
draggedX.value = await findClosestSnapPoint({
|
|
234
|
+
draggedX: mapSnapPoint(toValue(snapPoint)) || 0,
|
|
235
|
+
draggedY
|
|
236
|
+
}) || 0;
|
|
112
237
|
break;
|
|
113
238
|
}
|
|
114
239
|
}
|
|
115
240
|
function resetStateAndListeners() {
|
|
116
241
|
dragging.value = false;
|
|
117
242
|
shouldClose.value = false;
|
|
243
|
+
interpolateTo.value = void 0;
|
|
244
|
+
cancelPointerup?.();
|
|
118
245
|
cancelPointermove?.();
|
|
119
246
|
}
|
|
120
247
|
function resetDragged() {
|
|
121
248
|
draggedX.value = 0;
|
|
122
249
|
draggedY.value = 0;
|
|
123
250
|
}
|
|
251
|
+
function resetSnapped() {
|
|
252
|
+
snappedX.value = 0;
|
|
253
|
+
snappedY.value = 0;
|
|
254
|
+
}
|
|
124
255
|
function emitterCallback(event, _payload) {
|
|
125
256
|
if (event === "afterLeave") {
|
|
126
257
|
resetDragged();
|
|
258
|
+
resetSnapped();
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
async function interpolateDragged(target) {
|
|
262
|
+
switch (position) {
|
|
263
|
+
case "bottom":
|
|
264
|
+
case "top":
|
|
265
|
+
snappedY.value = target;
|
|
266
|
+
interpolate({
|
|
267
|
+
from: draggedY.value,
|
|
268
|
+
to: target,
|
|
269
|
+
duration: 300,
|
|
270
|
+
callback: (value) => {
|
|
271
|
+
draggedY.value = value;
|
|
272
|
+
}
|
|
273
|
+
});
|
|
274
|
+
break;
|
|
275
|
+
case "right":
|
|
276
|
+
case "left":
|
|
277
|
+
snappedX.value = target;
|
|
278
|
+
interpolate({
|
|
279
|
+
from: draggedX.value,
|
|
280
|
+
to: target,
|
|
281
|
+
duration: 300,
|
|
282
|
+
callback: (value) => {
|
|
283
|
+
draggedX.value = value;
|
|
284
|
+
}
|
|
285
|
+
});
|
|
286
|
+
break;
|
|
127
287
|
}
|
|
128
288
|
}
|
|
129
289
|
function onPointerup(e) {
|
|
130
290
|
if (shouldClose.value) {
|
|
131
291
|
close();
|
|
292
|
+
} else if (interpolateTo.value || interpolateTo.value === 0) {
|
|
293
|
+
interpolateDragged(interpolateTo.value);
|
|
132
294
|
} else {
|
|
133
295
|
switch (position) {
|
|
134
296
|
case "bottom":
|
|
135
297
|
case "top":
|
|
136
|
-
|
|
137
|
-
from: draggedY.value,
|
|
138
|
-
to: 0,
|
|
139
|
-
duration: 50,
|
|
140
|
-
callback: (value) => {
|
|
141
|
-
draggedY.value = value;
|
|
142
|
-
}
|
|
143
|
-
});
|
|
298
|
+
interpolateDragged(snappedY.value);
|
|
144
299
|
break;
|
|
145
300
|
case "right":
|
|
146
301
|
case "left":
|
|
147
|
-
|
|
148
|
-
from: draggedX.value,
|
|
149
|
-
to: 0,
|
|
150
|
-
duration: 50,
|
|
151
|
-
callback: (value) => {
|
|
152
|
-
draggedX.value = value;
|
|
153
|
-
}
|
|
154
|
-
});
|
|
302
|
+
interpolateDragged(snappedX.value);
|
|
155
303
|
break;
|
|
156
304
|
}
|
|
157
305
|
}
|
|
@@ -173,10 +321,10 @@ export function useDrawerDrag(args) {
|
|
|
173
321
|
}
|
|
174
322
|
;
|
|
175
323
|
e.target.setPointerCapture(e.pointerId);
|
|
176
|
-
useEventListener(document, "pointerup", onPointerup);
|
|
324
|
+
cancelPointerup = useEventListener(document, "pointerup", onPointerup);
|
|
177
325
|
cancelPointermove = useEventListener(document, "pointermove", onPointermove);
|
|
178
|
-
originX.value = e.screenX;
|
|
179
|
-
originY.value = e.screenY;
|
|
326
|
+
originX.value = e.screenX - draggedX.value;
|
|
327
|
+
originY.value = e.screenY - draggedY.value;
|
|
180
328
|
dragStart.value = /* @__PURE__ */ new Date();
|
|
181
329
|
onPointermove(e);
|
|
182
330
|
e.preventDefault();
|
|
@@ -186,9 +334,10 @@ export function useDrawerDrag(args) {
|
|
|
186
334
|
useDrawerEmitter().on("*", emitterCallback);
|
|
187
335
|
});
|
|
188
336
|
watch(
|
|
189
|
-
() => unrefElement(elRef),
|
|
337
|
+
() => [unrefElement(elRef), unrefElement(wrapperRef)],
|
|
190
338
|
() => {
|
|
191
339
|
getSizes();
|
|
340
|
+
setInitial();
|
|
192
341
|
}
|
|
193
342
|
);
|
|
194
343
|
onBeforeUnmount(() => {
|
|
@@ -196,6 +345,8 @@ export function useDrawerDrag(args) {
|
|
|
196
345
|
});
|
|
197
346
|
return {
|
|
198
347
|
style,
|
|
348
|
+
draggedX,
|
|
349
|
+
draggedY,
|
|
199
350
|
dragging,
|
|
200
351
|
onPointerdown
|
|
201
352
|
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type MaybeRef } from 'vue';
|
|
2
|
+
import { type DefaultOptions } from '../../utils/defaultOptions.js';
|
|
3
|
+
import { type SnapPoint } from '../../types.js';
|
|
4
|
+
type UseDrawerSnapArgs = {
|
|
5
|
+
wrapperRef: MaybeRef<HTMLDivElement | undefined>;
|
|
6
|
+
position: MaybeRef<DefaultOptions['position']>;
|
|
7
|
+
snapPoints: MaybeRef<DefaultOptions['snapPoints']>;
|
|
8
|
+
canClose: MaybeRef<DefaultOptions['canClose']>;
|
|
9
|
+
overshoot: MaybeRef<number>;
|
|
10
|
+
};
|
|
11
|
+
type FindClosestSnapPointArgs = {
|
|
12
|
+
draggedY: MaybeRef<number>;
|
|
13
|
+
draggedX: MaybeRef<number>;
|
|
14
|
+
direction?: 'below' | 'above' | 'absolute';
|
|
15
|
+
};
|
|
16
|
+
export declare function useDrawerSnap(args: UseDrawerSnapArgs): {
|
|
17
|
+
findClosestSnapPoint: (args: FindClosestSnapPointArgs) => Promise<number | undefined>;
|
|
18
|
+
mapSnapPoint: (snapPoint: SnapPoint) => number | undefined;
|
|
19
|
+
drawerHeight: import("vue").ComputedRef<number>;
|
|
20
|
+
drawerWidth: import("vue").ComputedRef<number>;
|
|
21
|
+
};
|
|
22
|
+
export {};
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { ref, computed, toValue, nextTick } from "vue";
|
|
2
|
+
import { unrefElement } from "@vueuse/core";
|
|
3
|
+
import { mapValue } from "@maas/vue-equipment/utils";
|
|
4
|
+
export function useDrawerSnap(args) {
|
|
5
|
+
const { snapPoints, position, wrapperRef, overshoot, canClose } = args;
|
|
6
|
+
const wrapperRect = ref(void 0);
|
|
7
|
+
const mappedSnapPoints = computed(() => {
|
|
8
|
+
const extended = toValue(canClose) ? [...toValue(snapPoints), 0] : toValue(snapPoints);
|
|
9
|
+
const mapped = extended.map((snapPoint) => {
|
|
10
|
+
return mapSnapPoint(snapPoint);
|
|
11
|
+
});
|
|
12
|
+
const filtered = mapped.filter((snapPoint) => !!snapPoint).sort((a, b) => a - b);
|
|
13
|
+
return filtered;
|
|
14
|
+
});
|
|
15
|
+
const drawerHeight = computed(
|
|
16
|
+
() => wrapperRect.value?.height - toValue(overshoot)
|
|
17
|
+
);
|
|
18
|
+
const drawerWidth = computed(
|
|
19
|
+
() => wrapperRect.value?.width - toValue(overshoot)
|
|
20
|
+
);
|
|
21
|
+
async function getSizes() {
|
|
22
|
+
wrapperRect.value = unrefElement(wrapperRef)?.getBoundingClientRect();
|
|
23
|
+
await nextTick();
|
|
24
|
+
}
|
|
25
|
+
function findClosestNumber(args2) {
|
|
26
|
+
const { number, numbers, direction } = args2;
|
|
27
|
+
let filtered = numbers;
|
|
28
|
+
switch (direction) {
|
|
29
|
+
case "above":
|
|
30
|
+
filtered = numbers.filter((num) => num > number);
|
|
31
|
+
break;
|
|
32
|
+
case "below":
|
|
33
|
+
filtered = numbers.filter((num) => num < number);
|
|
34
|
+
break;
|
|
35
|
+
}
|
|
36
|
+
if (filtered.length === 0) {
|
|
37
|
+
switch (direction) {
|
|
38
|
+
case "above":
|
|
39
|
+
return Math.max(...numbers);
|
|
40
|
+
case "below":
|
|
41
|
+
return Math.min(...numbers);
|
|
42
|
+
default:
|
|
43
|
+
return void 0;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
const closestNumber = filtered.reduce(
|
|
47
|
+
(closest, current) => Math.abs(current - number) < Math.abs(closest - number) ? current : closest
|
|
48
|
+
);
|
|
49
|
+
return closestNumber;
|
|
50
|
+
}
|
|
51
|
+
function mapSnapPoint(snapPoint) {
|
|
52
|
+
if (typeof snapPoint === "number") {
|
|
53
|
+
const reversedSnapPoint = mapValue(snapPoint, 0, 1, 1, 0);
|
|
54
|
+
const vh = window.innerHeight;
|
|
55
|
+
const vw = window.innerWidth;
|
|
56
|
+
if (wrapperRect.value === void 0) {
|
|
57
|
+
return void 0;
|
|
58
|
+
}
|
|
59
|
+
switch (position) {
|
|
60
|
+
case "bottom":
|
|
61
|
+
if (reversedSnapPoint === 1)
|
|
62
|
+
return drawerHeight.value;
|
|
63
|
+
else if (reversedSnapPoint === 0)
|
|
64
|
+
return 0;
|
|
65
|
+
else
|
|
66
|
+
return vh * reversedSnapPoint - wrapperRect.value?.top;
|
|
67
|
+
case "top":
|
|
68
|
+
if (reversedSnapPoint === 1)
|
|
69
|
+
return drawerHeight.value * -1;
|
|
70
|
+
else if (reversedSnapPoint === 0)
|
|
71
|
+
return 0;
|
|
72
|
+
else
|
|
73
|
+
return vh * reversedSnapPoint - wrapperRect.value?.bottom;
|
|
74
|
+
case "right":
|
|
75
|
+
if (reversedSnapPoint === 1)
|
|
76
|
+
return drawerWidth.value;
|
|
77
|
+
else if (reversedSnapPoint === 0)
|
|
78
|
+
return 0;
|
|
79
|
+
else
|
|
80
|
+
return vw * reversedSnapPoint - wrapperRect.value?.left;
|
|
81
|
+
case "left":
|
|
82
|
+
if (reversedSnapPoint === 1)
|
|
83
|
+
return drawerWidth.value * -1;
|
|
84
|
+
else if (reversedSnapPoint === 0)
|
|
85
|
+
return 0;
|
|
86
|
+
else
|
|
87
|
+
return vw * reversedSnapPoint - wrapperRect.value?.right;
|
|
88
|
+
default:
|
|
89
|
+
return 0;
|
|
90
|
+
}
|
|
91
|
+
} else {
|
|
92
|
+
const parsedSnapPoint = parseFloat(snapPoint);
|
|
93
|
+
if (drawerHeight.value === void 0 || drawerWidth.value === void 0) {
|
|
94
|
+
return void 0;
|
|
95
|
+
}
|
|
96
|
+
switch (position) {
|
|
97
|
+
case "bottom":
|
|
98
|
+
return drawerHeight.value - parsedSnapPoint;
|
|
99
|
+
case "top":
|
|
100
|
+
return (drawerHeight.value - parsedSnapPoint) * -1;
|
|
101
|
+
case "right":
|
|
102
|
+
return drawerWidth.value - parsedSnapPoint;
|
|
103
|
+
case "left":
|
|
104
|
+
return (drawerWidth.value - parsedSnapPoint) * -1;
|
|
105
|
+
default:
|
|
106
|
+
return parseFloat(snapPoint);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
async function findClosestSnapPoint(args2) {
|
|
111
|
+
const { draggedY, draggedX, direction = "absolute" } = args2;
|
|
112
|
+
await getSizes();
|
|
113
|
+
let closest = 0;
|
|
114
|
+
switch (position) {
|
|
115
|
+
case "bottom":
|
|
116
|
+
case "top":
|
|
117
|
+
closest = findClosestNumber({
|
|
118
|
+
number: toValue(draggedY),
|
|
119
|
+
numbers: mappedSnapPoints.value,
|
|
120
|
+
direction
|
|
121
|
+
});
|
|
122
|
+
break;
|
|
123
|
+
case "right":
|
|
124
|
+
case "left":
|
|
125
|
+
closest = findClosestNumber({
|
|
126
|
+
number: toValue(draggedX),
|
|
127
|
+
numbers: mappedSnapPoints.value,
|
|
128
|
+
direction
|
|
129
|
+
});
|
|
130
|
+
break;
|
|
131
|
+
}
|
|
132
|
+
return closest;
|
|
133
|
+
}
|
|
134
|
+
return { findClosestSnapPoint, mapSnapPoint, drawerHeight, drawerWidth };
|
|
135
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export type SnapPoint = number | `${string}px`;
|
|
1
2
|
export type DrawerOptions = {
|
|
2
3
|
position?: 'top' | 'right' | 'bottom' | 'left';
|
|
3
4
|
backdrop?: boolean;
|
|
@@ -18,6 +19,13 @@ export type DrawerOptions = {
|
|
|
18
19
|
};
|
|
19
20
|
tag?: 'dialog' | 'div';
|
|
20
21
|
keys?: string[] | false;
|
|
22
|
+
beforeMount?: {
|
|
23
|
+
open: boolean;
|
|
24
|
+
animate: boolean;
|
|
25
|
+
};
|
|
26
|
+
snapPoints?: SnapPoint[];
|
|
27
|
+
snapPoint?: SnapPoint;
|
|
28
|
+
canClose?: boolean;
|
|
21
29
|
};
|
|
22
30
|
export type DrawerEvents = {
|
|
23
31
|
beforeEnter: string;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const defaultOptions = {
|
|
2
2
|
position: "bottom",
|
|
3
3
|
backdrop: true,
|
|
4
|
-
focusTrap:
|
|
4
|
+
focusTrap: false,
|
|
5
5
|
scrollLock: true,
|
|
6
6
|
scrollLockPadding: true,
|
|
7
7
|
teleport: {
|
|
@@ -17,6 +17,13 @@ const defaultOptions = {
|
|
|
17
17
|
momentum: 1
|
|
18
18
|
},
|
|
19
19
|
tag: "dialog",
|
|
20
|
-
keys: ["Escape"]
|
|
20
|
+
keys: ["Escape"],
|
|
21
|
+
beforeMount: {
|
|
22
|
+
open: false,
|
|
23
|
+
animate: false
|
|
24
|
+
},
|
|
25
|
+
snapPoints: [1],
|
|
26
|
+
snapPoint: 1,
|
|
27
|
+
canClose: true
|
|
21
28
|
};
|
|
22
29
|
export { defaultOptions };
|
|
@@ -60,6 +60,7 @@ import {
|
|
|
60
60
|
watch,
|
|
61
61
|
nextTick,
|
|
62
62
|
toValue,
|
|
63
|
+
onBeforeUnmount,
|
|
63
64
|
type Component,
|
|
64
65
|
type MaybeRef,
|
|
65
66
|
} from 'vue'
|
|
@@ -159,6 +160,11 @@ watch(isActive, async (value) => {
|
|
|
159
160
|
onClose()
|
|
160
161
|
}
|
|
161
162
|
})
|
|
163
|
+
|
|
164
|
+
// Reset state on unmount
|
|
165
|
+
onBeforeUnmount(() => {
|
|
166
|
+
close()
|
|
167
|
+
})
|
|
162
168
|
</script>
|
|
163
169
|
|
|
164
170
|
<style>
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
</template>
|
|
6
6
|
|
|
7
7
|
<script setup lang="ts">
|
|
8
|
-
import { ref, inject, computed, onMounted,
|
|
8
|
+
import { ref, inject, computed, onMounted, watch } from 'vue'
|
|
9
9
|
import { unrefElement } from '@vueuse/core'
|
|
10
10
|
import { animate, type Easing } from 'motion'
|
|
11
11
|
import { ScrollProgressKey } from '../symbols'
|
package/dist/utils/index.js
CHANGED
|
@@ -37,26 +37,21 @@ function clampValue(value, min, max) {
|
|
|
37
37
|
|
|
38
38
|
// src/functions/interpolate.ts
|
|
39
39
|
function interpolate(args) {
|
|
40
|
-
const {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
const stepSize = 1 / steps;
|
|
50
|
-
let currentStep = 0;
|
|
51
|
-
const intervalId = setInterval(() => {
|
|
52
|
-
const progress = currentStep * stepSize;
|
|
53
|
-
const value = from + (to - from) * easing(progress);
|
|
40
|
+
const { from, to, duration, callback, easing = (t) => t * (2 - t) } = args;
|
|
41
|
+
let startTime;
|
|
42
|
+
const speed = 1;
|
|
43
|
+
function animate(timestamp) {
|
|
44
|
+
if (!startTime)
|
|
45
|
+
startTime = timestamp;
|
|
46
|
+
const progress = Math.min(1, (timestamp - startTime) / (duration * speed));
|
|
47
|
+
const easedProgress = easing(progress);
|
|
48
|
+
const value = from + (to - from) * easedProgress;
|
|
54
49
|
callback(value);
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
clearInterval(intervalId);
|
|
50
|
+
if (progress < 1) {
|
|
51
|
+
requestAnimationFrame(animate);
|
|
58
52
|
}
|
|
59
|
-
}
|
|
53
|
+
}
|
|
54
|
+
requestAnimationFrame(animate);
|
|
60
55
|
}
|
|
61
56
|
|
|
62
57
|
// src/functions/isIOS.ts
|
package/dist/utils/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../packages/utils/index.ts","../../packages/utils/src/functions/clampValue.ts","../../packages/utils/src/functions/interpolate.ts","../../packages/utils/src/functions/isIOS.ts","../../packages/utils/src/functions/mapValue.ts","../../packages/utils/src/functions/uuid.ts","../../packages/utils/src/functions/uniq.ts","../../packages/utils/src/functions/slugify.ts"],"sourcesContent":["export * from './src/functions/clampValue'\nexport * from './src/functions/interpolate'\nexport * from './src/functions/isIOS'\nexport * from './src/functions/mapValue'\nexport * from './src/functions/uuid'\nexport * from './src/functions/uniq'\nexport * from './src/functions/slugify'\n\nexport type * from './src/types'\n","export function clampValue(value: number, min: number, max: number) {\n return value <= min ? min : value >= max ? max : value\n}\n","export type InterpolateArgs = {\n from: number\n to: number\n duration: number\n interval?: number\n easing?: (t: number) => number\n callback: (result: number) => void\n}\n\nexport function interpolate(args: InterpolateArgs) {\n const {
|
|
1
|
+
{"version":3,"sources":["../../packages/utils/index.ts","../../packages/utils/src/functions/clampValue.ts","../../packages/utils/src/functions/interpolate.ts","../../packages/utils/src/functions/isIOS.ts","../../packages/utils/src/functions/mapValue.ts","../../packages/utils/src/functions/uuid.ts","../../packages/utils/src/functions/uniq.ts","../../packages/utils/src/functions/slugify.ts"],"sourcesContent":["export * from './src/functions/clampValue'\nexport * from './src/functions/interpolate'\nexport * from './src/functions/isIOS'\nexport * from './src/functions/mapValue'\nexport * from './src/functions/uuid'\nexport * from './src/functions/uniq'\nexport * from './src/functions/slugify'\n\nexport type * from './src/types'\n","export function clampValue(value: number, min: number, max: number) {\n return value <= min ? min : value >= max ? max : value\n}\n","export type InterpolateArgs = {\n from: number\n to: number\n duration: number\n interval?: number\n easing?: (t: number) => number\n callback: (result: number) => void\n}\n\nexport function interpolate(args: InterpolateArgs) {\n const { from, to, duration, callback, easing = (t) => t * (2 - t) } = args\n\n let startTime: number\n const speed = 1\n\n function animate(timestamp: number) {\n if (!startTime) startTime = timestamp\n\n const progress = Math.min(1, (timestamp - startTime) / (duration * speed))\n const easedProgress = easing(progress)\n const value = from + (to - from) * easedProgress\n\n callback(value)\n\n if (progress < 1) {\n requestAnimationFrame(animate)\n }\n }\n\n requestAnimationFrame(animate)\n}\n","export function isIOS() {\n if (typeof window === 'undefined') return false\n return /iPad|iPhone|iPod/.test(navigator?.userAgent)\n}\n","export function mapValue(\n value: number,\n inMin: number,\n inMax: number,\n outMin: number,\n outMax: number,\n) {\n return ((value - inMin) * (outMax - outMin)) / (inMax - inMin) + outMin\n}\n","// This implementation is meant for internal use only.\n// It is only used to generate a unique IDs for the `key` props.\n// It should not replace crypto.randomUUID() or window.crypto.randomUUID().\n\nexport function uuid() {\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'\n .split('')\n .reduce(\n (c, i) =>\n c +\n (i === 'x'\n ? Math.floor(Math.random() * 0xf).toString(16)\n : i === 'y'\n ? Math.floor(Math.random() * 4 + 8).toString(16)\n : i),\n '',\n )\n}\n","export function uniq<T extends any[]>(a: T) {\n return Array.from(new Set(a))\n}\n","export interface SlugifyOptions {\n separator?: string\n trim?: boolean\n remove?: RegExp\n strict?: boolean\n lowercase?: boolean\n}\n\nconst defaultOptions: SlugifyOptions = {\n separator: '-',\n trim: true,\n remove: undefined,\n strict: true,\n lowercase: true,\n}\n\nexport function slugify(string: string, options?: SlugifyOptions): string {\n if (typeof string !== 'string') {\n throw new Error('slugify: string argument expected')\n }\n\n // Merge provided options with default options\n const _options = { ...defaultOptions, ...options }\n\n const charMap: { [key: string]: string } = {}\n\n let slug = string\n .normalize()\n .split('')\n .reduce(function (result, ch) {\n let appendChar = charMap[ch]\n if (appendChar === undefined) appendChar = ch\n if (appendChar === _options?.separator) appendChar = ' '\n return (\n result +\n appendChar.replace(_options?.remove || /[^\\w\\s$*_+~.()'\"!\\-:@]+/g, '')\n )\n }, '')\n\n if (_options.strict) {\n slug = slug.replace(/[^A-Za-z0-9\\s]/g, '')\n }\n\n if (_options.trim) {\n slug = slug.trim()\n }\n\n if (_options.separator) {\n slug = slug.replace(/ +/g, _options.separator)\n }\n\n if (_options.lowercase) {\n slug = slug.toLocaleLowerCase()\n }\n\n return slug\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAO,SAAS,WAAW,OAAe,KAAa,KAAa;AAClE,SAAO,SAAS,MAAM,MAAM,SAAS,MAAM,MAAM;AACnD;;;ACOO,SAAS,YAAY,MAAuB;AACjD,QAAM,EAAE,MAAM,IAAI,UAAU,UAAU,SAAS,CAAC,MAAM,KAAK,IAAI,GAAG,IAAI;AAEtE,MAAI;AACJ,QAAM,QAAQ;AAEd,WAAS,QAAQ,WAAmB;AAClC,QAAI,CAAC;AAAW,kBAAY;AAE5B,UAAM,WAAW,KAAK,IAAI,IAAI,YAAY,cAAc,WAAW,MAAM;AACzE,UAAM,gBAAgB,OAAO,QAAQ;AACrC,UAAM,QAAQ,QAAQ,KAAK,QAAQ;AAEnC,aAAS,KAAK;AAEd,QAAI,WAAW,GAAG;AAChB,4BAAsB,OAAO;AAAA,IAC/B;AAAA,EACF;AAEA,wBAAsB,OAAO;AAC/B;;;AC9BO,SAAS,QAAQ;AACtB,MAAI,OAAO,WAAW;AAAa,WAAO;AAC1C,SAAO,mBAAmB,KAAK,uCAAW,SAAS;AACrD;;;ACHO,SAAS,SACd,OACA,OACA,OACA,QACA,QACA;AACA,UAAS,QAAQ,UAAU,SAAS,WAAY,QAAQ,SAAS;AACnE;;;ACJO,SAAS,OAAO;AACrB,SAAO,uCACJ,MAAM,EAAE,EACR;AAAA,IACC,CAAC,GAAG,MACF,KACC,MAAM,MACH,KAAK,MAAM,KAAK,OAAO,IAAI,EAAG,EAAE,SAAS,EAAE,IAC3C,MAAM,MACN,KAAK,MAAM,KAAK,OAAO,IAAI,IAAI,CAAC,EAAE,SAAS,EAAE,IAC7C;AAAA,IACN;AAAA,EACF;AACJ;;;ACjBO,SAAS,KAAsB,GAAM;AAC1C,SAAO,MAAM,KAAK,IAAI,IAAI,CAAC,CAAC;AAC9B;;;ACMA,IAAM,iBAAiC;AAAA,EACrC,WAAW;AAAA,EACX,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,WAAW;AACb;AAEO,SAAS,QAAQ,QAAgB,SAAkC;AACxE,MAAI,OAAO,WAAW,UAAU;AAC9B,UAAM,IAAI,MAAM,mCAAmC;AAAA,EACrD;AAGA,QAAM,WAAW,EAAE,GAAG,gBAAgB,GAAG,QAAQ;AAEjD,QAAM,UAAqC,CAAC;AAE5C,MAAI,OAAO,OACR,UAAU,EACV,MAAM,EAAE,EACR,OAAO,SAAU,QAAQ,IAAI;AAC5B,QAAI,aAAa,QAAQ,EAAE;AAC3B,QAAI,eAAe;AAAW,mBAAa;AAC3C,QAAI,gBAAe,qCAAU;AAAW,mBAAa;AACrD,WACE,SACA,WAAW,SAAQ,qCAAU,WAAU,4BAA4B,EAAE;AAAA,EAEzE,GAAG,EAAE;AAEP,MAAI,SAAS,QAAQ;AACnB,WAAO,KAAK,QAAQ,mBAAmB,EAAE;AAAA,EAC3C;AAEA,MAAI,SAAS,MAAM;AACjB,WAAO,KAAK,KAAK;AAAA,EACnB;AAEA,MAAI,SAAS,WAAW;AACtB,WAAO,KAAK,QAAQ,OAAO,SAAS,SAAS;AAAA,EAC/C;AAEA,MAAI,SAAS,WAAW;AACtB,WAAO,KAAK,kBAAkB;AAAA,EAChC;AAEA,SAAO;AACT;","names":[]}
|
package/dist/utils/index.mjs
CHANGED
|
@@ -5,26 +5,21 @@ function clampValue(value, min, max) {
|
|
|
5
5
|
|
|
6
6
|
// src/functions/interpolate.ts
|
|
7
7
|
function interpolate(args) {
|
|
8
|
-
const {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
const stepSize = 1 / steps;
|
|
18
|
-
let currentStep = 0;
|
|
19
|
-
const intervalId = setInterval(() => {
|
|
20
|
-
const progress = currentStep * stepSize;
|
|
21
|
-
const value = from + (to - from) * easing(progress);
|
|
8
|
+
const { from, to, duration, callback, easing = (t) => t * (2 - t) } = args;
|
|
9
|
+
let startTime;
|
|
10
|
+
const speed = 1;
|
|
11
|
+
function animate(timestamp) {
|
|
12
|
+
if (!startTime)
|
|
13
|
+
startTime = timestamp;
|
|
14
|
+
const progress = Math.min(1, (timestamp - startTime) / (duration * speed));
|
|
15
|
+
const easedProgress = easing(progress);
|
|
16
|
+
const value = from + (to - from) * easedProgress;
|
|
22
17
|
callback(value);
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
clearInterval(intervalId);
|
|
18
|
+
if (progress < 1) {
|
|
19
|
+
requestAnimationFrame(animate);
|
|
26
20
|
}
|
|
27
|
-
}
|
|
21
|
+
}
|
|
22
|
+
requestAnimationFrame(animate);
|
|
28
23
|
}
|
|
29
24
|
|
|
30
25
|
// src/functions/isIOS.ts
|
package/dist/utils/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../packages/utils/src/functions/clampValue.ts","../../packages/utils/src/functions/interpolate.ts","../../packages/utils/src/functions/isIOS.ts","../../packages/utils/src/functions/mapValue.ts","../../packages/utils/src/functions/uuid.ts","../../packages/utils/src/functions/uniq.ts","../../packages/utils/src/functions/slugify.ts"],"sourcesContent":["export function clampValue(value: number, min: number, max: number) {\n return value <= min ? min : value >= max ? max : value\n}\n","export type InterpolateArgs = {\n from: number\n to: number\n duration: number\n interval?: number\n easing?: (t: number) => number\n callback: (result: number) => void\n}\n\nexport function interpolate(args: InterpolateArgs) {\n const {
|
|
1
|
+
{"version":3,"sources":["../../packages/utils/src/functions/clampValue.ts","../../packages/utils/src/functions/interpolate.ts","../../packages/utils/src/functions/isIOS.ts","../../packages/utils/src/functions/mapValue.ts","../../packages/utils/src/functions/uuid.ts","../../packages/utils/src/functions/uniq.ts","../../packages/utils/src/functions/slugify.ts"],"sourcesContent":["export function clampValue(value: number, min: number, max: number) {\n return value <= min ? min : value >= max ? max : value\n}\n","export type InterpolateArgs = {\n from: number\n to: number\n duration: number\n interval?: number\n easing?: (t: number) => number\n callback: (result: number) => void\n}\n\nexport function interpolate(args: InterpolateArgs) {\n const { from, to, duration, callback, easing = (t) => t * (2 - t) } = args\n\n let startTime: number\n const speed = 1\n\n function animate(timestamp: number) {\n if (!startTime) startTime = timestamp\n\n const progress = Math.min(1, (timestamp - startTime) / (duration * speed))\n const easedProgress = easing(progress)\n const value = from + (to - from) * easedProgress\n\n callback(value)\n\n if (progress < 1) {\n requestAnimationFrame(animate)\n }\n }\n\n requestAnimationFrame(animate)\n}\n","export function isIOS() {\n if (typeof window === 'undefined') return false\n return /iPad|iPhone|iPod/.test(navigator?.userAgent)\n}\n","export function mapValue(\n value: number,\n inMin: number,\n inMax: number,\n outMin: number,\n outMax: number,\n) {\n return ((value - inMin) * (outMax - outMin)) / (inMax - inMin) + outMin\n}\n","// This implementation is meant for internal use only.\n// It is only used to generate a unique IDs for the `key` props.\n// It should not replace crypto.randomUUID() or window.crypto.randomUUID().\n\nexport function uuid() {\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'\n .split('')\n .reduce(\n (c, i) =>\n c +\n (i === 'x'\n ? Math.floor(Math.random() * 0xf).toString(16)\n : i === 'y'\n ? Math.floor(Math.random() * 4 + 8).toString(16)\n : i),\n '',\n )\n}\n","export function uniq<T extends any[]>(a: T) {\n return Array.from(new Set(a))\n}\n","export interface SlugifyOptions {\n separator?: string\n trim?: boolean\n remove?: RegExp\n strict?: boolean\n lowercase?: boolean\n}\n\nconst defaultOptions: SlugifyOptions = {\n separator: '-',\n trim: true,\n remove: undefined,\n strict: true,\n lowercase: true,\n}\n\nexport function slugify(string: string, options?: SlugifyOptions): string {\n if (typeof string !== 'string') {\n throw new Error('slugify: string argument expected')\n }\n\n // Merge provided options with default options\n const _options = { ...defaultOptions, ...options }\n\n const charMap: { [key: string]: string } = {}\n\n let slug = string\n .normalize()\n .split('')\n .reduce(function (result, ch) {\n let appendChar = charMap[ch]\n if (appendChar === undefined) appendChar = ch\n if (appendChar === _options?.separator) appendChar = ' '\n return (\n result +\n appendChar.replace(_options?.remove || /[^\\w\\s$*_+~.()'\"!\\-:@]+/g, '')\n )\n }, '')\n\n if (_options.strict) {\n slug = slug.replace(/[^A-Za-z0-9\\s]/g, '')\n }\n\n if (_options.trim) {\n slug = slug.trim()\n }\n\n if (_options.separator) {\n slug = slug.replace(/ +/g, _options.separator)\n }\n\n if (_options.lowercase) {\n slug = slug.toLocaleLowerCase()\n }\n\n return slug\n}\n"],"mappings":";AAAO,SAAS,WAAW,OAAe,KAAa,KAAa;AAClE,SAAO,SAAS,MAAM,MAAM,SAAS,MAAM,MAAM;AACnD;;;ACOO,SAAS,YAAY,MAAuB;AACjD,QAAM,EAAE,MAAM,IAAI,UAAU,UAAU,SAAS,CAAC,MAAM,KAAK,IAAI,GAAG,IAAI;AAEtE,MAAI;AACJ,QAAM,QAAQ;AAEd,WAAS,QAAQ,WAAmB;AAClC,QAAI,CAAC;AAAW,kBAAY;AAE5B,UAAM,WAAW,KAAK,IAAI,IAAI,YAAY,cAAc,WAAW,MAAM;AACzE,UAAM,gBAAgB,OAAO,QAAQ;AACrC,UAAM,QAAQ,QAAQ,KAAK,QAAQ;AAEnC,aAAS,KAAK;AAEd,QAAI,WAAW,GAAG;AAChB,4BAAsB,OAAO;AAAA,IAC/B;AAAA,EACF;AAEA,wBAAsB,OAAO;AAC/B;;;AC9BO,SAAS,QAAQ;AACtB,MAAI,OAAO,WAAW;AAAa,WAAO;AAC1C,SAAO,mBAAmB,KAAK,uCAAW,SAAS;AACrD;;;ACHO,SAAS,SACd,OACA,OACA,OACA,QACA,QACA;AACA,UAAS,QAAQ,UAAU,SAAS,WAAY,QAAQ,SAAS;AACnE;;;ACJO,SAAS,OAAO;AACrB,SAAO,uCACJ,MAAM,EAAE,EACR;AAAA,IACC,CAAC,GAAG,MACF,KACC,MAAM,MACH,KAAK,MAAM,KAAK,OAAO,IAAI,EAAG,EAAE,SAAS,EAAE,IAC3C,MAAM,MACN,KAAK,MAAM,KAAK,OAAO,IAAI,IAAI,CAAC,EAAE,SAAS,EAAE,IAC7C;AAAA,IACN;AAAA,EACF;AACJ;;;ACjBO,SAAS,KAAsB,GAAM;AAC1C,SAAO,MAAM,KAAK,IAAI,IAAI,CAAC,CAAC;AAC9B;;;ACMA,IAAM,iBAAiC;AAAA,EACrC,WAAW;AAAA,EACX,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,WAAW;AACb;AAEO,SAAS,QAAQ,QAAgB,SAAkC;AACxE,MAAI,OAAO,WAAW,UAAU;AAC9B,UAAM,IAAI,MAAM,mCAAmC;AAAA,EACrD;AAGA,QAAM,WAAW,EAAE,GAAG,gBAAgB,GAAG,QAAQ;AAEjD,QAAM,UAAqC,CAAC;AAE5C,MAAI,OAAO,OACR,UAAU,EACV,MAAM,EAAE,EACR,OAAO,SAAU,QAAQ,IAAI;AAC5B,QAAI,aAAa,QAAQ,EAAE;AAC3B,QAAI,eAAe;AAAW,mBAAa;AAC3C,QAAI,gBAAe,qCAAU;AAAW,mBAAa;AACrD,WACE,SACA,WAAW,SAAQ,qCAAU,WAAU,4BAA4B,EAAE;AAAA,EAEzE,GAAG,EAAE;AAEP,MAAI,SAAS,QAAQ;AACnB,WAAO,KAAK,QAAQ,mBAAmB,EAAE;AAAA,EAC3C;AAEA,MAAI,SAAS,MAAM;AACjB,WAAO,KAAK,KAAK;AAAA,EACnB;AAEA,MAAI,SAAS,WAAW;AACtB,WAAO,KAAK,QAAQ,OAAO,SAAS,SAAS;AAAA,EAC/C;AAEA,MAAI,SAAS,WAAW;AACtB,WAAO,KAAK,kBAAkB;AAAA,EAChC;AAEA,SAAO;AACT;","names":[]}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@maas/vue-equipment",
|
|
3
3
|
"description": "A magic collection of Vue composables, plugins, components and directives",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.15.0",
|
|
5
5
|
"author": "Robin Scholz <https://github.com/robinscholz>, Christoph Jeworutzki <https://github.com/ChristophJeworutzki>",
|
|
6
6
|
"devDependencies": {
|
|
7
7
|
"@antfu/ni": "^0.21.12",
|