@maas/vue-equipment 0.26.5 → 0.27.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.
Files changed (66) hide show
  1. package/dist/composables/index.d.mts +19 -18
  2. package/dist/composables/index.d.ts +19 -18
  3. package/dist/composables/index.js +20 -18
  4. package/dist/composables/index.js.map +1 -1
  5. package/dist/composables/index.mjs +38 -19
  6. package/dist/composables/index.mjs.map +1 -1
  7. package/dist/nuxt/module.json +1 -1
  8. package/dist/nuxt/module.mjs +9 -2
  9. package/dist/plugins/MagicCommand/nuxt.d.ts +2 -0
  10. package/dist/plugins/MagicCommand/src/components/MagicCommandBody.vue +4 -4
  11. package/dist/plugins/MagicCommand/src/components/MagicCommandBody.vue.d.ts +1 -0
  12. package/dist/plugins/MagicCookie/nuxt.d.ts +2 -0
  13. package/dist/plugins/MagicDraggable/index.d.ts +5 -0
  14. package/dist/plugins/MagicDraggable/index.mjs +8 -0
  15. package/dist/plugins/MagicDraggable/nuxt.d.ts +2 -0
  16. package/dist/plugins/MagicDraggable/nuxt.mjs +23 -0
  17. package/dist/plugins/MagicDraggable/src/components/MagicDraggable.vue +108 -0
  18. package/dist/plugins/MagicDraggable/src/components/MagicDraggable.vue.d.ts +41 -0
  19. package/dist/plugins/MagicDraggable/src/composables/private/useDraggableDrag.d.ts +18 -0
  20. package/dist/plugins/MagicDraggable/src/composables/private/useDraggableDrag.mjs +307 -0
  21. package/dist/plugins/MagicDraggable/src/composables/private/useDraggableSnap.d.ts +34 -0
  22. package/dist/plugins/MagicDraggable/src/composables/private/useDraggableSnap.mjs +143 -0
  23. package/dist/plugins/MagicDraggable/src/composables/private/useDraggableState.d.ts +108 -0
  24. package/dist/plugins/MagicDraggable/src/composables/private/useDraggableState.mjs +46 -0
  25. package/dist/plugins/MagicDraggable/src/composables/useDraggableApi.d.ts +1 -0
  26. package/dist/plugins/MagicDraggable/src/composables/useDraggableApi.mjs +2 -0
  27. package/dist/plugins/MagicDraggable/src/types/index.d.ts +48 -0
  28. package/dist/plugins/MagicDraggable/src/types/index.mjs +0 -0
  29. package/dist/plugins/MagicDraggable/src/utils/defaultOptions.d.ts +5 -0
  30. package/dist/plugins/MagicDraggable/src/utils/defaultOptions.mjs +21 -0
  31. package/dist/plugins/MagicDrawer/nuxt.d.ts +2 -0
  32. package/dist/plugins/MagicDrawer/src/components/MagicDrawer.vue +30 -19
  33. package/dist/plugins/MagicDrawer/src/components/MagicDrawer.vue.d.ts +1 -1
  34. package/dist/plugins/MagicDrawer/src/composables/private/useDrawerDrag.d.ts +4 -2
  35. package/dist/plugins/MagicDrawer/src/composables/private/useDrawerDrag.mjs +15 -14
  36. package/dist/plugins/MagicDrawer/src/composables/private/useDrawerSnap.d.ts +4 -2
  37. package/dist/plugins/MagicDrawer/src/composables/private/useDrawerSnap.mjs +13 -11
  38. package/dist/plugins/MagicDrawer/src/types/index.d.ts +21 -15
  39. package/dist/plugins/MagicDrawer/src/utils/defaultOptions.d.ts +4 -1
  40. package/dist/plugins/MagicDrawer/src/utils/defaultOptions.mjs +17 -14
  41. package/dist/plugins/MagicMarquee/nuxt.d.ts +2 -0
  42. package/dist/plugins/MagicModal/nuxt.d.ts +2 -0
  43. package/dist/plugins/MagicModal/src/components/MagicModal.vue +8 -5
  44. package/dist/plugins/MagicModal/src/types/index.d.ts +8 -5
  45. package/dist/plugins/MagicModal/src/utils/defaultOptions.mjs +6 -5
  46. package/dist/plugins/MagicNoise/nuxt.d.ts +2 -0
  47. package/dist/plugins/MagicPlayer/nuxt.d.ts +2 -0
  48. package/dist/plugins/MagicScroll/nuxt.d.ts +2 -0
  49. package/dist/plugins/MagicToast/nuxt.d.ts +2 -0
  50. package/dist/plugins/index.d.ts +1 -0
  51. package/dist/plugins/index.mjs +1 -0
  52. package/dist/utils/index.d.mts +16 -1
  53. package/dist/utils/index.d.ts +16 -1
  54. package/dist/utils/index.js +72 -0
  55. package/dist/utils/index.js.map +1 -1
  56. package/dist/utils/index.mjs +58 -0
  57. package/dist/utils/index.mjs.map +1 -1
  58. package/package.json +16 -4
  59. package/dist/plugins/MagicCommand/demo/DefaultView.vue +0 -84
  60. package/dist/plugins/MagicCommand/demo/DefaultView.vue.d.ts +0 -16
  61. package/dist/plugins/MagicCommand/demo/DemoItem.vue +0 -18
  62. package/dist/plugins/MagicCommand/demo/DemoItem.vue.d.ts +0 -21
  63. package/dist/plugins/MagicCommand/demo/ProjectView.vue +0 -63
  64. package/dist/plugins/MagicCommand/demo/ProjectView.vue.d.ts +0 -14
  65. package/dist/plugins/MagicToast/demo/DemoToast.vue +0 -22
  66. package/dist/plugins/MagicToast/demo/DemoToast.vue.d.ts +0 -18
@@ -0,0 +1,8 @@
1
+ import MagicDraggable from "./src/components/MagicDraggable.vue";
2
+ import { useDraggableApi } from "./src/composables/useDraggableApi.mjs";
3
+ const MagicDraggablePlugin = {
4
+ install: (app) => {
5
+ app.component("MagicDraggable", MagicDraggable);
6
+ }
7
+ };
8
+ export { MagicDraggablePlugin, MagicDraggable, useDraggableApi };
@@ -0,0 +1,2 @@
1
+ declare const _default: import("@nuxt/schema").NuxtModule<import("@nuxt/schema").ModuleOptions>;
2
+ export default _default;
@@ -0,0 +1,23 @@
1
+ import {
2
+ defineNuxtModule,
3
+ createResolver,
4
+ addComponent,
5
+ addImports
6
+ } from "@nuxt/kit";
7
+ export default defineNuxtModule({
8
+ meta: {
9
+ name: "@maas/vue-equipment/nuxt/MagicDraggable"
10
+ },
11
+ setup() {
12
+ const resolver = createResolver(import.meta.url);
13
+ addComponent({
14
+ filePath: resolver.resolve("src/components/MagicDraggable.vue"),
15
+ name: "MagicDraggable",
16
+ global: true
17
+ });
18
+ addImports({
19
+ from: "@maas/vue-equipment/plugins/MagicDraggable",
20
+ name: "useDraggableApi"
21
+ });
22
+ }
23
+ });
@@ -0,0 +1,108 @@
1
+ <template>
2
+ <div
3
+ ref="drawerRef"
4
+ class="magic-draggable"
5
+ :id="toValue(id)"
6
+ :class="[
7
+ toValue(props.class),
8
+
9
+ {
10
+ '-dragging': dragging,
11
+ '-disabled': disabled,
12
+ },
13
+ ]"
14
+ >
15
+ <div class="magic-draggable__wrapper" ref="wrapperRef">
16
+ <component
17
+ :is="mappedOptions.tag"
18
+ ref="elRef"
19
+ class="magic-draggable__drag"
20
+ :style="style"
21
+ @pointerdown="guardedPointerdown"
22
+ @click="guardedClick"
23
+ >
24
+ <component v-if="component" v-bind="props" :is="component" />
25
+ <slot v-else />
26
+ </component>
27
+ </div>
28
+ </div>
29
+ </template>
30
+
31
+ <script lang="ts" setup>
32
+ import {
33
+ ref,
34
+ computed,
35
+ toValue,
36
+ onMounted,
37
+ type Component,
38
+ type MaybeRef,
39
+ } from 'vue'
40
+ import { defu } from 'defu'
41
+ import { useDraggableDrag } from '../composables/private/useDraggableDrag'
42
+ import { useDraggableState } from '../composables/private/useDraggableState'
43
+ import { defaultOptions } from '../utils/defaultOptions'
44
+
45
+ import type { DraggableOptions } from '../types'
46
+
47
+ interface MagicDrawerProps {
48
+ id: MaybeRef<string>
49
+ class?: MaybeRef<string>
50
+ component?: Component
51
+ props?: Record<string, unknown>
52
+ options?: DraggableOptions
53
+ }
54
+
55
+ const props = withDefaults(defineProps<MagicDrawerProps>(), {
56
+ options: () => defaultOptions,
57
+ })
58
+
59
+ const mappedOptions = defu(props.options, defaultOptions)
60
+
61
+ const elRef = ref<HTMLElement | undefined>(undefined)
62
+ const wrapperRef = ref<HTMLDivElement | undefined>(undefined)
63
+
64
+ const { findState } = useDraggableState(props.id)
65
+ const { dragging } = findState()
66
+
67
+ // Make sure this is reactive
68
+ const disabled = computed(() => {
69
+ if (props.options.disabled === undefined) {
70
+ return defaultOptions.disabled
71
+ } else {
72
+ return props.options.disabled
73
+ }
74
+ })
75
+
76
+ const { snapPoints, animation, initial, threshold } = mappedOptions
77
+
78
+ const { initialize, onPointerdown, onClick, style } = useDraggableDrag({
79
+ id: props.id,
80
+ elRef,
81
+ wrapperRef,
82
+ threshold,
83
+ snapPoints,
84
+ animation,
85
+ initial,
86
+ })
87
+
88
+ // Public functions
89
+ function guardedPointerdown(event: PointerEvent) {
90
+ if (!disabled.value) {
91
+ onPointerdown(event)
92
+ }
93
+ }
94
+
95
+ function guardedClick(event: PointerEvent) {
96
+ if (!disabled.value) {
97
+ onClick(event)
98
+ }
99
+ }
100
+
101
+ onMounted(() => {
102
+ initialize()
103
+ })
104
+ </script>
105
+
106
+ <style>
107
+ :root{--magic-draggable-z-index:999;--magic-draggable-position:fixed;--magic-draggable-height:100%;--magic-draggable-width:100%;--magic-draggable-inset:0}.magic-draggable{background:transparent;border:none;color:inherit;height:var(--magic-draggable-height);inset:var(--magic-draggable-inset);padding:0;position:var(--magic-draggable-position);width:var(--magic-draggable-width);z-index:var(--magic-draggable-z-index)}.magic-draggable,.magic-draggable.-disabled{pointer-events:none}.magic-draggable__wrapper{display:block;height:100%;width:100%}.magic-draggable__drag{cursor:grab;display:inline-flex;height:auto;pointer-events:auto;position:relative;transform-origin:center;-webkit-user-select:none;-moz-user-select:none;user-select:none;width:auto}.magic-draggable.-dragging .magic-draggable__drag{cursor:grabbing;-webkit-user-select:none;-moz-user-select:none;user-select:none}.magic-draggable.-disabled .magic-draggable__drag{cursor:default}
108
+ </style>
@@ -0,0 +1,41 @@
1
+ import { type Component, type MaybeRef } from 'vue';
2
+ import type { DraggableOptions } from '../types';
3
+ interface MagicDrawerProps {
4
+ id: MaybeRef<string>;
5
+ class?: MaybeRef<string>;
6
+ component?: Component;
7
+ props?: Record<string, unknown>;
8
+ options?: DraggableOptions;
9
+ }
10
+ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__VLS_WithDefaults<__VLS_TypePropsToOption<MagicDrawerProps>, {
11
+ options: () => DraggableOptions;
12
+ }>, {}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<__VLS_WithDefaults<__VLS_TypePropsToOption<MagicDrawerProps>, {
13
+ options: () => DraggableOptions;
14
+ }>>>, {
15
+ options: DraggableOptions;
16
+ }, {}>, {
17
+ default?(_: {}): any;
18
+ }>;
19
+ export default _default;
20
+ type __VLS_WithDefaults<P, D> = {
21
+ [K in keyof Pick<P, keyof P>]: K extends keyof D ? __VLS_Prettify<P[K] & {
22
+ default: D[K];
23
+ }> : P[K];
24
+ };
25
+ type __VLS_Prettify<T> = {
26
+ [K in keyof T]: T[K];
27
+ } & {};
28
+ type __VLS_WithTemplateSlots<T, S> = T & {
29
+ new (): {
30
+ $slots: S;
31
+ };
32
+ };
33
+ type __VLS_NonUndefinedable<T> = T extends undefined ? never : T;
34
+ type __VLS_TypePropsToOption<T> = {
35
+ [K in keyof T]-?: {} extends Pick<T, K> ? {
36
+ type: import('vue').PropType<__VLS_NonUndefinedable<T[K]>>;
37
+ } : {
38
+ type: import('vue').PropType<T[K]>;
39
+ required: true;
40
+ };
41
+ };
@@ -0,0 +1,18 @@
1
+ import { type Ref, type MaybeRef } from 'vue';
2
+ import { type DefaultOptions } from '../../utils/defaultOptions.js';
3
+ type UseDraggableDragArgs = {
4
+ id: MaybeRef<string>;
5
+ elRef: Ref<HTMLElement | undefined>;
6
+ wrapperRef: Ref<HTMLDivElement | undefined>;
7
+ threshold: MaybeRef<DefaultOptions['threshold']>;
8
+ snapPoints: MaybeRef<DefaultOptions['snapPoints']>;
9
+ animation: MaybeRef<DefaultOptions['animation']>;
10
+ initial: MaybeRef<DefaultOptions['initial']>;
11
+ };
12
+ export declare function useDraggableDrag(args: UseDraggableDragArgs): {
13
+ initialize: () => Promise<void>;
14
+ onPointerdown: (e: PointerEvent) => void;
15
+ onClick: (e: MouseEvent) => void;
16
+ style: import("vue").ComputedRef<string>;
17
+ };
18
+ export {};
@@ -0,0 +1,307 @@
1
+ import {
2
+ ref,
3
+ computed,
4
+ toValue,
5
+ nextTick,
6
+ watch
7
+ } from "vue";
8
+ import {
9
+ useEventListener,
10
+ unrefElement,
11
+ useResizeObserver,
12
+ useThrottleFn,
13
+ useIdle
14
+ } from "@vueuse/core";
15
+ import { useDraggableSnap } from "./useDraggableSnap.mjs";
16
+ import { useDraggableState } from "./useDraggableState.mjs";
17
+ import { isIOS } from "@maas/vue-equipment/utils";
18
+ export function useDraggableDrag(args) {
19
+ const { id, elRef, wrapperRef, threshold, snapPoints, initial, animation } = args;
20
+ const { findState } = useDraggableState(toValue(id));
21
+ const {
22
+ dragStart,
23
+ dragging,
24
+ interpolateTo,
25
+ originX,
26
+ originY,
27
+ lastDraggedX,
28
+ lastDraggedY,
29
+ intermediateDraggedX,
30
+ intermediateDraggedY,
31
+ draggedX,
32
+ draggedY,
33
+ elRect,
34
+ wrapperRect
35
+ } = findState();
36
+ let cancelPointerup = void 0;
37
+ let cancelPointermove = void 0;
38
+ let cancelTouchend = void 0;
39
+ const momentumThresholdReached = ref(false);
40
+ const distanceThresholdReached = ref(false);
41
+ const style = computed(
42
+ () => `transform: translate3d(${draggedX.value}px, ${draggedY.value}px, 0)`
43
+ );
44
+ const {
45
+ snapTo,
46
+ activeSnapPoint,
47
+ mapSnapPoint,
48
+ mappedSnapPoints,
49
+ snapPointsMap,
50
+ interpolateDragged
51
+ } = useDraggableSnap({
52
+ elRect,
53
+ wrapperRect,
54
+ animation,
55
+ snapPoints,
56
+ draggedY,
57
+ draggedX
58
+ });
59
+ async function getSizes() {
60
+ elRect.value = unrefElement(elRef)?.getBoundingClientRect();
61
+ wrapperRect.value = unrefElement(wrapperRef)?.getBoundingClientRect();
62
+ await nextTick();
63
+ }
64
+ function setDragged({ x, y }) {
65
+ draggedX.value = x - originX.value;
66
+ draggedY.value = y - originY.value;
67
+ }
68
+ function resetStateAndListeners() {
69
+ dragging.value = false;
70
+ interpolateTo.value = void 0;
71
+ momentumThresholdReached.value = false;
72
+ distanceThresholdReached.value = false;
73
+ cancelTouchend?.();
74
+ cancelPointerup?.();
75
+ cancelPointermove?.();
76
+ }
77
+ function detectCollision() {
78
+ const childRect = toValue(elRect);
79
+ const parentRect = toValue(wrapperRect);
80
+ if (!childRect || !parentRect) {
81
+ return;
82
+ }
83
+ if (childRect.width > parentRect.width || childRect.height > parentRect.height) {
84
+ console.warn("MagicDraggable is too small for its content");
85
+ return;
86
+ }
87
+ interpolateTo.value = { x: draggedX.value, y: draggedY.value };
88
+ if (childRect.top < parentRect.top) {
89
+ interpolateTo.value = { x: interpolateTo.value?.x, y: 0 };
90
+ } else if (childRect.bottom > parentRect.bottom) {
91
+ interpolateTo.value = {
92
+ x: interpolateTo.value?.x,
93
+ y: parentRect.height - childRect.height
94
+ };
95
+ }
96
+ if (childRect.left < parentRect.left) {
97
+ interpolateTo.value = { x: 0, y: interpolateTo.value?.y };
98
+ } else if (childRect.right > parentRect.right) {
99
+ interpolateTo.value = {
100
+ x: parentRect.width - childRect.width,
101
+ y: interpolateTo.value?.y
102
+ };
103
+ }
104
+ }
105
+ function vectorBetweenCoordinates(a, b) {
106
+ const dx = b.x - a.x;
107
+ const dy = b.y - a.y;
108
+ const length = Math.sqrt(dx * dx + dy * dy);
109
+ if (length === 0) {
110
+ return { x: 0, y: 0 };
111
+ } else {
112
+ return { x: dx / length, y: dy / length };
113
+ }
114
+ }
115
+ function dotProduct(vectorA, vectorB) {
116
+ return vectorA.x * vectorB.x + vectorA.y * vectorB.y;
117
+ }
118
+ function calculateDistance(a, b) {
119
+ return Math.sqrt((a.x - b.x) ** 2 + (a.y - b.y) ** 2);
120
+ }
121
+ function checkDistance() {
122
+ if (toValue(threshold).distance) {
123
+ const intermediateDraggedCoords = {
124
+ x: intermediateDraggedX.value,
125
+ y: intermediateDraggedY.value
126
+ };
127
+ const draggedCoords = { x: draggedX.value, y: draggedY.value };
128
+ const draggedDistance = calculateDistance(
129
+ intermediateDraggedCoords,
130
+ draggedCoords
131
+ );
132
+ if (draggedDistance < toValue(threshold).distance) {
133
+ return;
134
+ }
135
+ }
136
+ distanceThresholdReached.value = true;
137
+ }
138
+ function checkMomentum() {
139
+ if (dragStart.value && toValue(threshold).momentum) {
140
+ const intermediateDraggedCoords = {
141
+ x: intermediateDraggedX.value,
142
+ y: intermediateDraggedY.value
143
+ };
144
+ const draggedCoords = { x: draggedX.value, y: draggedY.value };
145
+ const draggedDistance = calculateDistance(
146
+ intermediateDraggedCoords,
147
+ draggedCoords
148
+ );
149
+ const dragTime = (/* @__PURE__ */ new Date()).getTime() - dragStart.value.getTime();
150
+ if (dragTime === 0) {
151
+ return;
152
+ }
153
+ const dragSpeed = draggedDistance / dragTime;
154
+ if (dragSpeed < toValue(threshold).momentum) {
155
+ return;
156
+ }
157
+ }
158
+ momentumThresholdReached.value = true;
159
+ }
160
+ function compareDistances(a, b) {
161
+ const draggedCoords = { x: draggedX.value, y: draggedY.value };
162
+ const distanceA = calculateDistance(a, draggedCoords);
163
+ const distanceB = calculateDistance(b, draggedCoords);
164
+ return distanceA < distanceB ? a : b;
165
+ }
166
+ function findSnapPointByVector() {
167
+ let bestDotProduct = -Infinity;
168
+ const intermediateDraggedCoords = {
169
+ x: intermediateDraggedX.value,
170
+ y: intermediateDraggedY.value
171
+ };
172
+ const draggedCoords = { x: draggedX.value, y: draggedY.value };
173
+ const lineVector = vectorBetweenCoordinates(
174
+ intermediateDraggedCoords,
175
+ draggedCoords
176
+ );
177
+ for (let i = 0; i < mappedSnapPoints.value.length; i++) {
178
+ const snapPoint = mappedSnapPoints.value[i];
179
+ const targetVector = vectorBetweenCoordinates(
180
+ intermediateDraggedCoords,
181
+ snapPoint
182
+ );
183
+ const currentDotProduct = dotProduct(lineVector, targetVector);
184
+ if (currentDotProduct > bestDotProduct) {
185
+ bestDotProduct = currentDotProduct;
186
+ interpolateTo.value = snapPoint;
187
+ } else if (currentDotProduct === bestDotProduct) {
188
+ if (!interpolateTo.value) {
189
+ interpolateTo.value = snapPoint;
190
+ } else {
191
+ const smallerDistance = compareDistances(
192
+ snapPoint,
193
+ interpolateTo.value
194
+ );
195
+ interpolateTo.value = smallerDistance;
196
+ }
197
+ }
198
+ }
199
+ }
200
+ function findClosestSnapPoint() {
201
+ const draggedCoords = { x: draggedX.value, y: draggedY.value };
202
+ const closestSnapPoint = mappedSnapPoints.value.reduce((a, b) => {
203
+ return calculateDistance(a, draggedCoords) < calculateDistance(b, draggedCoords) ? a : b;
204
+ });
205
+ return closestSnapPoint;
206
+ }
207
+ function onPointerup(_e) {
208
+ if (!momentumThresholdReached.value && distanceThresholdReached.value) {
209
+ interpolateTo.value = findClosestSnapPoint();
210
+ }
211
+ const { x, y } = interpolateTo.value || {};
212
+ if (x !== void 0 && y !== void 0) {
213
+ interpolateDragged({ x, y });
214
+ }
215
+ if (interpolateTo.value) {
216
+ const key = `x${interpolateTo.value.x}y${interpolateTo.value.y}`;
217
+ activeSnapPoint.value = snapPointsMap.value[key];
218
+ }
219
+ resetStateAndListeners();
220
+ }
221
+ function onPointermove(e) {
222
+ setDragged({ x: e.screenX, y: e.screenY });
223
+ getSizes();
224
+ detectCollision();
225
+ if (!distanceThresholdReached.value) {
226
+ checkDistance();
227
+ }
228
+ if (!momentumThresholdReached.value) {
229
+ checkMomentum();
230
+ }
231
+ if (!distanceThresholdReached.value && !momentumThresholdReached.value) {
232
+ interpolateTo.value = { x: lastDraggedX.value, y: lastDraggedY.value };
233
+ return;
234
+ }
235
+ if (toValue(snapPoints).length) {
236
+ findSnapPointByVector();
237
+ }
238
+ }
239
+ function onIdle() {
240
+ interpolateTo.value = findClosestSnapPoint();
241
+ if (distanceThresholdReached.value && momentumThresholdReached.value) {
242
+ intermediateDraggedX.value = draggedX.value;
243
+ intermediateDraggedY.value = draggedY.value;
244
+ distanceThresholdReached.value = false;
245
+ momentumThresholdReached.value = false;
246
+ }
247
+ }
248
+ function onPointerdown(e) {
249
+ if (dragging.value) {
250
+ return;
251
+ } else {
252
+ dragging.value = true;
253
+ }
254
+ intermediateDraggedX.value = draggedX.value;
255
+ intermediateDraggedY.value = draggedY.value;
256
+ lastDraggedX.value = draggedX.value;
257
+ lastDraggedY.value = draggedY.value;
258
+ cancelPointerup = useEventListener(document, "pointerup", onPointerup);
259
+ cancelPointermove = useEventListener(document, "pointermove", onPointermove);
260
+ cancelTouchend = isIOS() ? useEventListener(document, "touchend", onPointerup) : void 0;
261
+ originX.value = e.screenX - draggedX.value;
262
+ originY.value = e.screenY - draggedY.value;
263
+ dragStart.value = /* @__PURE__ */ new Date();
264
+ onPointermove(e);
265
+ }
266
+ function onClick(e) {
267
+ e.preventDefault();
268
+ }
269
+ async function initialize() {
270
+ await getSizes();
271
+ if (elRect.value && wrapperRect.value) {
272
+ if (elRect.value.width > wrapperRect.value.width || elRect.value.height > wrapperRect.value.height) {
273
+ console.warn("MagicDraggable is too small for its content");
274
+ return;
275
+ }
276
+ }
277
+ await nextTick();
278
+ if (toValue(initial).snapPoint) {
279
+ const mappedSnapPoint = mapSnapPoint(toValue(initial).snapPoint);
280
+ if (mappedSnapPoint) {
281
+ draggedX.value = mappedSnapPoint.x;
282
+ draggedY.value = mappedSnapPoint.y;
283
+ }
284
+ }
285
+ }
286
+ useResizeObserver(wrapperRef, async () => {
287
+ useThrottleFn(async () => {
288
+ await getSizes();
289
+ if (activeSnapPoint.value) {
290
+ await snapTo({ snapPoint: activeSnapPoint.value, interpolate: false });
291
+ snapPointsMap.trigger();
292
+ }
293
+ }, 100)();
294
+ });
295
+ const { idle } = useIdle(toValue(threshold).idle);
296
+ watch(idle, (value) => {
297
+ if (value && dragging.value) {
298
+ onIdle();
299
+ }
300
+ });
301
+ return {
302
+ initialize,
303
+ onPointerdown,
304
+ onClick,
305
+ style
306
+ };
307
+ }
@@ -0,0 +1,34 @@
1
+ import { type MaybeRef, type Ref } from 'vue';
2
+ import { type DefaultOptions } from '../../utils/defaultOptions.js';
3
+ import type { SnapPoint, Coordinates } from '../../types.js';
4
+ type UseDraggableSnapArgs = {
5
+ elRect: Ref<DOMRect | undefined>;
6
+ wrapperRect: Ref<DOMRect | undefined>;
7
+ draggedY: Ref<number>;
8
+ draggedX: Ref<number>;
9
+ animation: MaybeRef<DefaultOptions['animation']>;
10
+ snapPoints: MaybeRef<DefaultOptions['snapPoints']>;
11
+ };
12
+ type InterpolateDraggedArgs = {
13
+ x: number;
14
+ y: number;
15
+ duration?: number;
16
+ easing?: (t: number) => number;
17
+ };
18
+ type SnapToArgs = {
19
+ snapPoint: SnapPoint;
20
+ interpolate?: boolean;
21
+ duration?: number;
22
+ };
23
+ export declare function useDraggableSnap(args: UseDraggableSnapArgs): {
24
+ mappedSnapPoints: import("@vueuse/core").ComputedRefWithControl<Coordinates[]>;
25
+ activeSnapPoint: Ref<("center" | "top-center" | "bottom-center" | "top-left" | "top-right" | "center-left" | "center-right" | "bottom-left" | "bottom-right") | ["center" | "top-center" | "bottom-center" | "top-left" | "top-right" | "center-left" | "center-right" | "bottom-left" | "bottom-right", offset?: {
26
+ x?: number | undefined;
27
+ y?: number | undefined;
28
+ } | undefined] | undefined>;
29
+ snapPointsMap: import("@vueuse/core").ComputedRefWithControl<Record<string, SnapPoint>>;
30
+ mapSnapPoint: (snapPoint: SnapPoint) => Coordinates | undefined;
31
+ interpolateDragged: (args: InterpolateDraggedArgs) => void;
32
+ snapTo: (args: SnapToArgs) => Promise<void>;
33
+ };
34
+ export {};
@@ -0,0 +1,143 @@
1
+ import { ref, toValue, nextTick } from "vue";
2
+ import { computedWithControl } from "@vueuse/core";
3
+ import { interpolate } from "@maas/vue-equipment/utils";
4
+ import { defu } from "defu";
5
+ export function useDraggableSnap(args) {
6
+ const { draggedY, draggedX, elRect, wrapperRect, animation, snapPoints } = args;
7
+ const activeSnapPoint = ref(void 0);
8
+ const mappedSnapPoints = computedWithControl(
9
+ () => toValue(wrapperRect),
10
+ () => {
11
+ const mapped = toValue(snapPoints).map((snapPoint) => {
12
+ return mapSnapPoint(snapPoint);
13
+ }).filter((snapPoint) => snapPoint !== void 0);
14
+ return mapped;
15
+ }
16
+ );
17
+ const snapPointsMap = computedWithControl(
18
+ () => toValue(snapPoints),
19
+ () => {
20
+ const mapped = toValue(snapPoints).reduce((acc, current) => {
21
+ const key = mapSnapPoint(current);
22
+ if (key) {
23
+ const mappedKey = `x${key.x}y${key.y}`;
24
+ acc[mappedKey] = current;
25
+ }
26
+ return acc;
27
+ }, {});
28
+ return mapped;
29
+ }
30
+ );
31
+ function mapSnapPoint(snapPoint) {
32
+ if (!wrapperRect.value) {
33
+ console.warn("Wrapper rect is not defined");
34
+ return void 0;
35
+ }
36
+ if (!elRect.value) {
37
+ console.warn("Element rect is not defined");
38
+ return void 0;
39
+ }
40
+ const mappedSnapPoint = typeof snapPoint === "string" ? [snapPoint] : snapPoint;
41
+ const [position, offset] = mappedSnapPoint;
42
+ const mappedOffset = defu(offset, { x: 0, y: 0 });
43
+ switch (position) {
44
+ case "top-left":
45
+ return {
46
+ x: mappedOffset.x,
47
+ y: mappedOffset.y
48
+ };
49
+ case "top-center":
50
+ return {
51
+ x: wrapperRect.value.width / 2 + mappedOffset.x - elRect.value.width / 2,
52
+ y: mappedOffset.y
53
+ };
54
+ case "top-right":
55
+ return {
56
+ x: wrapperRect.value.width - mappedOffset.x - elRect.value.width,
57
+ y: mappedOffset.y
58
+ };
59
+ case "center-left":
60
+ return {
61
+ x: mappedOffset.x,
62
+ y: wrapperRect.value.height / 2 + mappedOffset.y - elRect.value.height / 2
63
+ };
64
+ case "center":
65
+ return {
66
+ x: wrapperRect.value.width / 2 - elRect.value.width / 2 + mappedOffset.x,
67
+ y: wrapperRect.value.height / 2 - elRect.value.height / 2 + mappedOffset.y
68
+ };
69
+ case "center-right":
70
+ return {
71
+ x: wrapperRect.value.width - mappedOffset.x - elRect.value.width,
72
+ y: wrapperRect.value.height / 2 + mappedOffset.y - elRect.value.height / 2
73
+ };
74
+ case "bottom-left":
75
+ return {
76
+ x: mappedOffset.x,
77
+ y: wrapperRect.value.height + mappedOffset.y - elRect.value.height
78
+ };
79
+ case "bottom-center":
80
+ return {
81
+ x: wrapperRect.value.width / 2 + mappedOffset.x - elRect.value.width / 2,
82
+ y: wrapperRect.value.height - mappedOffset.y - elRect.value.height
83
+ };
84
+ case "bottom-right":
85
+ return {
86
+ x: wrapperRect.value.width - mappedOffset.x - elRect.value.width,
87
+ y: wrapperRect.value.height - mappedOffset.y - elRect.value.height
88
+ };
89
+ }
90
+ }
91
+ function interpolateDragged(args2) {
92
+ const {
93
+ x,
94
+ y,
95
+ duration = toValue(animation).snap?.duration,
96
+ easing = toValue(animation).snap?.easing
97
+ } = args2;
98
+ interpolate({
99
+ from: draggedY.value,
100
+ to: y,
101
+ duration,
102
+ easing,
103
+ callback: (value) => {
104
+ draggedY.value = value;
105
+ }
106
+ });
107
+ interpolate({
108
+ from: draggedX.value,
109
+ to: x,
110
+ duration,
111
+ easing,
112
+ callback: (value) => {
113
+ draggedX.value = value;
114
+ }
115
+ });
116
+ }
117
+ async function snapTo(args2) {
118
+ const { snapPoint, interpolate: interpolate2, duration } = args2;
119
+ await nextTick();
120
+ const mappedSnapPoint = mapSnapPoint(snapPoint);
121
+ if (mappedSnapPoint) {
122
+ if (interpolate2) {
123
+ interpolateDragged({
124
+ x: mappedSnapPoint.x,
125
+ y: mappedSnapPoint.y,
126
+ duration
127
+ });
128
+ } else {
129
+ draggedX.value = mappedSnapPoint.x;
130
+ draggedY.value = mappedSnapPoint.y;
131
+ }
132
+ }
133
+ activeSnapPoint.value = snapPoint;
134
+ }
135
+ return {
136
+ mappedSnapPoints,
137
+ activeSnapPoint,
138
+ snapPointsMap,
139
+ mapSnapPoint,
140
+ interpolateDragged,
141
+ snapTo
142
+ };
143
+ }