v-float 0.10.0 → 0.11.0

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 (50) hide show
  1. package/README.md +44 -175
  2. package/dist/index.d.mts +688 -0
  3. package/dist/index.d.mts.map +1 -0
  4. package/dist/index.mjs +2038 -0
  5. package/dist/index.mjs.map +1 -0
  6. package/package.json +74 -75
  7. package/dist/composables/index.d.ts +0 -4
  8. package/dist/composables/index.d.ts.map +0 -1
  9. package/dist/composables/interactions/index.d.ts +0 -7
  10. package/dist/composables/interactions/index.d.ts.map +0 -1
  11. package/dist/composables/interactions/polygon.d.ts +0 -38
  12. package/dist/composables/interactions/polygon.d.ts.map +0 -1
  13. package/dist/composables/interactions/use-click.d.ts +0 -120
  14. package/dist/composables/interactions/use-click.d.ts.map +0 -1
  15. package/dist/composables/interactions/use-escape-key.d.ts +0 -57
  16. package/dist/composables/interactions/use-escape-key.d.ts.map +0 -1
  17. package/dist/composables/interactions/use-focus-trap.d.ts +0 -78
  18. package/dist/composables/interactions/use-focus-trap.d.ts.map +0 -1
  19. package/dist/composables/interactions/use-focus.d.ts +0 -60
  20. package/dist/composables/interactions/use-focus.d.ts.map +0 -1
  21. package/dist/composables/interactions/use-hover.d.ts +0 -78
  22. package/dist/composables/interactions/use-hover.d.ts.map +0 -1
  23. package/dist/composables/interactions/use-list-navigation.d.ts +0 -144
  24. package/dist/composables/interactions/use-list-navigation.d.ts.map +0 -1
  25. package/dist/composables/middlewares/arrow.d.ts +0 -25
  26. package/dist/composables/middlewares/arrow.d.ts.map +0 -1
  27. package/dist/composables/middlewares/index.d.ts +0 -4
  28. package/dist/composables/middlewares/index.d.ts.map +0 -1
  29. package/dist/composables/positioning/index.d.ts +0 -5
  30. package/dist/composables/positioning/index.d.ts.map +0 -1
  31. package/dist/composables/positioning/use-arrow.d.ts +0 -55
  32. package/dist/composables/positioning/use-arrow.d.ts.map +0 -1
  33. package/dist/composables/positioning/use-client-point.d.ts +0 -218
  34. package/dist/composables/positioning/use-client-point.d.ts.map +0 -1
  35. package/dist/composables/positioning/use-floating-tree.d.ts +0 -240
  36. package/dist/composables/positioning/use-floating-tree.d.ts.map +0 -1
  37. package/dist/composables/positioning/use-floating.d.ts +0 -162
  38. package/dist/composables/positioning/use-floating.d.ts.map +0 -1
  39. package/dist/composables/utils/is-using-keyboard.d.ts +0 -2
  40. package/dist/composables/utils/is-using-keyboard.d.ts.map +0 -1
  41. package/dist/composables/utils/use-active-descendant.d.ts +0 -8
  42. package/dist/composables/utils/use-active-descendant.d.ts.map +0 -1
  43. package/dist/index.d.ts +0 -2
  44. package/dist/index.d.ts.map +0 -1
  45. package/dist/types.d.ts +0 -18
  46. package/dist/types.d.ts.map +0 -1
  47. package/dist/utils.d.ts +0 -92
  48. package/dist/utils.d.ts.map +0 -1
  49. package/dist/v-float.es.js +0 -3827
  50. package/dist/v-float.umd.js +0 -8
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # V-Float
2
2
 
3
- [![status: WIP](https://img.shields.io/badge/status-WIP-orange.svg)](#project-status)
3
+ [status: WIP](#project-status)
4
4
 
5
5
  > Work in progress: This library is under active development. APIs may change without notice and breaking changes can land without deprecation windows or warnings. Not recommended for production use yet.
6
6
 
@@ -12,7 +12,6 @@ of [@floating-ui/dom](https://floating-ui.com/) with Vue 3 Composition API.
12
12
  - **Precise Positioning**: Pixel-perfect positioning with automatic collision detection
13
13
  - **Vue 3 Composables**: Reactive composables designed for the Composition API
14
14
  - **Interaction Handling**: Built-in hover, focus, click, and dismiss behaviors
15
- - **Nested Elements**: Support for floating element trees and hierarchies
16
15
  - **Arrow Positioning**: `useArrow` composable for positioning arrow elements
17
16
  - **Lightweight**: Tree-shakable with minimal bundle impact
18
17
  - **Cross-platform**: Works on desktop, mobile, and touch devices
@@ -37,24 +36,24 @@ yarn add v-float
37
36
 
38
37
  ```vue
39
38
  <script setup lang="ts">
40
- import { useTemplateRef } from "vue"
41
- import { useFloating, useHover, offset } from "v-float"
39
+ import { useTemplateRef } from "vue";
40
+ import { useFloating, useHover, offset } from "v-float";
42
41
 
43
- const anchorEl = useTemplateRef("anchorEl")
44
- const floatingEl = useTemplateRef("floatingEl")
42
+ const anchorEl = useTemplateRef("anchorEl");
43
+ const floatingEl = useTemplateRef("floatingEl");
45
44
 
46
45
  const context = useFloating(anchorEl, floatingEl, {
47
46
  placement: "top",
48
47
  middlewares: [offset(8)],
49
- })
48
+ });
50
49
 
51
- useHover(context)
50
+ useHover(context);
52
51
  </script>
53
52
 
54
53
  <template>
55
54
  <button ref="anchorEl">Hover me</button>
56
55
 
57
- <div v-if="context.open.value" ref="floatingEl" :style="context.floatingStyles.value">
56
+ <div v-if="context.state.open.value" ref="floatingEl" :style="context.position.styles.value">
58
57
  This is a tooltip
59
58
  </div>
60
59
  </template>
@@ -64,27 +63,27 @@ useHover(context)
64
63
 
65
64
  ```vue
66
65
  <script setup lang="ts">
67
- import { useTemplateRef } from "vue"
68
- import { useFloating, useClick, useEscapeKey, offset, flip, shift } from "v-float"
66
+ import { useTemplateRef } from "vue";
67
+ import { useFloating, useClick, useEscapeKey, offset, flip, shift } from "v-float";
69
68
 
70
- const triggerEl = useTemplateRef("triggerEl")
71
- const menuEl = useTemplateRef("menuEl")
69
+ const triggerEl = useTemplateRef("triggerEl");
70
+ const menuEl = useTemplateRef("menuEl");
72
71
 
73
72
  const context = useFloating(triggerEl, menuEl, {
74
73
  placement: "bottom-start",
75
74
  middlewares: [offset(4), flip(), shift({ padding: 8 })],
76
- })
75
+ });
77
76
 
78
- useClick(context)
79
- useEscapeKey({
77
+ useClick(context);
78
+ useEscapeKey(context, {
80
79
  onEscape: () => context.setOpen(false),
81
- })
80
+ });
82
81
  </script>
83
82
 
84
83
  <template>
85
84
  <button ref="triggerEl">Open Menu</button>
86
85
 
87
- <div v-if="context.open.value" ref="menuEl" :style="context.floatingStyles.value">
86
+ <div v-if="context.state.open.value" ref="menuEl" :style="context.position.styles.value">
88
87
  <div>Menu Item 1</div>
89
88
  <div>Menu Item 2</div>
90
89
  <div>Menu Item 3</div>
@@ -96,33 +95,33 @@ useEscapeKey({
96
95
 
97
96
  ```vue
98
97
  <script setup lang="ts">
99
- import { useTemplateRef } from "vue"
100
- import { useFloating, useHover, useArrow, offset, flip } from "v-float"
98
+ import { useTemplateRef } from "vue";
99
+ import { useFloating, useHover, useArrow, offset, flip } from "v-float";
101
100
 
102
- const anchorEl = useTemplateRef("anchorEl")
103
- const tooltipEl = useTemplateRef("tooltipEl")
104
- const arrowEl = useTemplateRef("arrowEl")
101
+ const anchorEl = useTemplateRef("anchorEl");
102
+ const tooltipEl = useTemplateRef("tooltipEl");
103
+ const arrowEl = useTemplateRef("arrowEl");
105
104
 
106
105
  const context = useFloating(anchorEl, tooltipEl, {
107
106
  placement: "top",
108
107
  middlewares: [offset(8), flip()],
109
- })
108
+ });
110
109
 
111
- useHover(context)
110
+ useHover(context);
112
111
 
113
- // Arrow middleware is automatically registered
114
- const { arrowStyles } = useArrow(arrowEl, context, {
112
+ const { arrowStyles } = useArrow(context, {
113
+ element: arrowEl,
115
114
  offset: "-4px",
116
- })
115
+ });
117
116
  </script>
118
117
 
119
118
  <template>
120
119
  <button ref="anchorEl">Hover me</button>
121
120
 
122
121
  <div
123
- v-if="context.open.value"
122
+ v-if="context.state.open.value"
124
123
  ref="tooltipEl"
125
- :style="context.floatingStyles.value"
124
+ :style="context.position.styles.value"
126
125
  class="tooltip"
127
126
  >
128
127
  This is a tooltip with an arrow
@@ -155,30 +154,29 @@ const { arrowStyles } = useArrow(arrowEl, context, {
155
154
 
156
155
  ### Positioning
157
156
 
158
- - **`useFloating`**: Core positioning logic with middleware support
159
- - **`useArrow`**: Position arrow elements pointing to the anchor
160
- - **`useFloatingTree`**: Manage nested floating element hierarchies
157
+ - `**useFloating**`: Core positioning logic with middleware support
158
+ - `**useArrow**`: Position arrow elements pointing to the anchor
161
159
 
162
160
  ### Interactions
163
161
 
164
- - **`useHover`**: Hover interactions with configurable delays
165
- - **`useFocus`**: Focus/blur event handling for keyboard navigation
166
- - **`useClick`**: Click event handling with toggle and dismiss options
167
- - **`useEscapeKey`**: Close on ESC key press with composition handling
168
- - **`useClientPoint`**: Position floating elements at cursor/touch coordinates
162
+ - `**useHover**`: Hover interactions with configurable delays
163
+ - `**useFocus**`: Focus/blur event handling for keyboard navigation
164
+ - `**useClick**`: Click event handling with toggle and dismiss options
165
+ - `**useEscapeKey**`: Close on ESC key press with composition handling
166
+ - `**useClientPoint**`: Position floating elements at cursor/touch coordinates
169
167
 
170
168
  ### Middleware
171
169
 
172
170
  All [Floating UI middleware](https://floating-ui.com/docs/middleware) are supported:
173
171
 
174
- - **`offset`**: Add distance between anchor and floating element
175
- - **`flip`**: Flip placement when there's insufficient space
176
- - **`shift`**: Shift floating element to stay in view
177
- - **`hide`**: Hide floating element when anchor is not visible
178
- - **`autoPlacement`**: Automatically choose the best placement
179
- - **`size`**: Resize floating element to fit within viewport
172
+ - `**offset**`: Add distance between anchor and floating element
173
+ - `**flip**`: Flip placement when there's insufficient space
174
+ - `**shift**`: Shift floating element to stay in view
175
+ - `**hide**`: Hide floating element when anchor is not visible
176
+ - `**autoPlacement**`: Automatically choose the best placement
177
+ - `**size**`: Resize floating element to fit within viewport
180
178
 
181
- **Arrow positioning** is handled by the [`useArrow`](/api/use-arrow) composable, which automatically registers the necessary middleware.
179
+ **Arrow positioning** is handled by the `[useArrow](/api/use-arrow)` composable, which owns arrow registration for the floating context.
182
180
 
183
181
  ## Project Status
184
182
 
@@ -186,135 +184,6 @@ All [Floating UI middleware](https://floating-ui.com/docs/middleware) are suppor
186
184
  - API, docs, and examples are subject to change and may be incomplete.
187
185
  - Feedback and contributions are welcome while the API stabilizes.
188
186
 
189
- ## Advanced Features
190
-
191
- ### Floating Trees
192
-
193
- For nested floating elements like submenus, use `useFloatingTree` to manage hierarchical structures with a streamlined API that eliminates redundant `useFloating` calls.
194
-
195
- **Clear Separation of Concerns:**
196
-
197
- - Use `useFloating` for isolated floating elements
198
- - Use `useFloatingTree` for hierarchical structures
199
-
200
- Here's how you can set up a parent menu with a submenu using the new API:
201
-
202
- ```vue
203
- <script setup lang="ts">
204
- import { useTemplateRef, ref } from "vue"
205
- import { useFloatingTree, useHover, useClick, offset, flip, shift } from "v-float"
206
-
207
- const parentTriggerEl = useTemplateRef("parentTriggerRef")
208
- const parentMenuEl = useTemplateRef("parentMenuRef")
209
- const isParentOpen = ref(false)
210
-
211
- const submenuTriggerEl = useTemplateRef("submenuTriggerRef")
212
- const submenuEl = useTemplateRef("submenuRef")
213
- const isSubmenuOpen = ref(false)
214
-
215
- // 1. Create the floating tree with root context automatically
216
- const tree = useFloatingTree(parentTriggerEl, parentMenuEl, {
217
- placement: "bottom-start",
218
- open: isParentOpen,
219
- middlewares: [offset(4), flip(), shift({ padding: 8 })],
220
- })
221
-
222
- // 2. Add submenu node - no separate useFloating call needed!
223
- const submenuNode = tree.addNode(submenuTriggerEl, submenuEl, {
224
- placement: "right-start",
225
- open: isSubmenuOpen,
226
- middlewares: [offset(4), flip(), shift({ padding: 8 })],
227
- parentId: tree.root.id, // Link to parent using parentId in options
228
- })
229
-
230
- // 3. Add interactions
231
- useClick(tree.root, { outsideClick: true })
232
- useHover(submenuNode, { delay: { open: 100, close: 300 } })
233
-
234
- // Access floating styles from the contexts
235
- const { floatingStyles: parentStyles } = tree.rootContext
236
- const { floatingStyles: submenuStyles } = submenuNode.data
237
- </script>
238
-
239
- <template>
240
- <!-- Parent Menu Trigger -->
241
- <button ref="parentTriggerEl" @click="isParentOpen = !isParentOpen">Open Menu</button>
242
-
243
- <!-- Parent Menu -->
244
- <div v-if="isParentOpen" ref="parentMenuEl" :style="parentStyles" class="menu">
245
- <div class="menu-item">Menu Item 1</div>
246
-
247
- <!-- Submenu Trigger -->
248
- <div
249
- ref="submenuTriggerEl"
250
- class="menu-item menu-item--submenu"
251
- @click="isSubmenuOpen = !isSubmenuOpen"
252
- >
253
- Menu Item 2 (Has Submenu)
254
-
255
- <!-- Submenu -->
256
- <div v-if="isSubmenuOpen" ref="submenuEl" :style="submenuStyles" class="menu submenu">
257
- <div class="menu-item">Submenu Item A</div>
258
- <div class="menu-item">Submenu Item B</div>
259
- <div class="menu-item">Submenu Item C</div>
260
- </div>
261
- </div>
262
-
263
- <div class="menu-item">Menu Item 3</div>
264
- </div>
265
- </template>
266
-
267
- <style scoped>
268
- .menu {
269
- background: white;
270
- border: 1px solid #ddd;
271
- border-radius: 4px;
272
- padding: 4px 0;
273
- box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
274
- min-width: 160px;
275
- z-index: 1000;
276
- }
277
-
278
- .submenu {
279
- margin-left: 8px;
280
- z-index: 1010;
281
- }
282
-
283
- .menu-item {
284
- padding: 8px 12px;
285
- cursor: pointer;
286
- user-select: none;
287
- }
288
-
289
- .menu-item:hover {
290
- background-color: #f5f5f5;
291
- }
292
-
293
- .menu-item--submenu {
294
- position: relative;
295
- }
296
- </style>
297
- ```
298
-
299
- **API Benefits:**
300
-
301
- ```ts
302
- // Before: Required separate useFloating calls
303
- const parentContext = useFloating(parentEl, parentFloating, options)
304
- const tree = useFloatingTree(parentContext)
305
- const childContext = useFloating(childEl, childFloating, childOptions)
306
- const childNode = tree.addNode(childContext, parentContext.nodeId)
307
-
308
- // After: Streamlined API with internal context creation
309
- const tree = useFloatingTree(parentEl, parentFloating, options)
310
- const childNode = tree.addNode(childEl, childFloating, {
311
- ...childOptions,
312
- parentId: tree.root.id,
313
- })
314
- ```
315
-
316
- This approach eliminates redundant calls and provides a clearer separation between isolated floating elements (`useFloating`) and hierarchical structures (`useFloatingTree`).
317
-
318
187
  ## TypeScript Support
319
188
 
320
189
  V-Float is built with TypeScript and provides comprehensive type definitions:
@@ -322,7 +191,7 @@ V-Float is built with TypeScript and provides comprehensive type definitions:
322
191
  ## Browser Support
323
192
 
324
193
  - **Modern browsers**: Chrome, Firefox, Safari, Edge
325
- - **Mobile browsers**: iOS Safari, Chrome Mobile, Samsung Internet
194
+ - **Mobile browsers**: iOS Safari, Chrome Mobile
326
195
  - **Node.js**: SSR compatible (with proper hydration)
327
196
 
328
197
  ## Documentation