@thangdevalone/meet-layout-grid-vue 1.3.2 → 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 +240 -150
- 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 +242 -154
- 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, {
|
|
@@ -214,11 +236,11 @@ const GridItem = defineComponent({
|
|
|
214
236
|
});
|
|
215
237
|
const isFloat = computed(() => grid.value.floatIndex === props.index);
|
|
216
238
|
const floatDims = computed(() => grid.value.floatDimensions ?? { width: 120, height: 160 });
|
|
217
|
-
const floatAnchor = ref(
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
const
|
|
221
|
-
const
|
|
239
|
+
const floatAnchor = ref(
|
|
240
|
+
"bottom-right"
|
|
241
|
+
);
|
|
242
|
+
const x = useMotionValue(0);
|
|
243
|
+
const y = useMotionValue(0);
|
|
222
244
|
const floatInitialized = ref(false);
|
|
223
245
|
const getFloatCornerPos = (corner) => {
|
|
224
246
|
const padding = 12;
|
|
@@ -237,11 +259,11 @@ const GridItem = defineComponent({
|
|
|
237
259
|
return { x: dims.width - fw - padding, y: dims.height - fh - padding };
|
|
238
260
|
}
|
|
239
261
|
};
|
|
240
|
-
const findFloatNearestCorner = (
|
|
262
|
+
const findFloatNearestCorner = (posX, posY) => {
|
|
241
263
|
const fw = floatDims.value.width;
|
|
242
264
|
const fh = floatDims.value.height;
|
|
243
|
-
const centerX =
|
|
244
|
-
const centerY =
|
|
265
|
+
const centerX = posX + fw / 2;
|
|
266
|
+
const centerY = posY + fh / 2;
|
|
245
267
|
const dims = containerDimensions.value;
|
|
246
268
|
const isLeft = centerX < dims.width / 2;
|
|
247
269
|
const isTop = centerY < dims.height / 2;
|
|
@@ -253,46 +275,77 @@ const GridItem = defineComponent({
|
|
|
253
275
|
return "bottom-left";
|
|
254
276
|
return "bottom-right";
|
|
255
277
|
};
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
floatDragOffset.value = { x: 0, y: 0 };
|
|
285
|
-
};
|
|
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
|
+
);
|
|
286
306
|
const isLastVisibleOther = computed(() => {
|
|
287
307
|
const lastVisibleOthersIndex = grid.value.getLastVisibleOthersIndex();
|
|
288
308
|
return props.index === lastVisibleOthersIndex;
|
|
289
309
|
});
|
|
290
310
|
const hiddenCount = computed(() => grid.value.hiddenCount);
|
|
291
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
|
+
);
|
|
292
344
|
const slotProps = computed(() => ({
|
|
293
345
|
contentDimensions: contentDimensions.value,
|
|
294
346
|
isLastVisibleOther: isLastVisibleOther.value,
|
|
295
|
-
hiddenCount: hiddenCount.value
|
|
347
|
+
hiddenCount: hiddenCount.value,
|
|
348
|
+
isFloat: isFloat.value
|
|
296
349
|
}));
|
|
297
350
|
return () => {
|
|
298
351
|
if (isHidden.value) {
|
|
@@ -302,88 +355,90 @@ const GridItem = defineComponent({
|
|
|
302
355
|
const dims = containerDimensions.value;
|
|
303
356
|
if (dims.width === 0 || dims.height === 0)
|
|
304
357
|
return null;
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
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
|
+
};
|
|
309
374
|
return h(
|
|
310
375
|
motion.div,
|
|
311
376
|
{
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
transition: floatDragging.value ? { duration: 0 } : { type: "spring", stiffness: 400, damping: 30 },
|
|
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,
|
|
319
383
|
style: {
|
|
320
384
|
position: "absolute",
|
|
321
385
|
width: `${floatDims.value.width}px`,
|
|
322
386
|
height: `${floatDims.value.height}px`,
|
|
323
387
|
borderRadius: "12px",
|
|
324
|
-
boxShadow:
|
|
388
|
+
boxShadow: "0 4px 20px rgba(0,0,0,0.3)",
|
|
325
389
|
overflow: "hidden",
|
|
326
|
-
cursor:
|
|
390
|
+
cursor: "grab",
|
|
327
391
|
zIndex: 100,
|
|
328
392
|
touchAction: "none",
|
|
329
393
|
left: 0,
|
|
330
|
-
top: 0
|
|
394
|
+
top: 0,
|
|
395
|
+
x,
|
|
396
|
+
y
|
|
331
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 },
|
|
332
400
|
"data-grid-index": props.index,
|
|
333
401
|
"data-grid-float": true,
|
|
334
|
-
|
|
335
|
-
onMousemove: handleFloatDragMove,
|
|
336
|
-
onMouseup: handleFloatDragEnd,
|
|
337
|
-
onMouseleave: handleFloatDragEnd,
|
|
338
|
-
onTouchstart: handleFloatDragStart,
|
|
339
|
-
onTouchmove: handleFloatDragMove,
|
|
340
|
-
onTouchend: handleFloatDragEnd
|
|
402
|
+
onDragEnd: handleDragEnd
|
|
341
403
|
},
|
|
342
404
|
() => slots.default?.(slotProps.value)
|
|
343
405
|
);
|
|
344
406
|
}
|
|
345
|
-
const
|
|
346
|
-
|
|
347
|
-
height: dimensions.value.height,
|
|
348
|
-
top: position.value.top,
|
|
349
|
-
left: position.value.left
|
|
350
|
-
};
|
|
407
|
+
const itemWidth = dimensions.value.width;
|
|
408
|
+
const itemHeight = dimensions.value.height;
|
|
351
409
|
if (props.disableAnimation) {
|
|
352
410
|
return h(
|
|
353
411
|
props.tag,
|
|
354
412
|
{
|
|
355
413
|
style: {
|
|
356
414
|
position: "absolute",
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
left: `${animateProps.left}px`
|
|
415
|
+
width: `${itemWidth}px`,
|
|
416
|
+
height: `${itemHeight}px`,
|
|
417
|
+
top: `${position.value.top}px`,
|
|
418
|
+
left: `${position.value.left}px`
|
|
362
419
|
},
|
|
363
420
|
"data-grid-index": props.index,
|
|
364
421
|
"data-grid-main": isMain.value
|
|
365
422
|
},
|
|
366
|
-
// Pass all slot props
|
|
367
423
|
slots.default?.(slotProps.value)
|
|
368
424
|
);
|
|
369
425
|
}
|
|
370
426
|
return h(
|
|
371
427
|
motion.div,
|
|
372
428
|
{
|
|
373
|
-
|
|
374
|
-
animate: animateProps,
|
|
375
|
-
transition: {
|
|
376
|
-
type: springConfig.type,
|
|
377
|
-
stiffness: springConfig.stiffness,
|
|
378
|
-
damping: springConfig.damping
|
|
379
|
-
},
|
|
429
|
+
key: `grid-${props.index}`,
|
|
380
430
|
style: {
|
|
381
|
-
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`
|
|
382
438
|
},
|
|
383
439
|
"data-grid-index": props.index,
|
|
384
440
|
"data-grid-main": isMain.value
|
|
385
441
|
},
|
|
386
|
-
// Pass all slot props
|
|
387
442
|
() => slots.default?.(slotProps.value)
|
|
388
443
|
);
|
|
389
444
|
};
|
|
@@ -428,16 +483,26 @@ const GridOverlay = defineComponent({
|
|
|
428
483
|
const FloatingGridItem = defineComponent({
|
|
429
484
|
name: "FloatingGridItem",
|
|
430
485
|
props: {
|
|
431
|
-
/** Width of the floating item */
|
|
486
|
+
/** Width of the floating item (px). Overridden by `breakpoints` when provided. */
|
|
432
487
|
width: {
|
|
433
488
|
type: Number,
|
|
434
489
|
default: 120
|
|
435
490
|
},
|
|
436
|
-
/** Height of the floating item */
|
|
491
|
+
/** Height of the floating item (px). Overridden by `breakpoints` when provided. */
|
|
437
492
|
height: {
|
|
438
493
|
type: Number,
|
|
439
494
|
default: 160
|
|
440
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
|
+
},
|
|
441
506
|
/** Initial position (x, y from container edges) */
|
|
442
507
|
initialPosition: {
|
|
443
508
|
type: Object,
|
|
@@ -478,10 +543,14 @@ const FloatingGridItem = defineComponent({
|
|
|
478
543
|
}
|
|
479
544
|
const { dimensions } = context;
|
|
480
545
|
const currentAnchor = ref(props.anchor);
|
|
481
|
-
const
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
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);
|
|
485
554
|
const isInitialized = ref(false);
|
|
486
555
|
const containerDimensions = computed(() => ({
|
|
487
556
|
width: dimensions.value.width,
|
|
@@ -490,21 +559,23 @@ const FloatingGridItem = defineComponent({
|
|
|
490
559
|
const getCornerPosition = (corner) => {
|
|
491
560
|
const padding = props.edgePadding + props.initialPosition.x;
|
|
492
561
|
const dims = containerDimensions.value;
|
|
562
|
+
const ew = effectiveSize.value.width;
|
|
563
|
+
const eh = effectiveSize.value.height;
|
|
493
564
|
switch (corner) {
|
|
494
565
|
case "top-left":
|
|
495
566
|
return { x: padding, y: padding };
|
|
496
567
|
case "top-right":
|
|
497
|
-
return { x: dims.width -
|
|
568
|
+
return { x: dims.width - ew - padding, y: padding };
|
|
498
569
|
case "bottom-left":
|
|
499
|
-
return { x: padding, y: dims.height -
|
|
570
|
+
return { x: padding, y: dims.height - eh - padding };
|
|
500
571
|
case "bottom-right":
|
|
501
572
|
default:
|
|
502
|
-
return { x: dims.width -
|
|
573
|
+
return { x: dims.width - ew - padding, y: dims.height - eh - padding };
|
|
503
574
|
}
|
|
504
575
|
};
|
|
505
|
-
const findNearestCorner = (
|
|
506
|
-
const centerX =
|
|
507
|
-
const centerY =
|
|
576
|
+
const findNearestCorner = (posX, posY) => {
|
|
577
|
+
const centerX = posX + effectiveSize.value.width / 2;
|
|
578
|
+
const centerY = posY + effectiveSize.value.height / 2;
|
|
508
579
|
const dims = containerDimensions.value;
|
|
509
580
|
const containerCenterX = dims.width / 2;
|
|
510
581
|
const containerCenterY = dims.height / 2;
|
|
@@ -518,78 +589,95 @@ const FloatingGridItem = defineComponent({
|
|
|
518
589
|
return "bottom-left";
|
|
519
590
|
return "bottom-right";
|
|
520
591
|
};
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
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
|
+
);
|
|
554
631
|
return () => {
|
|
555
632
|
const dims = containerDimensions.value;
|
|
556
633
|
if (!props.visible || dims.width === 0 || dims.height === 0) {
|
|
557
634
|
return null;
|
|
558
635
|
}
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
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
|
+
};
|
|
563
656
|
return h(
|
|
564
657
|
motion.div,
|
|
565
658
|
{
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
scale: isDragging.value ? 1.05 : 1
|
|
571
|
-
},
|
|
572
|
-
transition: isDragging.value ? { duration: 0 } : { type: "spring", stiffness: 400, damping: 30 },
|
|
659
|
+
drag: true,
|
|
660
|
+
dragMomentum: false,
|
|
661
|
+
dragElastic: 0.1,
|
|
662
|
+
dragConstraints,
|
|
573
663
|
style: {
|
|
574
664
|
position: "absolute",
|
|
575
|
-
width: `${
|
|
576
|
-
height: `${
|
|
665
|
+
width: `${ew}px`,
|
|
666
|
+
height: `${eh}px`,
|
|
577
667
|
borderRadius: `${props.borderRadius}px`,
|
|
578
|
-
boxShadow:
|
|
668
|
+
boxShadow: props.boxShadow,
|
|
579
669
|
overflow: "hidden",
|
|
580
|
-
cursor:
|
|
670
|
+
cursor: "grab",
|
|
581
671
|
zIndex: 100,
|
|
582
672
|
touchAction: "none",
|
|
583
673
|
left: 0,
|
|
584
|
-
top: 0
|
|
674
|
+
top: 0,
|
|
675
|
+
x,
|
|
676
|
+
y
|
|
585
677
|
},
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
onMouseleave: handleDragEnd,
|
|
590
|
-
onTouchstart: handleDragStart,
|
|
591
|
-
onTouchmove: handleDragMove,
|
|
592
|
-
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
|
|
593
681
|
},
|
|
594
682
|
slots.default?.()
|
|
595
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",
|