ropav 0.0.12 → 0.0.13

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.
@@ -1,6 +1,6 @@
1
1
  import { Component, HTMLAttributes, Ref } from 'vue';
2
2
  import { StylesApiProps } from '../../styles-api.js';
3
- import { FloatingCollisionPadding, FloatingOffset, FloatingOffsetOptions, FloatingPositionProps, FloatingStrategy, FloatingTarget, FloatingVirtualElement, TeleportProps } from '../floating/types.js';
3
+ import { FloatingAutoUpdateOptions, FloatingCollisionPadding, FloatingFlipOptions, FloatingOffset, FloatingOffsetOptions, FloatingPositionProps, FloatingStrategy, FloatingTarget, FloatingVirtualElement, TeleportProps } from '../floating/types.js';
4
4
  export declare const dropdownMenuParts: readonly ["root", "trigger", "content", "item", "label", "shortcut", "submenu", "submenuIndicator", "empty"];
5
5
  export type DropdownMenuPart = (typeof dropdownMenuParts)[number];
6
6
  export type DropdownMenuPlacement = 'top-start' | 'top' | 'top-end' | 'right-start' | 'right' | 'right-end' | 'bottom-start' | 'bottom' | 'bottom-end' | 'left-start' | 'left' | 'left-end';
@@ -177,8 +177,10 @@ export interface DropdownMenuContentPrimitiveProps {
177
177
  offset?: DropdownMenuOffset;
178
178
  strategy?: FloatingStrategy;
179
179
  flip?: boolean;
180
+ flipOptions?: FloatingFlipOptions;
180
181
  shift?: boolean;
181
182
  collisionPadding?: FloatingCollisionPadding;
183
+ autoUpdateOptions?: FloatingAutoUpdateOptions;
182
184
  arrow?: boolean;
183
185
  /** @deprecated Use `flip` and `shift` instead. */
184
186
  avoidCollisions?: boolean;
@@ -33,8 +33,10 @@ export interface DropdownMenuRenderContext {
33
33
  getSubmenuPlacement: () => DropdownMenuPlacement;
34
34
  getStrategy: () => NonNullable<DropdownMenuProps['strategy']>;
35
35
  getFlip: () => boolean;
36
+ getFlipOptions: () => DropdownMenuProps['flipOptions'];
36
37
  getShift: () => boolean;
37
38
  getCollisionPadding: () => NonNullable<DropdownMenuProps['collisionPadding']>;
39
+ getAutoUpdateOptions: () => DropdownMenuProps['autoUpdateOptions'];
38
40
  }
39
41
  export declare function useDropdownMenuRenderItems({ props, actualPlacement, items, getItemId, getSubmenuId, getMenuActiveDescendant, getItemElement, isItemFocused, isSubmenuOpen, activateItem, focusHoveredItem, selectItem, openSubmenu, closeSubmenu, close, }: UseDropdownMenuRenderItemsOptions): {
40
42
  renderedItems: import('vue').ComputedRef<DropdownMenuRenderedItem[]>;
@@ -1,3 +1,3 @@
1
1
  export { useHoverDisclosure } from './useHoverDisclosure.js';
2
2
  export { useFloatingPosition } from './useFloatingPosition.js';
3
- export type { FloatingAlignment, FloatingCollisionPadding, FloatingOffset, FloatingOffsetOptions, FloatingPlacement, FloatingPositionProps, FloatingReference, FloatingSide, FloatingStrategy, FloatingTarget, FloatingVirtualElement, HoverDisclosureContentProps, HoverDisclosureContentTarget, HoverDisclosureInteractionTarget, HoverDisclosureOpenChangeDetails, HoverDisclosureOpenChangeReason, HoverDisclosureOption, HoverDisclosureState, HoverDisclosureTouchBehavior, HoverDisclosureTriggerProps, TeleportProps, TeleportTarget, TeleportTargetValue, UseHoverDisclosureOptions, UseHoverDisclosureReturn, UseFloatingPositionOptions, UseFloatingPositionReturn, } from './types.js';
3
+ export type { FloatingAlignment, FloatingAutoUpdateOptions, FloatingCollisionPadding, FloatingFlipFallbackStrategy, FloatingFlipOptions, FloatingOffset, FloatingOffsetOptions, FloatingPlacement, FloatingPositionProps, FloatingReference, FloatingSide, FloatingStrategy, FloatingTarget, FloatingVirtualElement, HoverDisclosureContentProps, HoverDisclosureContentTarget, HoverDisclosureInteractionTarget, HoverDisclosureOpenChangeDetails, HoverDisclosureOpenChangeReason, HoverDisclosureOption, HoverDisclosureState, HoverDisclosureTouchBehavior, HoverDisclosureTriggerProps, TeleportProps, TeleportTarget, TeleportTargetValue, UseHoverDisclosureOptions, UseHoverDisclosureReturn, UseFloatingPositionOptions, UseFloatingPositionReturn, } from './types.js';
@@ -10,6 +10,13 @@ export interface FloatingOffsetOptions {
10
10
  }
11
11
  export type FloatingOffset = number | FloatingOffsetOptions;
12
12
  export type FloatingCollisionPadding = number | Partial<Record<FloatingSide, number>>;
13
+ export type FloatingFlipFallbackStrategy = 'bestFit' | 'initialPlacement';
14
+ export interface FloatingFlipOptions {
15
+ fallbackStrategy?: FloatingFlipFallbackStrategy;
16
+ }
17
+ export interface FloatingAutoUpdateOptions {
18
+ animationFrame?: boolean;
19
+ }
13
20
  export type FloatingReference = Element | VirtualElement;
14
21
  export type FloatingTarget = string | FloatingReference | Ref<FloatingReference | null | undefined>;
15
22
  export interface FloatingPositionProps<TPlacement extends FloatingPlacement = FloatingPlacement> extends TeleportProps {
@@ -18,8 +25,10 @@ export interface FloatingPositionProps<TPlacement extends FloatingPlacement = Fl
18
25
  strategy?: FloatingStrategy;
19
26
  offset?: FloatingOffset;
20
27
  flip?: boolean;
28
+ flipOptions?: FloatingFlipOptions;
21
29
  shift?: boolean;
22
30
  collisionPadding?: FloatingCollisionPadding;
31
+ autoUpdateOptions?: FloatingAutoUpdateOptions;
23
32
  arrow?: boolean;
24
33
  }
25
34
  export interface UseFloatingPositionOptions {
@@ -31,8 +40,10 @@ export interface UseFloatingPositionOptions {
31
40
  strategy?: MaybeRefOrGetter<FloatingStrategy | undefined>;
32
41
  offset?: MaybeRefOrGetter<FloatingOffset | undefined>;
33
42
  flip?: MaybeRefOrGetter<boolean | undefined>;
43
+ flipOptions?: MaybeRefOrGetter<FloatingFlipOptions | undefined>;
34
44
  shift?: MaybeRefOrGetter<boolean | undefined>;
35
45
  collisionPadding?: MaybeRefOrGetter<FloatingCollisionPadding | undefined>;
46
+ autoUpdateOptions?: MaybeRefOrGetter<FloatingAutoUpdateOptions | undefined>;
36
47
  restartKey?: MaybeRefOrGetter<unknown>;
37
48
  }
38
49
  export interface UseFloatingPositionReturn {
@@ -434,8 +434,10 @@ function useDropdownMenuPrimitiveContent(props, attrs, events, submenu) {
434
434
  strategy: () => props.strategy ?? "absolute",
435
435
  offset: () => props.offset,
436
436
  flip: () => props.avoidCollisions !== false && props.flip !== false,
437
+ flipOptions: () => props.flipOptions,
437
438
  shift: () => props.avoidCollisions !== false && props.shift !== false,
438
439
  collisionPadding: () => props.collisionPadding ?? 8,
440
+ autoUpdateOptions: () => props.autoUpdateOptions,
439
441
  restartKey: teleportPositioningKey
440
442
  });
441
443
  watch(floating.actualPlacement, (value) => {
@@ -584,11 +586,13 @@ var dropdown_menu_content_default = /* @__PURE__ */ defineVaporComponent({
584
586
  type: Boolean,
585
587
  default: true
586
588
  },
589
+ flipOptions: {},
587
590
  shift: {
588
591
  type: Boolean,
589
592
  default: true
590
593
  },
591
594
  collisionPadding: { default: 8 },
595
+ autoUpdateOptions: {},
592
596
  arrow: {
593
597
  type: Boolean,
594
598
  default: false
@@ -1289,11 +1293,13 @@ var dropdown_menu_sub_content_default = /* @__PURE__ */ defineVaporComponent({
1289
1293
  type: Boolean,
1290
1294
  default: true
1291
1295
  },
1296
+ flipOptions: {},
1292
1297
  shift: {
1293
1298
  type: Boolean,
1294
1299
  default: true
1295
1300
  },
1296
1301
  collisionPadding: { default: 8 },
1302
+ autoUpdateOptions: {},
1297
1303
  avoidCollisions: {
1298
1304
  type: Boolean,
1299
1305
  default: true
@@ -1599,8 +1605,10 @@ var dropdown_menu_item_row_default = /* @__PURE__ */ defineVaporComponent({
1599
1605
  strategy: props.context.getStrategy,
1600
1606
  offset: () => 4,
1601
1607
  flip: props.context.getFlip,
1608
+ flipOptions: props.context.getFlipOptions,
1602
1609
  shift: props.context.getShift,
1603
- collisionPadding: props.context.getCollisionPadding
1610
+ collisionPadding: props.context.getCollisionPadding,
1611
+ autoUpdateOptions: props.context.getAutoUpdateOptions
1604
1612
  });
1605
1613
  const submenuProps = computed(() => props.context.getSubmenuProps(props.item, path.value, true));
1606
1614
  const publicSubmenuProps = computed(() => ({
@@ -2193,8 +2201,10 @@ function useDropdownMenuPortalPosition(options) {
2193
2201
  strategy: () => options.props.strategy ?? "absolute",
2194
2202
  offset: () => options.props.offset,
2195
2203
  flip: () => options.props.flip !== false,
2204
+ flipOptions: () => options.props.flipOptions,
2196
2205
  shift: () => options.props.shift !== false,
2197
2206
  collisionPadding: () => options.props.collisionPadding ?? 8,
2207
+ autoUpdateOptions: () => options.props.autoUpdateOptions,
2198
2208
  restartKey: options.restartKey
2199
2209
  });
2200
2210
  return {
@@ -2296,8 +2306,10 @@ function useDropdownMenuRenderItems({ props, actualPlacement, items, getItemId,
2296
2306
  getSubmenuPlacement: () => actualPlacement.value.endsWith("end") ? "left-start" : "right-start",
2297
2307
  getStrategy: () => props.strategy ?? "absolute",
2298
2308
  getFlip: () => props.flip !== false,
2309
+ getFlipOptions: () => props.flipOptions,
2299
2310
  getShift: () => props.shift !== false,
2300
- getCollisionPadding: () => props.collisionPadding ?? 8
2311
+ getCollisionPadding: () => props.collisionPadding ?? 8,
2312
+ getAutoUpdateOptions: () => props.autoUpdateOptions
2301
2313
  },
2302
2314
  getItemProps,
2303
2315
  getItemSlotProps
@@ -2617,11 +2629,13 @@ var dropdown_menu_default = /* @__PURE__ */ defineVaporComponent({
2617
2629
  type: Boolean,
2618
2630
  default: true
2619
2631
  },
2632
+ flipOptions: {},
2620
2633
  shift: {
2621
2634
  type: Boolean,
2622
2635
  default: true
2623
2636
  },
2624
2637
  collisionPadding: { default: 8 },
2638
+ autoUpdateOptions: {},
2625
2639
  arrow: {
2626
2640
  type: Boolean,
2627
2641
  default: false
package/dist/popover.js CHANGED
@@ -96,8 +96,10 @@ function usePopover(props, emitOpenChange) {
96
96
  strategy: () => props.strategy ?? "absolute",
97
97
  offset: () => props.offset,
98
98
  flip: () => props.flip !== false,
99
+ flipOptions: () => props.flipOptions,
99
100
  shift: () => props.shift !== false,
100
101
  collisionPadding: () => props.collisionPadding ?? 8,
102
+ autoUpdateOptions: () => props.autoUpdateOptions,
101
103
  restartKey: () => [
102
104
  Boolean(props.teleport),
103
105
  teleportTo.value,
@@ -344,11 +346,13 @@ var popover_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE
344
346
  type: Boolean,
345
347
  default: true
346
348
  },
349
+ flipOptions: {},
347
350
  shift: {
348
351
  type: Boolean,
349
352
  default: true
350
353
  },
351
354
  collisionPadding: { default: 8 },
355
+ autoUpdateOptions: {},
352
356
  arrow: {
353
357
  type: Boolean,
354
358
  default: false
package/dist/tooltip.js CHANGED
@@ -111,8 +111,10 @@ function useTooltip(props, emitOpenChange) {
111
111
  strategy: () => props.strategy ?? "absolute",
112
112
  offset: () => props.offset,
113
113
  flip: () => props.flip !== false,
114
+ flipOptions: () => props.flipOptions,
114
115
  shift: () => props.shift !== false,
115
116
  collisionPadding: () => props.collisionPadding ?? 8,
117
+ autoUpdateOptions: () => props.autoUpdateOptions,
116
118
  restartKey: () => [
117
119
  Boolean(props.teleport),
118
120
  teleportTo.value,
@@ -240,11 +242,13 @@ var tooltip_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE
240
242
  type: Boolean,
241
243
  default: true
242
244
  },
245
+ flipOptions: {},
243
246
  shift: {
244
247
  type: Boolean,
245
248
  default: true
246
249
  },
247
250
  collisionPadding: { default: 8 },
251
+ autoUpdateOptions: {},
248
252
  arrow: {
249
253
  type: Boolean,
250
254
  default: false
@@ -1213,12 +1213,18 @@ function useFloatingPosition(options) {
1213
1213
  function getFlip() {
1214
1214
  return toValue(options.flip) !== false;
1215
1215
  }
1216
+ function getFlipFallbackStrategy() {
1217
+ return toValue(options.flipOptions)?.fallbackStrategy;
1218
+ }
1216
1219
  function getShift() {
1217
1220
  return toValue(options.shift) !== false;
1218
1221
  }
1219
1222
  function getCollisionPadding() {
1220
1223
  return toValue(options.collisionPadding) ?? DEFAULT_COLLISION_PADDING;
1221
1224
  }
1225
+ function getAutoUpdateAnimationFrame() {
1226
+ return toValue(options.autoUpdateOptions)?.animationFrame;
1227
+ }
1222
1228
  function getHiddenStyle() {
1223
1229
  return {
1224
1230
  position: getStrategy(),
@@ -1242,7 +1248,11 @@ function useFloatingPosition(options) {
1242
1248
  function getMiddleware() {
1243
1249
  const middleware = [offset(getOffset())];
1244
1250
  const padding = getCollisionPadding();
1245
- if (getFlip()) middleware.push(flip({ padding }));
1251
+ const fallbackStrategy = getFlipFallbackStrategy();
1252
+ if (getFlip()) middleware.push(flip({
1253
+ padding,
1254
+ ...fallbackStrategy == null ? {} : { fallbackStrategy }
1255
+ }));
1246
1256
  if (getShift()) middleware.push(shift({ padding }));
1247
1257
  const arrow$2 = getArrow();
1248
1258
  if (arrow$2) middleware.push(arrow({
@@ -1285,7 +1295,9 @@ function useFloatingPosition(options) {
1285
1295
  const reference = getReference();
1286
1296
  const floating = getFloating();
1287
1297
  if (currentGeneration !== generation || !reference || !floating || !getOpen()) return;
1288
- cleanup = autoUpdate(reference, floating, () => void update());
1298
+ const updatePosition = () => void update();
1299
+ const animationFrame = getAutoUpdateAnimationFrame();
1300
+ cleanup = animationFrame == null ? autoUpdate(reference, floating, updatePosition) : autoUpdate(reference, floating, updatePosition, { animationFrame });
1289
1301
  });
1290
1302
  }
1291
1303
  watch([
@@ -1297,8 +1309,10 @@ function useFloatingPosition(options) {
1297
1309
  getStrategy,
1298
1310
  getOffset,
1299
1311
  getFlip,
1312
+ getFlipFallbackStrategy,
1300
1313
  getShift,
1301
1314
  getCollisionPadding,
1315
+ getAutoUpdateAnimationFrame,
1302
1316
  () => toValue(options.restartKey)
1303
1317
  ], start, {
1304
1318
  flush: "post",
@@ -49,19 +49,30 @@ const { actualPlacement, arrowStyle, floatingStyle } = useFloatingPosition({
49
49
 
50
50
  The composable accepts plain values, refs, computed refs or getters for reactive options.
51
51
 
52
- | Option | Default | Description |
53
- | ------------------ | ---------- | -------------------------------------------------------------- |
54
- | `reference` | required | Element or virtual element used as the anchor. |
55
- | `floating` | required | Floating HTML element. |
56
- | `arrow` | — | Optional arrow HTML element. |
57
- | `open` | `true` | Suspends positioning and auto-updates when false. |
58
- | `placement` | `bottom` | Preferred side and optional alignment. |
59
- | `strategy` | `absolute` | CSS positioning strategy: `absolute` or `fixed`. |
60
- | `offset` | `8` | Main/cross-axis distance from the reference. |
61
- | `flip` | `true` | Tries the opposite side when space is insufficient. |
62
- | `shift` | `true` | Keeps the floating element inside the collision boundary. |
63
- | `collisionPadding` | `8` | Padding between the floating element and viewport boundary. |
64
- | `restartKey` | | Rebinds auto-update observers when its reactive value changes. |
52
+ | Option | Default | Description |
53
+ | ---------------------------------- | ---------- | ---------------------------------------------------------------------- |
54
+ | `reference` | required | Element or virtual element used as the anchor. |
55
+ | `floating` | required | Floating HTML element. |
56
+ | `arrow` | — | Optional arrow HTML element. |
57
+ | `open` | `true` | Suspends positioning and auto-updates when false. |
58
+ | `placement` | `bottom` | Preferred side and optional alignment. |
59
+ | `strategy` | `absolute` | CSS positioning strategy: `absolute` or `fixed`. |
60
+ | `offset` | `8` | Main/cross-axis distance from the reference. |
61
+ | `flip` | `true` | Tries the opposite side when space is insufficient. |
62
+ | `flipOptions.fallbackStrategy` | `bestFit` | Chooses the best fit or preserves the initial placement when none fit. |
63
+ | `shift` | `true` | Keeps the floating element inside the collision boundary. |
64
+ | `collisionPadding` | `8` | Padding between the floating element and viewport boundary. |
65
+ | `autoUpdateOptions.animationFrame` | `false` | Tracks transform animations and detached nested floating contexts. |
66
+ | `restartKey` | — | Rebinds auto-update observers when its reactive value changes. |
67
+
68
+ Use `autoUpdateOptions.animationFrame` sparingly. It checks the reference position every animation
69
+ frame and is intended for references moving with CSS transforms or nested floating elements outside
70
+ their ancestor's scrolling context. The animation-frame loop only runs while positioning is open.
71
+
72
+ `Popover`, `Tooltip`, `DropdownMenu`, `DropdownMenuContent` and `DropdownMenuSubContent` accept the
73
+ same `flipOptions` and `autoUpdateOptions` objects. On the data-driven `DropdownMenu`, the options
74
+ also apply to its open submenus. Each open floating element using `animationFrame: true` runs its own
75
+ animation-frame loop.
65
76
 
66
77
  The return value contains readonly `actualPlacement`, `floatingStyle`, `arrowStyle` and
67
78
  `isPositioned` refs, plus an async `update()` method for content-driven layout changes.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ropav",
3
- "version": "0.0.12",
3
+ "version": "0.0.13",
4
4
  "type": "module",
5
5
  "packageManager": "pnpm@11.10.0",
6
6
  "engines": {