@thangdevalone/meet-layout-grid-vue 1.3.1 → 1.3.3
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/README.md +107 -31
- package/dist/index.cjs +297 -92
- package/dist/index.d.cts +68 -6
- package/dist/index.d.mts +68 -6
- package/dist/index.d.ts +68 -6
- package/dist/index.mjs +299 -96
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { ref, onMounted, computed, defineComponent, provide, h, inject } from 'vue';
|
|
1
|
+
import { ref, onMounted, computed, defineComponent, provide, h, inject, watch } from 'vue';
|
|
2
2
|
import { useResizeObserver } from '@vueuse/core';
|
|
3
|
-
import { createMeetGrid, getSpringConfig } from '@thangdevalone/meet-layout-grid-core';
|
|
4
|
-
export { createGrid, createGridItemPositioner, createMeetGrid, getAspectRatio, getGridItemDimensions, getSpringConfig, springPresets } from '@thangdevalone/meet-layout-grid-core';
|
|
5
|
-
import { motion } from 'motion-v';
|
|
3
|
+
import { createMeetGrid, getSpringConfig, resolveFloatSize } from '@thangdevalone/meet-layout-grid-core';
|
|
4
|
+
export { DEFAULT_FLOAT_BREAKPOINTS, createGrid, createGridItemPositioner, createMeetGrid, getAspectRatio, getGridItemDimensions, getSpringConfig, resolveFloatSize, springPresets } from '@thangdevalone/meet-layout-grid-core';
|
|
5
|
+
import { useMotionValue, animate, motion } from 'motion-v';
|
|
6
6
|
|
|
7
7
|
function useGridDimensions(elementRef) {
|
|
8
8
|
const width = ref(0);
|
|
@@ -123,6 +123,25 @@ const GridContainer = defineComponent({
|
|
|
123
123
|
type: Array,
|
|
124
124
|
default: void 0
|
|
125
125
|
},
|
|
126
|
+
/** Custom width for the floating PiP item in 2-person mode */
|
|
127
|
+
floatWidth: {
|
|
128
|
+
type: Number,
|
|
129
|
+
default: void 0
|
|
130
|
+
},
|
|
131
|
+
/** Custom height for the floating PiP item in 2-person mode */
|
|
132
|
+
floatHeight: {
|
|
133
|
+
type: Number,
|
|
134
|
+
default: void 0
|
|
135
|
+
},
|
|
136
|
+
/**
|
|
137
|
+
* Responsive breakpoints for the floating PiP in 2-person mode.
|
|
138
|
+
* When provided, PiP size auto-adjusts based on container width.
|
|
139
|
+
* Use `DEFAULT_FLOAT_BREAKPOINTS` for a ready-made 5-level responsive config.
|
|
140
|
+
*/
|
|
141
|
+
floatBreakpoints: {
|
|
142
|
+
type: Array,
|
|
143
|
+
default: void 0
|
|
144
|
+
},
|
|
126
145
|
/** HTML tag to render */
|
|
127
146
|
tag: {
|
|
128
147
|
type: String,
|
|
@@ -144,7 +163,10 @@ const GridContainer = defineComponent({
|
|
|
144
163
|
currentPage: props.currentPage,
|
|
145
164
|
maxVisible: props.maxVisible,
|
|
146
165
|
currentVisiblePage: props.currentVisiblePage,
|
|
147
|
-
itemAspectRatios: props.itemAspectRatios
|
|
166
|
+
itemAspectRatios: props.itemAspectRatios,
|
|
167
|
+
floatWidth: props.floatWidth,
|
|
168
|
+
floatHeight: props.floatHeight,
|
|
169
|
+
floatBreakpoints: props.floatBreakpoints
|
|
148
170
|
}));
|
|
149
171
|
const grid = useMeetGrid(gridOptions);
|
|
150
172
|
provide(GridContextKey, {
|
|
@@ -197,7 +219,7 @@ const GridItem = defineComponent({
|
|
|
197
219
|
console.warn("GridItem must be used inside a GridContainer");
|
|
198
220
|
return () => null;
|
|
199
221
|
}
|
|
200
|
-
const { grid, springPreset } = context;
|
|
222
|
+
const { grid, springPreset, dimensions: containerDimensions } = context;
|
|
201
223
|
const position = computed(() => grid.value.getPosition(props.index));
|
|
202
224
|
const dimensions = computed(() => grid.value.getItemDimensions(props.index));
|
|
203
225
|
const contentDimensions = computed(
|
|
@@ -212,63 +234,211 @@ const GridItem = defineComponent({
|
|
|
212
234
|
return true;
|
|
213
235
|
return false;
|
|
214
236
|
});
|
|
237
|
+
const isFloat = computed(() => grid.value.floatIndex === props.index);
|
|
238
|
+
const floatDims = computed(() => grid.value.floatDimensions ?? { width: 120, height: 160 });
|
|
239
|
+
const floatAnchor = ref(
|
|
240
|
+
"bottom-right"
|
|
241
|
+
);
|
|
242
|
+
const x = useMotionValue(0);
|
|
243
|
+
const y = useMotionValue(0);
|
|
244
|
+
const floatInitialized = ref(false);
|
|
245
|
+
const getFloatCornerPos = (corner) => {
|
|
246
|
+
const padding = 12;
|
|
247
|
+
const dims = containerDimensions.value;
|
|
248
|
+
const fw = floatDims.value.width;
|
|
249
|
+
const fh = floatDims.value.height;
|
|
250
|
+
switch (corner) {
|
|
251
|
+
case "top-left":
|
|
252
|
+
return { x: padding, y: padding };
|
|
253
|
+
case "top-right":
|
|
254
|
+
return { x: dims.width - fw - padding, y: padding };
|
|
255
|
+
case "bottom-left":
|
|
256
|
+
return { x: padding, y: dims.height - fh - padding };
|
|
257
|
+
case "bottom-right":
|
|
258
|
+
default:
|
|
259
|
+
return { x: dims.width - fw - padding, y: dims.height - fh - padding };
|
|
260
|
+
}
|
|
261
|
+
};
|
|
262
|
+
const findFloatNearestCorner = (posX, posY) => {
|
|
263
|
+
const fw = floatDims.value.width;
|
|
264
|
+
const fh = floatDims.value.height;
|
|
265
|
+
const centerX = posX + fw / 2;
|
|
266
|
+
const centerY = posY + fh / 2;
|
|
267
|
+
const dims = containerDimensions.value;
|
|
268
|
+
const isLeft = centerX < dims.width / 2;
|
|
269
|
+
const isTop = centerY < dims.height / 2;
|
|
270
|
+
if (isTop && isLeft)
|
|
271
|
+
return "top-left";
|
|
272
|
+
if (isTop && !isLeft)
|
|
273
|
+
return "top-right";
|
|
274
|
+
if (!isTop && isLeft)
|
|
275
|
+
return "bottom-left";
|
|
276
|
+
return "bottom-right";
|
|
277
|
+
};
|
|
278
|
+
watch(isFloat, (floating) => {
|
|
279
|
+
if (!floating) {
|
|
280
|
+
floatInitialized.value = false;
|
|
281
|
+
}
|
|
282
|
+
});
|
|
283
|
+
watch(
|
|
284
|
+
[isFloat, () => containerDimensions.value.width, () => containerDimensions.value.height],
|
|
285
|
+
([floating, w, h2]) => {
|
|
286
|
+
if (floating && w > 0 && h2 > 0 && !floatInitialized.value) {
|
|
287
|
+
const pos = getFloatCornerPos(floatAnchor.value);
|
|
288
|
+
x.set(pos.x);
|
|
289
|
+
y.set(pos.y);
|
|
290
|
+
floatInitialized.value = true;
|
|
291
|
+
}
|
|
292
|
+
},
|
|
293
|
+
{ immediate: true }
|
|
294
|
+
);
|
|
295
|
+
watch(
|
|
296
|
+
[floatAnchor, () => containerDimensions.value.width, () => containerDimensions.value.height],
|
|
297
|
+
([, w, h2]) => {
|
|
298
|
+
if (isFloat.value && floatInitialized.value && w > 0 && h2 > 0) {
|
|
299
|
+
const pos = getFloatCornerPos(floatAnchor.value);
|
|
300
|
+
const springCfg = { type: "spring", stiffness: 400, damping: 30 };
|
|
301
|
+
animate(x, pos.x, springCfg);
|
|
302
|
+
animate(y, pos.y, springCfg);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
);
|
|
215
306
|
const isLastVisibleOther = computed(() => {
|
|
216
307
|
const lastVisibleOthersIndex = grid.value.getLastVisibleOthersIndex();
|
|
217
308
|
return props.index === lastVisibleOthersIndex;
|
|
218
309
|
});
|
|
219
310
|
const hiddenCount = computed(() => grid.value.hiddenCount);
|
|
220
311
|
const springConfig = getSpringConfig(springPreset);
|
|
312
|
+
const gridX = useMotionValue(0);
|
|
313
|
+
const gridY = useMotionValue(0);
|
|
314
|
+
const gridAnimReady = ref(false);
|
|
315
|
+
watch(
|
|
316
|
+
[
|
|
317
|
+
() => position.value.top,
|
|
318
|
+
() => position.value.left,
|
|
319
|
+
isFloat,
|
|
320
|
+
isHidden
|
|
321
|
+
],
|
|
322
|
+
([, , floating, hidden]) => {
|
|
323
|
+
if (floating || hidden) {
|
|
324
|
+
gridAnimReady.value = false;
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
327
|
+
const pos = position.value;
|
|
328
|
+
if (!gridAnimReady.value) {
|
|
329
|
+
gridX.set(pos.left);
|
|
330
|
+
gridY.set(pos.top);
|
|
331
|
+
gridAnimReady.value = true;
|
|
332
|
+
} else {
|
|
333
|
+
const cfg = {
|
|
334
|
+
type: "spring",
|
|
335
|
+
stiffness: springConfig.stiffness,
|
|
336
|
+
damping: springConfig.damping
|
|
337
|
+
};
|
|
338
|
+
animate(gridX, pos.left, cfg);
|
|
339
|
+
animate(gridY, pos.top, cfg);
|
|
340
|
+
}
|
|
341
|
+
},
|
|
342
|
+
{ immediate: true }
|
|
343
|
+
);
|
|
221
344
|
const slotProps = computed(() => ({
|
|
222
345
|
contentDimensions: contentDimensions.value,
|
|
223
346
|
isLastVisibleOther: isLastVisibleOther.value,
|
|
224
|
-
hiddenCount: hiddenCount.value
|
|
347
|
+
hiddenCount: hiddenCount.value,
|
|
348
|
+
isFloat: isFloat.value
|
|
225
349
|
}));
|
|
226
350
|
return () => {
|
|
227
351
|
if (isHidden.value) {
|
|
228
352
|
return null;
|
|
229
353
|
}
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
354
|
+
if (isFloat.value) {
|
|
355
|
+
const dims = containerDimensions.value;
|
|
356
|
+
if (dims.width === 0 || dims.height === 0)
|
|
357
|
+
return null;
|
|
358
|
+
const dragConstraints = {
|
|
359
|
+
left: 12,
|
|
360
|
+
right: dims.width - floatDims.value.width - 12,
|
|
361
|
+
top: 12,
|
|
362
|
+
bottom: dims.height - floatDims.value.height - 12
|
|
363
|
+
};
|
|
364
|
+
const handleDragEnd = () => {
|
|
365
|
+
const currentX = x.get();
|
|
366
|
+
const currentY = y.get();
|
|
367
|
+
const nearestCorner = findFloatNearestCorner(currentX, currentY);
|
|
368
|
+
floatAnchor.value = nearestCorner;
|
|
369
|
+
const snapPos = getFloatCornerPos(nearestCorner);
|
|
370
|
+
const springCfg = { type: "spring", stiffness: 400, damping: 30 };
|
|
371
|
+
animate(x, snapPos.x, springCfg);
|
|
372
|
+
animate(y, snapPos.y, springCfg);
|
|
373
|
+
};
|
|
374
|
+
return h(
|
|
375
|
+
motion.div,
|
|
376
|
+
{
|
|
377
|
+
// Key forces Vue to recreate this element when switching float↔grid
|
|
378
|
+
key: `float-${props.index}`,
|
|
379
|
+
drag: true,
|
|
380
|
+
dragMomentum: false,
|
|
381
|
+
dragElastic: 0.1,
|
|
382
|
+
dragConstraints,
|
|
383
|
+
style: {
|
|
384
|
+
position: "absolute",
|
|
385
|
+
width: `${floatDims.value.width}px`,
|
|
386
|
+
height: `${floatDims.value.height}px`,
|
|
387
|
+
borderRadius: "12px",
|
|
388
|
+
boxShadow: "0 4px 20px rgba(0,0,0,0.3)",
|
|
389
|
+
overflow: "hidden",
|
|
390
|
+
cursor: "grab",
|
|
391
|
+
zIndex: 100,
|
|
392
|
+
touchAction: "none",
|
|
393
|
+
left: 0,
|
|
394
|
+
top: 0,
|
|
395
|
+
x,
|
|
396
|
+
y
|
|
397
|
+
},
|
|
398
|
+
whileDrag: { cursor: "grabbing", scale: 1.05, boxShadow: "0 8px 32px rgba(0,0,0,0.4)" },
|
|
399
|
+
transition: { type: "spring", stiffness: 400, damping: 30 },
|
|
400
|
+
"data-grid-index": props.index,
|
|
401
|
+
"data-grid-float": true,
|
|
402
|
+
onDragEnd: handleDragEnd
|
|
403
|
+
},
|
|
404
|
+
() => slots.default?.(slotProps.value)
|
|
405
|
+
);
|
|
406
|
+
}
|
|
407
|
+
const itemWidth = dimensions.value.width;
|
|
408
|
+
const itemHeight = dimensions.value.height;
|
|
236
409
|
if (props.disableAnimation) {
|
|
237
410
|
return h(
|
|
238
411
|
props.tag,
|
|
239
412
|
{
|
|
240
413
|
style: {
|
|
241
414
|
position: "absolute",
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
left: `${animateProps.left}px`
|
|
415
|
+
width: `${itemWidth}px`,
|
|
416
|
+
height: `${itemHeight}px`,
|
|
417
|
+
top: `${position.value.top}px`,
|
|
418
|
+
left: `${position.value.left}px`
|
|
247
419
|
},
|
|
248
420
|
"data-grid-index": props.index,
|
|
249
421
|
"data-grid-main": isMain.value
|
|
250
422
|
},
|
|
251
|
-
// Pass all slot props
|
|
252
423
|
slots.default?.(slotProps.value)
|
|
253
424
|
);
|
|
254
425
|
}
|
|
255
426
|
return h(
|
|
256
427
|
motion.div,
|
|
257
428
|
{
|
|
258
|
-
|
|
259
|
-
animate: animateProps,
|
|
260
|
-
transition: {
|
|
261
|
-
type: springConfig.type,
|
|
262
|
-
stiffness: springConfig.stiffness,
|
|
263
|
-
damping: springConfig.damping
|
|
264
|
-
},
|
|
429
|
+
key: `grid-${props.index}`,
|
|
265
430
|
style: {
|
|
266
|
-
position: "absolute"
|
|
431
|
+
position: "absolute",
|
|
432
|
+
top: 0,
|
|
433
|
+
left: 0,
|
|
434
|
+
x: gridX,
|
|
435
|
+
y: gridY,
|
|
436
|
+
width: `${itemWidth}px`,
|
|
437
|
+
height: `${itemHeight}px`
|
|
267
438
|
},
|
|
268
439
|
"data-grid-index": props.index,
|
|
269
440
|
"data-grid-main": isMain.value
|
|
270
441
|
},
|
|
271
|
-
// Pass all slot props
|
|
272
442
|
() => slots.default?.(slotProps.value)
|
|
273
443
|
);
|
|
274
444
|
};
|
|
@@ -313,16 +483,26 @@ const GridOverlay = defineComponent({
|
|
|
313
483
|
const FloatingGridItem = defineComponent({
|
|
314
484
|
name: "FloatingGridItem",
|
|
315
485
|
props: {
|
|
316
|
-
/** Width of the floating item */
|
|
486
|
+
/** Width of the floating item (px). Overridden by `breakpoints` when provided. */
|
|
317
487
|
width: {
|
|
318
488
|
type: Number,
|
|
319
489
|
default: 120
|
|
320
490
|
},
|
|
321
|
-
/** Height of the floating item */
|
|
491
|
+
/** Height of the floating item (px). Overridden by `breakpoints` when provided. */
|
|
322
492
|
height: {
|
|
323
493
|
type: Number,
|
|
324
494
|
default: 160
|
|
325
495
|
},
|
|
496
|
+
/**
|
|
497
|
+
* Responsive breakpoints for PiP sizing.
|
|
498
|
+
* When provided, width/height auto-adjust based on container width.
|
|
499
|
+
* Overrides the fixed `width`/`height` props.
|
|
500
|
+
* Use `DEFAULT_FLOAT_BREAKPOINTS` for a ready-made 5-level responsive config.
|
|
501
|
+
*/
|
|
502
|
+
breakpoints: {
|
|
503
|
+
type: Array,
|
|
504
|
+
default: void 0
|
|
505
|
+
},
|
|
326
506
|
/** Initial position (x, y from container edges) */
|
|
327
507
|
initialPosition: {
|
|
328
508
|
type: Object,
|
|
@@ -363,10 +543,14 @@ const FloatingGridItem = defineComponent({
|
|
|
363
543
|
}
|
|
364
544
|
const { dimensions } = context;
|
|
365
545
|
const currentAnchor = ref(props.anchor);
|
|
366
|
-
const
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
546
|
+
const effectiveSize = computed(() => {
|
|
547
|
+
if (props.breakpoints && props.breakpoints.length > 0 && dimensions.value.width > 0) {
|
|
548
|
+
return resolveFloatSize(dimensions.value.width, props.breakpoints);
|
|
549
|
+
}
|
|
550
|
+
return { width: props.width, height: props.height };
|
|
551
|
+
});
|
|
552
|
+
const x = useMotionValue(0);
|
|
553
|
+
const y = useMotionValue(0);
|
|
370
554
|
const isInitialized = ref(false);
|
|
371
555
|
const containerDimensions = computed(() => ({
|
|
372
556
|
width: dimensions.value.width,
|
|
@@ -375,21 +559,23 @@ const FloatingGridItem = defineComponent({
|
|
|
375
559
|
const getCornerPosition = (corner) => {
|
|
376
560
|
const padding = props.edgePadding + props.initialPosition.x;
|
|
377
561
|
const dims = containerDimensions.value;
|
|
562
|
+
const ew = effectiveSize.value.width;
|
|
563
|
+
const eh = effectiveSize.value.height;
|
|
378
564
|
switch (corner) {
|
|
379
565
|
case "top-left":
|
|
380
566
|
return { x: padding, y: padding };
|
|
381
567
|
case "top-right":
|
|
382
|
-
return { x: dims.width -
|
|
568
|
+
return { x: dims.width - ew - padding, y: padding };
|
|
383
569
|
case "bottom-left":
|
|
384
|
-
return { x: padding, y: dims.height -
|
|
570
|
+
return { x: padding, y: dims.height - eh - padding };
|
|
385
571
|
case "bottom-right":
|
|
386
572
|
default:
|
|
387
|
-
return { x: dims.width -
|
|
573
|
+
return { x: dims.width - ew - padding, y: dims.height - eh - padding };
|
|
388
574
|
}
|
|
389
575
|
};
|
|
390
|
-
const findNearestCorner = (
|
|
391
|
-
const centerX =
|
|
392
|
-
const centerY =
|
|
576
|
+
const findNearestCorner = (posX, posY) => {
|
|
577
|
+
const centerX = posX + effectiveSize.value.width / 2;
|
|
578
|
+
const centerY = posY + effectiveSize.value.height / 2;
|
|
393
579
|
const dims = containerDimensions.value;
|
|
394
580
|
const containerCenterX = dims.width / 2;
|
|
395
581
|
const containerCenterY = dims.height / 2;
|
|
@@ -403,78 +589,95 @@ const FloatingGridItem = defineComponent({
|
|
|
403
589
|
return "bottom-left";
|
|
404
590
|
return "bottom-right";
|
|
405
591
|
};
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
592
|
+
watch(
|
|
593
|
+
[() => containerDimensions.value.width, () => containerDimensions.value.height],
|
|
594
|
+
([w, h2]) => {
|
|
595
|
+
if (w > 0 && h2 > 0 && !isInitialized.value) {
|
|
596
|
+
const pos = getCornerPosition(currentAnchor.value);
|
|
597
|
+
x.set(pos.x);
|
|
598
|
+
y.set(pos.y);
|
|
599
|
+
isInitialized.value = true;
|
|
600
|
+
}
|
|
601
|
+
},
|
|
602
|
+
{ immediate: true }
|
|
603
|
+
);
|
|
604
|
+
watch(
|
|
605
|
+
[
|
|
606
|
+
() => props.anchor,
|
|
607
|
+
() => containerDimensions.value.width,
|
|
608
|
+
() => containerDimensions.value.height
|
|
609
|
+
],
|
|
610
|
+
([newAnchor, w, h2]) => {
|
|
611
|
+
if (isInitialized.value && w > 0 && h2 > 0 && newAnchor !== currentAnchor.value) {
|
|
612
|
+
currentAnchor.value = newAnchor;
|
|
613
|
+
const pos = getCornerPosition(newAnchor);
|
|
614
|
+
const springCfg = { type: "spring", stiffness: 400, damping: 30 };
|
|
615
|
+
animate(x, pos.x, springCfg);
|
|
616
|
+
animate(y, pos.y, springCfg);
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
);
|
|
620
|
+
watch(
|
|
621
|
+
[() => effectiveSize.value.width, () => effectiveSize.value.height],
|
|
622
|
+
() => {
|
|
623
|
+
if (isInitialized.value && containerDimensions.value.width > 0 && containerDimensions.value.height > 0) {
|
|
624
|
+
const pos = getCornerPosition(currentAnchor.value);
|
|
625
|
+
const springCfg = { type: "spring", stiffness: 400, damping: 30 };
|
|
626
|
+
animate(x, pos.x, springCfg);
|
|
627
|
+
animate(y, pos.y, springCfg);
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
);
|
|
439
631
|
return () => {
|
|
440
632
|
const dims = containerDimensions.value;
|
|
441
633
|
if (!props.visible || dims.width === 0 || dims.height === 0) {
|
|
442
634
|
return null;
|
|
443
635
|
}
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
636
|
+
const ew = effectiveSize.value.width;
|
|
637
|
+
const eh = effectiveSize.value.height;
|
|
638
|
+
const padding = props.edgePadding + props.initialPosition.x;
|
|
639
|
+
const dragConstraints = {
|
|
640
|
+
left: padding,
|
|
641
|
+
right: dims.width - ew - padding,
|
|
642
|
+
top: padding,
|
|
643
|
+
bottom: dims.height - eh - padding
|
|
644
|
+
};
|
|
645
|
+
const handleDragEnd = () => {
|
|
646
|
+
const currentX = x.get();
|
|
647
|
+
const currentY = y.get();
|
|
648
|
+
const nearestCorner = findNearestCorner(currentX, currentY);
|
|
649
|
+
currentAnchor.value = nearestCorner;
|
|
650
|
+
emit("anchorChange", nearestCorner);
|
|
651
|
+
const snapPos = getCornerPosition(nearestCorner);
|
|
652
|
+
const springCfg = { type: "spring", stiffness: 400, damping: 30 };
|
|
653
|
+
animate(x, snapPos.x, springCfg);
|
|
654
|
+
animate(y, snapPos.y, springCfg);
|
|
655
|
+
};
|
|
448
656
|
return h(
|
|
449
657
|
motion.div,
|
|
450
658
|
{
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
scale: isDragging.value ? 1.05 : 1
|
|
456
|
-
},
|
|
457
|
-
transition: isDragging.value ? { duration: 0 } : { type: "spring", stiffness: 400, damping: 30 },
|
|
659
|
+
drag: true,
|
|
660
|
+
dragMomentum: false,
|
|
661
|
+
dragElastic: 0.1,
|
|
662
|
+
dragConstraints,
|
|
458
663
|
style: {
|
|
459
664
|
position: "absolute",
|
|
460
|
-
width: `${
|
|
461
|
-
height: `${
|
|
665
|
+
width: `${ew}px`,
|
|
666
|
+
height: `${eh}px`,
|
|
462
667
|
borderRadius: `${props.borderRadius}px`,
|
|
463
|
-
boxShadow:
|
|
668
|
+
boxShadow: props.boxShadow,
|
|
464
669
|
overflow: "hidden",
|
|
465
|
-
cursor:
|
|
670
|
+
cursor: "grab",
|
|
466
671
|
zIndex: 100,
|
|
467
672
|
touchAction: "none",
|
|
468
673
|
left: 0,
|
|
469
|
-
top: 0
|
|
674
|
+
top: 0,
|
|
675
|
+
x,
|
|
676
|
+
y
|
|
470
677
|
},
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
onMouseleave: handleDragEnd,
|
|
475
|
-
onTouchstart: handleDragStart,
|
|
476
|
-
onTouchmove: handleDragMove,
|
|
477
|
-
onTouchend: handleDragEnd
|
|
678
|
+
whileDrag: { cursor: "grabbing", scale: 1.05, boxShadow: "0 8px 32px rgba(0,0,0,0.4)" },
|
|
679
|
+
transition: { type: "spring", stiffness: 400, damping: 30 },
|
|
680
|
+
onDragEnd: handleDragEnd
|
|
478
681
|
},
|
|
479
682
|
slots.default?.()
|
|
480
683
|
);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thangdevalone/meet-layout-grid-vue",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.3",
|
|
4
4
|
"description": "Vue 3 integration for meet-layout-grid with Motion animations",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"dependencies": {
|
|
44
44
|
"@vueuse/core": "^10.7.0",
|
|
45
45
|
"motion-v": "^1.0.0",
|
|
46
|
-
"@thangdevalone/meet-layout-grid-core": "1.3.
|
|
46
|
+
"@thangdevalone/meet-layout-grid-core": "1.3.3"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"vue": "^3.4.0",
|