ropav 0.0.11 → 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.
Files changed (126) hide show
  1. package/README.md +3 -0
  2. package/dist/checkbox.css +32 -32
  3. package/dist/checkbox.js +33 -14
  4. package/dist/color-input.css +19 -19
  5. package/dist/color-input.js +35 -17
  6. package/dist/components/checkbox/types.d.ts +5 -1
  7. package/dist/components/checkbox/useCheckbox.d.ts +1 -1
  8. package/dist/components/color-input/types.d.ts +4 -1
  9. package/dist/components/color-input/useColorInput.d.ts +1 -1
  10. package/dist/components/color-input/useColorInputValue.d.ts +1 -1
  11. package/dist/components/dialog/dialog-close.d.ts +21 -0
  12. package/dist/components/dialog/dialog-content.d.ts +32 -0
  13. package/dist/components/dialog/dialog-core.d.ts +27 -0
  14. package/dist/components/dialog/dialog-description.d.ts +21 -0
  15. package/dist/components/dialog/dialog-overlay.d.ts +21 -0
  16. package/dist/components/dialog/dialog-portal.d.ts +21 -0
  17. package/dist/components/dialog/dialog-root.d.ts +28 -0
  18. package/dist/components/dialog/dialog-title.d.ts +21 -0
  19. package/dist/components/dialog/dialog-trigger.d.ts +23 -0
  20. package/dist/components/dialog/index.d.ts +9 -0
  21. package/dist/components/dialog/index.js +2 -0
  22. package/dist/components/dialog/types.d.ts +61 -0
  23. package/dist/components/dropdown-menu/dropdown-menu-checkbox-item.d.ts +24 -0
  24. package/dist/components/dropdown-menu/dropdown-menu-content.d.ts +34 -0
  25. package/dist/components/dropdown-menu/dropdown-menu-context-trigger.d.ts +23 -0
  26. package/dist/components/dropdown-menu/dropdown-menu-item-indicator.d.ts +24 -0
  27. package/dist/components/dropdown-menu/dropdown-menu-item-row.d.ts +28 -0
  28. package/dist/components/dropdown-menu/dropdown-menu-item.d.ts +23 -0
  29. package/dist/components/dropdown-menu/dropdown-menu-items.d.ts +24 -22
  30. package/dist/components/dropdown-menu/dropdown-menu-label.d.ts +21 -0
  31. package/dist/components/dropdown-menu/dropdown-menu-outside.d.ts +3 -0
  32. package/dist/components/dropdown-menu/dropdown-menu-portal.d.ts +21 -0
  33. package/dist/components/dropdown-menu/dropdown-menu-primitive-core.d.ts +110 -0
  34. package/dist/components/dropdown-menu/dropdown-menu-primitives.d.ts +15 -724
  35. package/dist/components/dropdown-menu/dropdown-menu-radio-group.d.ts +25 -0
  36. package/dist/components/dropdown-menu/dropdown-menu-radio-item.d.ts +23 -0
  37. package/dist/components/dropdown-menu/dropdown-menu-root.d.ts +30 -0
  38. package/dist/components/dropdown-menu/dropdown-menu-separator.d.ts +19 -0
  39. package/dist/components/dropdown-menu/dropdown-menu-sub-content.d.ts +34 -0
  40. package/dist/components/dropdown-menu/dropdown-menu-sub-trigger.d.ts +28 -0
  41. package/dist/components/dropdown-menu/dropdown-menu-sub.d.ts +28 -0
  42. package/dist/components/dropdown-menu/dropdown-menu-trigger.d.ts +23 -0
  43. package/dist/components/dropdown-menu/dropdown-menu.d.ts +5 -2
  44. package/dist/components/dropdown-menu/index.d.ts +28 -49
  45. package/dist/components/dropdown-menu/index.js +2 -2
  46. package/dist/components/dropdown-menu/types.d.ts +8 -3
  47. package/dist/components/dropdown-menu/useDropdownMenu.d.ts +8 -4
  48. package/dist/components/dropdown-menu/useDropdownMenuDisclosure.d.ts +7 -2
  49. package/dist/components/dropdown-menu/useDropdownMenuPortalPosition.d.ts +3 -3
  50. package/dist/components/dropdown-menu/useDropdownMenuPrimitiveContent.d.ts +27 -0
  51. package/dist/components/dropdown-menu/useDropdownMenuRenderItems.d.ts +2 -0
  52. package/dist/components/floating/index.d.ts +3 -1
  53. package/dist/components/floating/index.js +3 -0
  54. package/dist/components/floating/types.d.ts +86 -1
  55. package/dist/components/floating/useFloatingPosition.d.ts +3 -26
  56. package/dist/components/floating/useHoverDisclosure.d.ts +2 -0
  57. package/dist/components/input/input.d.ts +4 -1
  58. package/dist/components/input/types.d.ts +3 -1
  59. package/dist/components/modal/index.d.ts +1 -1
  60. package/dist/components/modal/modal.d.ts +3 -1
  61. package/dist/components/modal/types.d.ts +3 -0
  62. package/dist/components/modal/useModal.d.ts +7 -4
  63. package/dist/components/number-input/types.d.ts +3 -1
  64. package/dist/components/number-input/useNumberInput.d.ts +2 -1
  65. package/dist/components/popover/usePopover.d.ts +2 -2
  66. package/dist/components/radio/types.d.ts +17 -1
  67. package/dist/components/radio/useRadio.d.ts +3 -0
  68. package/dist/components/select/select.d.ts +4 -1
  69. package/dist/components/select/types.d.ts +6 -1
  70. package/dist/components/select/useSelect.d.ts +3 -2
  71. package/dist/components/slider/index.d.ts +1 -1
  72. package/dist/components/slider/range-slider.d.ts +3 -3
  73. package/dist/components/slider/types.d.ts +11 -3
  74. package/dist/components/slider/useRangeSlider.d.ts +1 -1
  75. package/dist/components/slider/useSlider.d.ts +1 -1
  76. package/dist/components/switch/types.d.ts +5 -1
  77. package/dist/components/switch/useSwitch.d.ts +1 -1
  78. package/dist/components/teleport-provider/index.d.ts +1 -0
  79. package/dist/components/teleport-provider/index.js +2 -1
  80. package/dist/components/teleport-provider/useTeleportTarget.d.ts +4 -3
  81. package/dist/components/textarea/types.d.ts +4 -1
  82. package/dist/components/textarea/useTextarea.d.ts +1 -1
  83. package/dist/components/toast/index.d.ts +2 -1
  84. package/dist/components/toast/index.js +2 -2
  85. package/dist/components/toast/toast-store.d.ts +2 -0
  86. package/dist/components/toast/types.d.ts +10 -4
  87. package/dist/components/toast/useToast.d.ts +2 -2
  88. package/dist/components/tooltip/useTooltip.d.ts +3 -3
  89. package/dist/composables/useOverlayLayer.d.ts +32 -0
  90. package/dist/dialog.js +510 -0
  91. package/dist/dropdown-menu.css +4 -5
  92. package/dist/dropdown-menu.js +1155 -886
  93. package/dist/floating.js +403 -0
  94. package/dist/index.d.ts +1 -0
  95. package/dist/index.js +7 -4
  96. package/dist/input.css +24 -24
  97. package/dist/input.js +21 -11
  98. package/dist/legacy-unlayered.css +424 -503
  99. package/dist/modal.css +28 -28
  100. package/dist/modal.js +141 -200
  101. package/dist/number-input.css +20 -20
  102. package/dist/number-input.js +44 -16
  103. package/dist/popover.css +4 -4
  104. package/dist/popover.js +29 -40
  105. package/dist/radio.css +18 -18
  106. package/dist/radio.js +96 -18
  107. package/dist/select.css +54 -43
  108. package/dist/select.js +185 -67
  109. package/dist/slider.css +183 -202
  110. package/dist/slider.js +138 -37
  111. package/dist/switch.css +17 -17
  112. package/dist/switch.js +31 -13
  113. package/dist/textarea.css +26 -26
  114. package/dist/textarea.js +19 -9
  115. package/dist/toast.js +110 -99
  116. package/dist/tooltip.css +5 -80
  117. package/dist/tooltip.js +11 -3
  118. package/dist/useControlState.js +4 -0
  119. package/dist/useFloatingPosition.js +86 -39
  120. package/dist/useFormControl.js +107 -0
  121. package/dist/useOverlayLayer.js +262 -0
  122. package/dist/useTeleportTarget.js +21 -10
  123. package/docs/public-floating-api.md +159 -0
  124. package/docs/public-styles-api.md +2 -1
  125. package/package.json +10 -6
  126. package/dist/useClickOutside.js +0 -24
@@ -0,0 +1,159 @@
1
+ # Public floating API
2
+
3
+ `useFloatingPosition` provides Ropav's positioning behavior without rendering component DOM or
4
+ styles. It applies the same offset, flip, shift and collision defaults used by Ropav overlays.
5
+
6
+ ```vue
7
+ <template>
8
+ <button
9
+ ref="reference"
10
+ type="button"
11
+ aria-haspopup="dialog"
12
+ :aria-expanded="open"
13
+ @click="open = !open"
14
+ >
15
+ Toggle card
16
+ </button>
17
+
18
+ <Teleport :to="teleportTo" :disabled="!teleport">
19
+ <section v-if="open" ref="floating" :style="floatingStyle" :data-placement="actualPlacement">
20
+ Custom content
21
+ <span ref="arrow" :style="arrowStyle" aria-hidden="true" />
22
+ </section>
23
+ </Teleport>
24
+ </template>
25
+
26
+ <script setup lang="ts">
27
+ import { ref } from 'vue';
28
+ import { useFloatingPosition } from 'ropav/floating';
29
+ import { useTeleportTarget } from 'ropav/teleport-provider';
30
+
31
+ const reference = ref<HTMLElement | null>(null);
32
+ const floating = ref<HTMLElement | null>(null);
33
+ const arrow = ref<HTMLElement | null>(null);
34
+ const open = ref(false);
35
+ const teleport = ref(true);
36
+ const teleportTo = useTeleportTarget();
37
+
38
+ const { actualPlacement, arrowStyle, floatingStyle } = useFloatingPosition({
39
+ reference,
40
+ floating,
41
+ arrow,
42
+ open,
43
+ placement: 'bottom-start',
44
+ offset: 8,
45
+ restartKey: () => [teleport.value, teleportTo.value],
46
+ });
47
+ </script>
48
+ ```
49
+
50
+ The composable accepts plain values, refs, computed refs or getters for reactive options.
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
+ | `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.
76
+
77
+ The return value contains readonly `actualPlacement`, `floatingStyle`, `arrowStyle` and
78
+ `isPositioned` refs, plus an async `update()` method for content-driven layout changes.
79
+
80
+ `useTeleportTarget()` resolves the nearest `TeleportProvider` target and falls back to `body`. Pass
81
+ a target value, ref or getter to override the provider for one floating element. Include the
82
+ resolved target and the Teleport enabled state in `restartKey` whenever either can change while the
83
+ floating element is open.
84
+
85
+ Positioning does not add interaction or accessibility behavior. Custom overlays remain responsible
86
+ for keyboard handling, focus management, roles, labels, outside interaction and dismissal.
87
+
88
+ ## Hover disclosure interactions
89
+
90
+ `useHoverDisclosure` manages hover and focus state without rendering DOM or positioning content. It
91
+ coordinates the trigger and floating content, so a close delay started when the pointer leaves the
92
+ trigger is cancelled when the pointer enters the content.
93
+
94
+ ```vue
95
+ <template>
96
+ <a ref="reference" href="/people/ada" v-bind="triggerProps">Ada Lovelace</a>
97
+
98
+ <Teleport to="body">
99
+ <section
100
+ v-if="isOpen"
101
+ ref="floating"
102
+ v-bind="contentProps"
103
+ :style="floatingStyle"
104
+ :data-placement="actualPlacement"
105
+ >
106
+ Mathematician and writer
107
+ </section>
108
+ </Teleport>
109
+ </template>
110
+
111
+ <script setup lang="ts">
112
+ import { ref } from 'vue';
113
+ import { useFloatingPosition, useHoverDisclosure } from 'ropav/floating';
114
+
115
+ const reference = ref<HTMLElement | null>(null);
116
+ const floating = ref<HTMLElement | null>(null);
117
+
118
+ const { isOpen, triggerProps, contentProps } = useHoverDisclosure({
119
+ openDelay: 600,
120
+ closeDelay: 150,
121
+ });
122
+
123
+ const { actualPlacement, floatingStyle } = useFloatingPosition({
124
+ reference,
125
+ floating,
126
+ open: isOpen,
127
+ placement: 'bottom-start',
128
+ });
129
+ </script>
130
+ ```
131
+
132
+ Focus opens immediately by default. Hover uses `openDelay`; leaving the combined trigger/content
133
+ area uses `closeDelay`. Escape dismisses an open disclosure even when keyboard focus is elsewhere.
134
+ The return value also contains `state`, `isDisabled`, and immediate `open()`, `close()` and
135
+ `toggle()` controls.
136
+
137
+ | Option | Default | Description |
138
+ | ------------------- | ------- | --------------------------------------------------------------------------- |
139
+ | `open` | — | Controlled open state. Omit it for internal state. |
140
+ | `defaultOpen` | `false` | Initial internal state. |
141
+ | `openDelay` | `0` | Delay in milliseconds before pointer hover opens the disclosure. |
142
+ | `closeDelay` | `0` | Delay before closing after pointer and focus leave trigger and content. |
143
+ | `disabled` | `false` | Prevents opening and closes pending/open internal state. |
144
+ | `openOnFocus` | `true` | Opens immediately when focus enters the trigger. |
145
+ | `closeOnEscape` | `true` | Allows Escape to dismiss the disclosure. |
146
+ | `touchBehavior` | `none` | `toggle` opts into tap-to-toggle and prevents the activating click default. |
147
+ | `interactionTarget` | — | External element, selector or virtual reference that owns trigger events. |
148
+ | `contentTarget` | — | External element or selector that owns content events. |
149
+ | `onOpenChange` | — | Receives the requested state and its interaction reason. |
150
+
151
+ When `interactionTarget` or `contentTarget` is supplied, the composable attaches the corresponding
152
+ listeners directly; do not also bind the matching props to that same element. An element reference
153
+ is used directly. A virtual reference uses its `contextElement` for events. A virtual reference
154
+ without `contextElement` cannot receive pointer or focus events, so control it with `open` or the
155
+ imperative methods instead.
156
+
157
+ The composable only owns disclosure interaction. Consumers remain responsible for content roles,
158
+ labels and deciding whether the revealed information is appropriate for hover/focus. Interactive
159
+ dialogs and focus-trapped content should use `Popover` or `Dialog` instead.
@@ -92,7 +92,8 @@ Boolean states use presence semantics: the attribute value is empty when true an
92
92
  - `data-filled`: Slider and RangeSlider marks.
93
93
  - `data-submenu`: DropdownMenu items that own children.
94
94
  - `data-orientation="horizontal|vertical"`: Accordion, ButtonGroup, RadioGroup, Slider, RangeSlider, Tabs and TabsList.
95
- - `data-placement`: twelve Popover placements, a side (`top`, `right`, `bottom`, `left`) for DropdownMenu, and the same four sides for Tooltip.
95
+ - `data-placement`: the final placement after collision handling; twelve placements for Popover and DropdownMenu, and a side (`top`, `right`, `bottom`, `left`) for Tooltip.
96
+ - `data-side="top|right|bottom|left"`: the side component of the final placement for Popover, DropdownMenu and Tooltip.
96
97
  - `data-control="increment|decrement"`: NumberInput controls.
97
98
  - `data-control="saturation|hue|opacity"`: ColorPicker controls and handles.
98
99
  - `data-thumb="lower|upper|merged"`: RangeSlider inputs, thumbs and tooltips; `data-active-thumb="lower|upper"` is present on its root only while a thumb is active.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ropav",
3
- "version": "0.0.11",
3
+ "version": "0.0.13",
4
4
  "type": "module",
5
5
  "packageManager": "pnpm@11.10.0",
6
6
  "engines": {
@@ -83,6 +83,10 @@
83
83
  "types": "./dist/components/dropdown-menu/index.d.ts",
84
84
  "import": "./dist/components/dropdown-menu/index.js"
85
85
  },
86
+ "./dialog": {
87
+ "types": "./dist/components/dialog/index.d.ts",
88
+ "import": "./dist/components/dialog/index.js"
89
+ },
86
90
  "./field": {
87
91
  "types": "./dist/components/field/index.d.ts",
88
92
  "import": "./dist/components/field/index.js"
@@ -204,12 +208,12 @@
204
208
  "focus-trap": "^8.2.2"
205
209
  },
206
210
  "devDependencies": {
207
- "@iconify-json/lucide": "^1.2.116",
211
+ "@iconify-json/lucide": "^1.2.117",
208
212
  "@storybook/addon-themes": "^10.5.0",
209
213
  "@storybook/addon-vitest": "^10.5.0",
210
214
  "@storybook/vue3-vite": "^10.5.0",
211
215
  "@types/node": "^26.1.1",
212
- "@vitejs/plugin-vue": "^6.0.7",
216
+ "@vitejs/plugin-vue": "^6.0.8",
213
217
  "@vitest/browser-playwright": "^4.1.10",
214
218
  "@vue/compiler-vapor": "3.6.0-beta.17",
215
219
  "@vue/tsconfig": "^0.9.1",
@@ -217,10 +221,10 @@
217
221
  "conventional-changelog": "^8.1.0",
218
222
  "conventional-changelog-conventionalcommits": "^10.2.1",
219
223
  "jsdom": "^29.1.1",
220
- "oxfmt": "^0.58.0",
221
- "oxlint": "^1.73.0",
224
+ "oxfmt": "^0.59.0",
225
+ "oxlint": "^1.74.0",
222
226
  "playwright": "^1.61.1",
223
- "postcss": "^8.5.16",
227
+ "postcss": "^8.5.19",
224
228
  "sass-embedded": "^1.100.0",
225
229
  "storybook": "^10.5.0",
226
230
  "style-dictionary": "5.5.0",
@@ -1,24 +0,0 @@
1
- import { onBeforeUnmount, onMounted, watch } from "vue";
2
- //#region src/composables/useClickOutside.ts
3
- function useClickOutside(target, active, callback) {
4
- let isListening = false;
5
- let stopWatch;
6
- function handler(e) {
7
- if (!(Array.isArray(target) ? target : [target]).some((current) => current.value?.contains(e.target))) callback(e);
8
- }
9
- function setListening(value) {
10
- if (typeof document === "undefined" || value === isListening) return;
11
- isListening = value;
12
- if (value) document.addEventListener("click", handler, true);
13
- else document.removeEventListener("click", handler, true);
14
- }
15
- onMounted(() => {
16
- stopWatch = watch(active, setListening, { immediate: true });
17
- });
18
- onBeforeUnmount(() => {
19
- stopWatch?.();
20
- setListening(false);
21
- });
22
- }
23
- //#endregion
24
- export { useClickOutside as t };