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