v-float 0.2.0 → 0.3.1

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 (41) hide show
  1. package/README.md +249 -109
  2. package/dist/composables/interactions/index.d.ts +2 -1
  3. package/dist/composables/interactions/index.d.ts.map +1 -1
  4. package/dist/composables/interactions/polygon.d.ts +38 -0
  5. package/dist/composables/interactions/polygon.d.ts.map +1 -0
  6. package/dist/composables/interactions/use-click.d.ts +78 -10
  7. package/dist/composables/interactions/use-click.d.ts.map +1 -1
  8. package/dist/composables/interactions/use-client-point.d.ts +1 -1
  9. package/dist/composables/interactions/use-client-point.d.ts.map +1 -1
  10. package/dist/composables/interactions/use-escape-key.d.ts +24 -0
  11. package/dist/composables/interactions/use-escape-key.d.ts.map +1 -0
  12. package/dist/composables/interactions/use-focus.d.ts +28 -3
  13. package/dist/composables/interactions/use-focus.d.ts.map +1 -1
  14. package/dist/composables/interactions/use-hover.d.ts +32 -18
  15. package/dist/composables/interactions/use-hover.d.ts.map +1 -1
  16. package/dist/composables/interactions/utils/browser-detection.d.ts +23 -0
  17. package/dist/composables/interactions/utils/browser-detection.d.ts.map +1 -0
  18. package/dist/composables/interactions/utils/element-detection.d.ts +53 -0
  19. package/dist/composables/interactions/utils/element-detection.d.ts.map +1 -0
  20. package/dist/composables/interactions/utils/event-utils.d.ts +30 -0
  21. package/dist/composables/interactions/utils/event-utils.d.ts.map +1 -0
  22. package/dist/composables/interactions/utils/index.d.ts +11 -0
  23. package/dist/composables/interactions/utils/index.d.ts.map +1 -0
  24. package/dist/composables/interactions/utils/tree-context.d.ts +32 -0
  25. package/dist/composables/interactions/utils/tree-context.d.ts.map +1 -0
  26. package/dist/composables/middlewares/index.d.ts +0 -1
  27. package/dist/composables/middlewares/index.d.ts.map +1 -1
  28. package/dist/composables/use-arrow.d.ts +10 -3
  29. package/dist/composables/use-arrow.d.ts.map +1 -1
  30. package/dist/composables/use-floating-tree.d.ts +13 -13
  31. package/dist/composables/use-floating-tree.d.ts.map +1 -1
  32. package/dist/composables/use-floating.d.ts +12 -20
  33. package/dist/composables/use-floating.d.ts.map +1 -1
  34. package/dist/composables/use-tree.d.ts.map +1 -1
  35. package/dist/utils.d.ts +1 -0
  36. package/dist/utils.d.ts.map +1 -1
  37. package/dist/v-float.es.js +1457 -1061
  38. package/dist/v-float.umd.js +1 -1
  39. package/package.json +34 -21
  40. package/dist/composables/interactions/use-dismiss.d.ts +0 -68
  41. package/dist/composables/interactions/use-dismiss.d.ts.map +0 -1
package/README.md CHANGED
@@ -32,20 +32,19 @@ yarn add v-float
32
32
  ### Basic Tooltip
33
33
 
34
34
  ```vue
35
-
36
35
  <script setup lang="ts">
37
- import { useTemplateRef } from "vue"
38
- import { useFloating, useHover, offset } from "v-float"
36
+ import { useTemplateRef } from "vue"
37
+ import { useFloating, useHover, offset } from "v-float"
39
38
 
40
- const anchorEl = useTemplateRef("anchorEl")
41
- const floatingEl = useTemplateRef("floatingEl")
39
+ const anchorEl = useTemplateRef("anchorEl")
40
+ const floatingEl = useTemplateRef("floatingEl")
42
41
 
43
- const context = useFloating(anchorEl, floatingEl, {
44
- placement: "top",
45
- middlewares: [offset(8)],
46
- })
42
+ const context = useFloating(anchorEl, floatingEl, {
43
+ placement: "top",
44
+ middlewares: [offset(8)],
45
+ })
47
46
 
48
- useHover(context)
47
+ useHover(context)
49
48
  </script>
50
49
 
51
50
  <template>
@@ -60,21 +59,22 @@ yarn add v-float
60
59
  ### Dropdown Menu
61
60
 
62
61
  ```vue
63
-
64
62
  <script setup lang="ts">
65
- import { useTemplateRef } from "vue"
66
- import { useFloating, useClick, useDismiss, offset, flip, shift } from "v-float"
63
+ import { useTemplateRef } from "vue"
64
+ import { useFloating, useClick, useEscapeKey, offset, flip, shift } from "v-float"
67
65
 
68
- const triggerEl = useTemplateRef("triggerEl")
69
- const menuEl = useTemplateRef("menuEl")
66
+ const triggerEl = useTemplateRef("triggerEl")
67
+ const menuEl = useTemplateRef("menuEl")
70
68
 
71
- const context = useFloating(triggerEl, menuEl, {
72
- placement: "bottom-start",
73
- middlewares: [offset(4), flip(), shift({ padding: 8 })],
74
- })
69
+ const context = useFloating(triggerEl, menuEl, {
70
+ placement: "bottom-start",
71
+ middlewares: [offset(4), flip(), shift({ padding: 8 })],
72
+ })
75
73
 
76
- useClick(context)
77
- useDismiss(context)
74
+ useClick(context)
75
+ useEscapeKey({
76
+ onEscape: () => context.setOpen(false),
77
+ })
78
78
  </script>
79
79
 
80
80
  <template>
@@ -88,6 +88,65 @@ yarn add v-float
88
88
  </template>
89
89
  ```
90
90
 
91
+ ### Tooltip with Arrow
92
+
93
+ ```vue
94
+ <script setup lang="ts">
95
+ import { useTemplateRef } from "vue"
96
+ import { useFloating, useHover, useArrow, offset, flip } from "v-float"
97
+
98
+ const anchorEl = useTemplateRef("anchorEl")
99
+ const tooltipEl = useTemplateRef("tooltipEl")
100
+ const arrowEl = useTemplateRef("arrowEl")
101
+
102
+ const context = useFloating(anchorEl, tooltipEl, {
103
+ placement: "top",
104
+ middlewares: [offset(8), flip()],
105
+ })
106
+
107
+ useHover(context)
108
+
109
+ // Arrow middleware is automatically registered
110
+ const { arrowStyles } = useArrow(arrowEl, context, {
111
+ offset: "-4px",
112
+ })
113
+ </script>
114
+
115
+ <template>
116
+ <button ref="anchorEl">Hover me</button>
117
+
118
+ <div
119
+ v-if="context.open.value"
120
+ ref="tooltipEl"
121
+ :style="context.floatingStyles.value"
122
+ class="tooltip"
123
+ >
124
+ This is a tooltip with an arrow
125
+ <div ref="arrowEl" class="arrow" :style="arrowStyles"></div>
126
+ </div>
127
+ </template>
128
+
129
+ <style scoped>
130
+ .tooltip {
131
+ background: white;
132
+ border: 1px solid #ddd;
133
+ border-radius: 4px;
134
+ padding: 8px 12px;
135
+ box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
136
+ }
137
+
138
+ .arrow {
139
+ position: absolute;
140
+ width: 8px;
141
+ height: 8px;
142
+ background: white;
143
+ border: 1px solid #ddd;
144
+ transform: rotate(45deg);
145
+ z-index: -1;
146
+ }
147
+ </style>
148
+ ```
149
+
91
150
  ## Core Composables
92
151
 
93
152
  ### Positioning
@@ -98,10 +157,10 @@ yarn add v-float
98
157
 
99
158
  ### Interactions
100
159
 
101
- - **`useHover`**: Hover interactions with configurable delays and safe areas
160
+ - **`useHover`**: Hover interactions with configurable delays
102
161
  - **`useFocus`**: Focus/blur event handling for keyboard navigation
103
162
  - **`useClick`**: Click event handling with toggle and dismiss options
104
- - **`useDismiss`**: Close on outside click, ESC key, or scroll events
163
+ - **`useEscapeKey`**: Close on ESC key press with composition handling
105
164
  - **`useClientPoint`**: Position floating elements at cursor/touch coordinates
106
165
 
107
166
  ### Middleware
@@ -112,115 +171,137 @@ All [Floating UI middleware](https://floating-ui.com/docs/middleware) are suppor
112
171
  - **`flip`**: Flip placement when there's insufficient space
113
172
  - **`shift`**: Shift floating element to stay in view
114
173
  - **`hide`**: Hide floating element when anchor is not visible
115
- - **`arrow`**: Position arrow elements (via `useArrow`)
116
-
117
- ## Components
118
-
119
- ### FloatingArrow
120
-
121
- Pre-built SVG arrow component with automatic positioning:
122
-
123
- ```vue
124
174
 
125
- <script setup lang="ts">
126
- import { FloatingArrow, useFloating, useArrow } from "v-float"
127
-
128
- const context = useFloating(anchorEl, floatingEl, {
129
- middlewares: [arrow({ element: arrowEl })],
130
- })
131
- </script>
132
-
133
- <template>
134
- <div ref="floatingEl" :style="context.floatingStyles.value">
135
- Tooltip content
136
- <FloatingArrow :context="context" fill="white" />
137
- </div>
138
- </template>
139
- ```
175
+ **Arrow positioning** is handled by the [`useArrow`](/api/use-arrow) composable, which automatically registers the necessary middleware.
140
176
 
141
177
  ## Advanced Features
142
178
 
143
179
  ### Floating Trees
144
180
 
145
- For nested floating elements like submenus, you need to manage the tree structure explicitly. `useFloating` creates
146
- contexts for individual floating elements, and `useFloatingTree` manages their hierarchical relationship.
181
+ For nested floating elements like submenus, use `useFloatingTree` to manage hierarchical structures with a streamlined API that eliminates redundant `useFloating` calls.
147
182
 
148
- Here's how you can set up a parent menu with a submenu:
183
+ **Clear Separation of Concerns:**
149
184
 
150
- ```vue
185
+ - Use `useFloating` for isolated floating elements
186
+ - Use `useFloatingTree` for hierarchical structures
187
+
188
+ Here's how you can set up a parent menu with a submenu using the new API:
151
189
 
190
+ ```vue
152
191
  <script setup lang="ts">
153
- import { useTemplateRef } from "vue";
154
- import { useFloating, useFloatingTree, offset } from "v-float";
155
-
156
- const parentTriggerEl = useTemplateRef("parentTriggerRef");
157
- const parentMenuEl = useTemplateRef("parentMenuRef");
158
-
159
- const submenuTriggerEl = useTemplateRef("submenuTriggerRef");
160
- const submenuEl = useTemplateRef("submenuRef");
161
-
162
- // 1. Create the floating context for the parent menu.
163
- const parentContext = useFloating(parentTriggerEl, parentMenuEl, {
164
- placement: "bottom-start",
165
- middlewares: [offset(4)],
166
- });
167
-
168
- // 2. Create the floating tree, using the parent's context as the data for the root node.
169
- // useFloatingTree will create a root TreeNode whose `data` is parentContext.
170
- const tree = useFloatingTree(parentContext);
171
-
172
- // 3. Create the floating context for the submenu.
173
- const submenuContext = useFloating(submenuTriggerEl, submenuEl, {
174
- placement: "right-start",
175
- middlewares: [offset(4)],
176
- });
177
-
178
- // 4. Add the submenu to the tree as a child of the parent menu.
179
- // tree.root refers to the TreeNode associated with parentContext.
180
- const submenuNode = tree.addNode(submenuContext, tree.root.id);
181
- // submenuNode is the TreeNode for the submenu. You can store it if needed.
192
+ import { useTemplateRef, ref } from "vue"
193
+ import { useFloatingTree, useHover, useClick, offset, flip, shift } from "v-float"
194
+
195
+ const parentTriggerEl = useTemplateRef("parentTriggerRef")
196
+ const parentMenuEl = useTemplateRef("parentMenuRef")
197
+ const isParentOpen = ref(false)
198
+
199
+ const submenuTriggerEl = useTemplateRef("submenuTriggerRef")
200
+ const submenuEl = useTemplateRef("submenuRef")
201
+ const isSubmenuOpen = ref(false)
202
+
203
+ // 1. Create the floating tree with root context automatically
204
+ const tree = useFloatingTree(parentTriggerEl, parentMenuEl, {
205
+ placement: "bottom-start",
206
+ open: isParentOpen,
207
+ middlewares: [offset(4), flip(), shift({ padding: 8 })],
208
+ })
209
+
210
+ // 2. Add submenu node - no separate useFloating call needed!
211
+ const submenuNode = tree.addNode(submenuTriggerEl, submenuEl, {
212
+ placement: "right-start",
213
+ open: isSubmenuOpen,
214
+ middlewares: [offset(4), flip(), shift({ padding: 8 })],
215
+ parentId: tree.root.id, // Link to parent using parentId in options
216
+ })
217
+
218
+ // 3. Add interactions
219
+ useClick(tree.root, { outsideClick: true })
220
+ useHover(submenuNode, { delay: { open: 100, close: 300 } })
221
+
222
+ // Access floating styles from the contexts
223
+ const { floatingStyles: parentStyles } = tree.rootContext
224
+ const { floatingStyles: submenuStyles } = submenuNode.data
182
225
  </script>
183
226
 
184
227
  <template>
185
228
  <!-- Parent Menu Trigger -->
186
- <button ref="parentTriggerRef">Open Menu</button>
229
+ <button ref="parentTriggerEl" @click="isParentOpen = !isParentOpen">Open Menu</button>
187
230
 
188
- <!-- Parent Menu Floating Element -->
189
- <div
190
- v-if="parentContext.open.value"
191
- ref="parentMenuRef"
192
- :style="parentContext.floatingStyles.value"
193
- style="background-color: #f0f0f0; border: 1px solid #ccc; padding: 5px; z-index: 1000;"
194
- >
195
- <div>Parent Menu Item 1</div>
231
+ <!-- Parent Menu -->
232
+ <div v-if="isParentOpen" ref="parentMenuEl" :style="parentStyles" class="menu">
233
+ <div class="menu-item">Menu Item 1</div>
196
234
 
197
- <!-- Submenu Trigger (an item within the parent menu) -->
235
+ <!-- Submenu Trigger -->
198
236
  <div
199
- ref="submenuTriggerRef"
200
- style="padding: 5px; cursor: pointer; hover: background-color: #e0e0e0;"
201
- @mouseenter="() => submenuContext?.setOpen(true)" @mouseleave="() => submenuContext?.setOpen(false)"
202
- <!-- Basic hover for example -->
237
+ ref="submenuTriggerEl"
238
+ class="menu-item menu-item--submenu"
239
+ @click="isSubmenuOpen = !isSubmenuOpen"
203
240
  >
204
- Parent Menu Item 2 (Hover for Submenu)
205
-
206
- <!-- Submenu Floating Element -->
207
- <div
208
- v-if="submenuContext.open.value"
209
- ref="submenuRef"
210
- :style="submenuContext.floatingStyles.value"
211
- style="background-color: #e0e0e0; border: 1px solid #bbb; padding: 5px; margin-left: 10px; z-index: 1010;"
212
- >
213
- <div>Submenu Item A</div>
214
- <div>Submenu Item B</div>
241
+ Menu Item 2 (Has Submenu)
242
+
243
+ <!-- Submenu -->
244
+ <div v-if="isSubmenuOpen" ref="submenuEl" :style="submenuStyles" class="menu submenu">
245
+ <div class="menu-item">Submenu Item A</div>
246
+ <div class="menu-item">Submenu Item B</div>
247
+ <div class="menu-item">Submenu Item C</div>
248
+ </div>
215
249
  </div>
250
+
251
+ <div class="menu-item">Menu Item 3</div>
216
252
  </div>
217
253
  </template>
254
+
255
+ <style scoped>
256
+ .menu {
257
+ background: white;
258
+ border: 1px solid #ddd;
259
+ border-radius: 4px;
260
+ padding: 4px 0;
261
+ box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
262
+ min-width: 160px;
263
+ z-index: 1000;
264
+ }
265
+
266
+ .submenu {
267
+ margin-left: 8px;
268
+ z-index: 1010;
269
+ }
270
+
271
+ .menu-item {
272
+ padding: 8px 12px;
273
+ cursor: pointer;
274
+ user-select: none;
275
+ }
276
+
277
+ .menu-item:hover {
278
+ background-color: #f5f5f5;
279
+ }
280
+
281
+ .menu-item--submenu {
282
+ position: relative;
283
+ }
284
+ </style>
285
+ ```
286
+
287
+ **API Benefits:**
288
+
289
+ ```ts
290
+ // Before: Required separate useFloating calls
291
+ const parentContext = useFloating(parentEl, parentFloating, options)
292
+ const tree = useFloatingTree(parentContext)
293
+ const childContext = useFloating(childEl, childFloating, childOptions)
294
+ const childNode = tree.addNode(childContext, parentContext.nodeId)
295
+
296
+ // After: Streamlined API with internal context creation
297
+ const tree = useFloatingTree(parentEl, parentFloating, options)
298
+ const childNode = tree.addNode(childEl, childFloating, {
299
+ ...childOptions,
300
+ parentId: tree.root.id,
301
+ })
218
302
  ```
219
303
 
220
- This example demonstrates the manual process of creating contexts and then linking them within the tree. For more
221
- complex scenarios, you would integrate interaction composables (`useClick`, `useHover`, `useDismiss`) to manage the
222
- `open` state of each context, potentially using tree methods like `tree.isTopmost()` or `tree.forEach()` to coordinate
223
- behavior (e.g., closing child menus when a parent closes).
304
+ This approach eliminates redundant calls and provides a clearer separation between isolated floating elements (`useFloating`) and hierarchical structures (`useFloatingTree`).
224
305
 
225
306
  ## TypeScript Support
226
307
 
@@ -241,6 +322,65 @@ For complete documentation with interactive examples, visit the [V-Float Documen
241
322
  Contributions are welcome! Please read our contributing guidelines and submit pull requests to
242
323
  our [GitHub repository](https://github.com/sherif414/VFloat).
243
324
 
325
+ ## Development
326
+
327
+ ### Prerequisites
328
+
329
+ - Node.js (18+)
330
+ - pnpm (recommended package manager)
331
+
332
+ ### Setup
333
+
334
+ ```bash
335
+ # Clone the repository
336
+ git clone https://github.com/sherif414/VFloat.git
337
+ cd VFloat
338
+
339
+ # Install dependencies
340
+ pnpm install
341
+
342
+ # Start development server
343
+ pnpm dev
344
+
345
+ # Run tests
346
+ pnpm test:unit
347
+
348
+ # Build for production
349
+ pnpm build
350
+ ```
351
+
352
+ ### Release Process
353
+
354
+ This project uses [release-it](https://github.com/release-it/release-it) for automated releases:
355
+
356
+ ```bash
357
+ # Dry run to see what would happen
358
+ pnpm run release:dry
359
+
360
+ # Release with automatic version bump (interactive)
361
+ pnpm run release
362
+
363
+ # Release specific version types
364
+ pnpm run release:patch # 0.2.1 -> 0.2.2
365
+ pnpm run release:minor # 0.2.1 -> 0.3.0
366
+ pnpm run release:major # 0.2.1 -> 1.0.0
367
+ ```
368
+
369
+ **Release Features:**
370
+
371
+ - Automatic version bumping based on conventional commits
372
+ - Changelog generation from commit messages
373
+ - Git tagging and GitHub releases
374
+ - NPM publishing (when configured)
375
+ - Pre-release validation (linting, type checking, tests)
376
+
377
+ **Before releasing:**
378
+
379
+ 1. Ensure all changes are committed
380
+ 2. Working directory is clean
381
+ 3. You're on the main branch
382
+ 4. All tests pass
383
+
244
384
  ## License
245
385
 
246
386
  MIT License - see [LICENSE](LICENSE) file for details.
@@ -1,6 +1,7 @@
1
1
  export * from './use-hover';
2
2
  export * from './use-focus';
3
3
  export * from './use-click';
4
- export * from './use-dismiss';
5
4
  export * from './use-client-point';
5
+ export * from './use-escape-key';
6
+ export * from './utils';
6
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/composables/interactions/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,eAAe,CAAA;AAC7B,cAAc,oBAAoB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/composables/interactions/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,oBAAoB,CAAA;AAClC,cAAc,kBAAkB,CAAA;AAChC,cAAc,SAAS,CAAA"}
@@ -0,0 +1,38 @@
1
+ import { TreeNode } from '../use-tree';
2
+ import { AnchorElement, FloatingContext, FloatingElement } from '../use-floating';
3
+ type Point = [number, number];
4
+ type Polygon = Point[];
5
+ export interface SafePolygonOptions {
6
+ buffer?: number;
7
+ blockPointerEvents?: boolean;
8
+ requireIntent?: boolean;
9
+ onPolygonChange?: (polygon: Polygon) => void;
10
+ }
11
+ export interface CreateSafePolygonHandlerContext {
12
+ x: number;
13
+ y: number;
14
+ placement: FloatingContext["placement"]["value"];
15
+ elements: {
16
+ domReference: AnchorElement | null;
17
+ floating: FloatingElement | null;
18
+ };
19
+ buffer: number;
20
+ onClose: () => void;
21
+ nodeId?: string;
22
+ tree?: {
23
+ nodes: Map<string, TreeNode<FloatingContext>>;
24
+ };
25
+ }
26
+ /**
27
+ * Generates a safe polygon area that the user can traverse without closing the
28
+ * floating element once leaving the reference element.
29
+ * @see https://floating-ui.com/docs/useHover#safepolygon
30
+ */
31
+ export declare function safePolygon(options?: SafePolygonOptions): {
32
+ (context: CreateSafePolygonHandlerContext): (event: MouseEvent) => void;
33
+ __options: {
34
+ blockPointerEvents: boolean;
35
+ };
36
+ };
37
+ export {};
38
+ //# sourceMappingURL=polygon.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"polygon.d.ts","sourceRoot":"","sources":["../../../src/composables/interactions/polygon.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AAGtD,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAGtF,KAAK,KAAK,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;AAC7B,KAAK,OAAO,GAAG,KAAK,EAAE,CAAA;AAoDtB,MAAM,WAAW,kBAAkB;IACjC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAA;CAC7C;AAED,MAAM,WAAW,+BAA+B;IAC9C,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,SAAS,EAAE,eAAe,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,CAAA;IAChD,QAAQ,EAAE;QACR,YAAY,EAAE,aAAa,GAAG,IAAI,CAAA;QAClC,QAAQ,EAAE,eAAe,GAAG,IAAI,CAAA;KACjC,CAAA;IACD,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE;QAAE,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,eAAe,CAAC,CAAC,CAAA;KAAE,CAAA;CACzD;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,OAAO,GAAE,kBAAuB;cAsCJ,+BAA+B,WAehD,UAAU;;;;EAiVhD"}
@@ -1,23 +1,53 @@
1
- import { MaybeRefOrGetter } from 'vue';
2
1
  import { FloatingContext } from '..';
2
+ import { TreeNode } from '../use-tree';
3
+ import { MaybeRefOrGetter } from 'vue';
3
4
  /**
4
- * Enables showing/hiding the floating element when clicking the reference element.
5
+ * Enables showing/hiding the floating element when clicking the reference element
6
+ * and optionally when clicking outside both the reference and floating elements.
5
7
  *
6
- * This composable provides event handlers for click interactions with the reference element
7
- * to control the visibility of the floating element.
8
+ * This composable provides unified event handlers for both inside click interactions
9
+ * (to open/toggle floating elements) and outside click interactions (to close them).
8
10
  *
9
- * @param context - The floating context with open state and change handler.
11
+ * The composable supports both standalone usage with FloatingContext and tree-aware
12
+ * usage with TreeNode<FloatingContext> for complex nested floating UI structures.
13
+ *
14
+ * @param context - The floating context or tree node with open state and change handler.
10
15
  * @param options - Configuration options for click behavior.
11
16
  *
12
- * @example
17
+ * @example Basic standalone usage with outside click enabled
13
18
  * ```ts
14
19
  * const context = useFloating(...)
15
20
  * useClick(context, {
16
- * event: "mousedown",
21
+ * toggle: true,
22
+ * outsideClick: true,
23
+ * outsideEvent: 'pointerdown'
24
+ * })
25
+ * ```
26
+ *
27
+ * @example Tree-aware usage for nested floating elements
28
+ * ```ts
29
+ * const tree = useFloatingTree(rootContext)
30
+ * const parentNode = tree.root
31
+ * const childNode = tree.addNode(childContext, parentNode.id)
32
+ *
33
+ * // Tree-aware behavior: child won't close when clicked,
34
+ * // but will close when parent or outside is clicked
35
+ * useClick(childNode, { outsideClick: true })
36
+ * ```
37
+ *
38
+ * @example Custom outside click handler
39
+ * ```ts
40
+ * useClick(context, {
41
+ * outsideClick: true,
42
+ * onOutsideClick: (event, context) => {
43
+ * if (confirm('Close dialog?')) {
44
+ * context.setOpen(false)
45
+ * }
46
+ * }
17
47
  * })
18
48
  * ```
19
49
  */
20
- export declare function useClick(context: FloatingContext, options?: UseClickOptions): void;
50
+ export declare function useClick(context: FloatingContext | TreeNode<FloatingContext>, options?: UseClickOptions): void;
21
51
  /**
22
52
  * Options for configuring the useClick behavior.
23
53
  */
@@ -44,9 +74,47 @@ export interface UseClickOptions {
44
74
  */
45
75
  ignoreMouse?: MaybeRefOrGetter<boolean>;
46
76
  /**
47
- * Whether to add keyboard handlers (Enter and Space key functionality).
77
+ * Whether to ignore keyboard handlers (Enter and Space key functionality).
78
+ * @default false
79
+ */
80
+ ignoreKeyboard?: MaybeRefOrGetter<boolean>;
81
+ /**
82
+ * Whether to ignore touch events.
83
+ * @default false
84
+ */
85
+ ignoreTouch?: MaybeRefOrGetter<boolean>;
86
+ /**
87
+ * Whether to enable outside click detection to close the floating element.
88
+ * @default false
89
+ */
90
+ outsideClick?: MaybeRefOrGetter<boolean>;
91
+ /**
92
+ * The event to use for outside click detection.
93
+ * @default 'pointerdown'
94
+ */
95
+ outsideEvent?: MaybeRefOrGetter<"pointerdown" | "mousedown" | "click">;
96
+ /**
97
+ * Whether to use capture phase for document outside click listener.
98
+ * @default true
99
+ */
100
+ outsideCapture?: MaybeRefOrGetter<boolean>;
101
+ /**
102
+ * Custom function to handle outside clicks.
103
+ * If provided, this function will be called instead of the default behavior.
104
+ * The function receives the event and context as parameters.
105
+ * @param event - The mouse event that triggered the outside click
106
+ * @param context - The floating context containing refs and state
107
+ */
108
+ onOutsideClick?: (event: MouseEvent, context: FloatingContext) => void;
109
+ /**
110
+ * Whether to prevent clicks on scrollbars from triggering outside click.
111
+ * @default true
112
+ */
113
+ preventScrollbarClick?: MaybeRefOrGetter<boolean>;
114
+ /**
115
+ * Whether to handle drag events that start inside and end outside.
48
116
  * @default true
49
117
  */
50
- keyboardHandlers?: MaybeRefOrGetter<boolean>;
118
+ handleDragEvents?: MaybeRefOrGetter<boolean>;
51
119
  }
52
120
  //# sourceMappingURL=use-click.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-click.d.ts","sourceRoot":"","sources":["../../../src/composables/interactions/use-click.ts"],"names":[],"mappings":"AACA,OAAO,EAAY,KAAK,gBAAgB,EAA8C,MAAM,KAAK,CAAA;AACjG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAMpD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,eAAe,EAAE,OAAO,GAAE,eAAoB,GAAG,IAAI,CA4HtF;AAqDD;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,OAAO,CAAC,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAA;IAEnC;;;;OAIG;IACH,KAAK,CAAC,EAAE,gBAAgB,CAAC,OAAO,GAAG,WAAW,CAAC,CAAA;IAE/C;;;OAGG;IACH,MAAM,CAAC,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAA;IAElC;;;OAGG;IACH,WAAW,CAAC,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAA;IAEvC;;;OAGG;IACH,gBAAgB,CAAC,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAA;CAC7C"}
1
+ {"version":3,"file":"use-click.d.ts","sourceRoot":"","sources":["../../../src/composables/interactions/use-click.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AACpD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AAGtD,OAAO,EAAE,KAAK,gBAAgB,EAAwD,MAAM,KAAK,CAAA;AAkBjG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AACH,wBAAgB,QAAQ,CACtB,OAAO,EAAE,eAAe,GAAG,QAAQ,CAAC,eAAe,CAAC,EACpD,OAAO,GAAE,eAAoB,GAC5B,IAAI,CAiQN;AA0CD;;GAEG;AACH,MAAM,WAAW,eAAe;IAG9B;;;OAGG;IACH,OAAO,CAAC,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAA;IAEnC;;;;OAIG;IACH,KAAK,CAAC,EAAE,gBAAgB,CAAC,OAAO,GAAG,WAAW,CAAC,CAAA;IAE/C;;;OAGG;IACH,MAAM,CAAC,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAA;IAElC;;;OAGG;IACH,WAAW,CAAC,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAA;IAEvC;;;OAGG;IACH,cAAc,CAAC,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAA;IAE1C;;;OAGG;IACH,WAAW,CAAC,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAA;IAIvC;;;OAGG;IACH,YAAY,CAAC,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAA;IAExC;;;OAGG;IACH,YAAY,CAAC,EAAE,gBAAgB,CAAC,aAAa,GAAG,WAAW,GAAG,OAAO,CAAC,CAAA;IAEtE;;;OAGG;IACH,cAAc,CAAC,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAA;IAE1C;;;;;;OAMG;IACH,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,eAAe,KAAK,IAAI,CAAA;IAEtE;;;OAGG;IACH,qBAAqB,CAAC,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAA;IAEjD;;;OAGG;IACH,gBAAgB,CAAC,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAA;CAC7C"}
@@ -1,5 +1,5 @@
1
- import { MaybeRefOrGetter, Ref } from 'vue';
2
1
  import { FloatingContext } from '..';
2
+ import { MaybeRefOrGetter, Ref } from 'vue';
3
3
  /**
4
4
  * Positions the floating element relative to a client point (mouse position).
5
5
  *
@@ -1 +1 @@
1
- {"version":3,"file":"use-client-point.d.ts","sourceRoot":"","sources":["../../../src/composables/interactions/use-client-point.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,gBAAgB,EAGrB,KAAK,GAAG,EAIT,MAAM,KAAK,CAAA;AACZ,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAOpD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,cAAc,CAC5B,aAAa,EAAE,GAAG,CAAC,WAAW,GAAG,IAAI,CAAC,EACtC,OAAO,EAAE,eAAe,EACxB,OAAO,GAAE,qBAA0B,GAClC,oBAAoB,CA4EtB;AAoGD,MAAM,WAAW,qBAAqB;IACpC;;;OAGG;IACH,OAAO,CAAC,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAA;IAEnC;;;OAGG;IACH,IAAI,CAAC,EAAE,gBAAgB,CAAC,GAAG,GAAG,GAAG,GAAG,MAAM,CAAC,CAAA;IAE3C;;;OAGG;IACH,CAAC,CAAC,EAAE,gBAAgB,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;IAEnC;;;OAGG;IACH,CAAC,CAAC,EAAE,gBAAgB,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;CACpC;AAED,MAAM,WAAW,oBAAoB;IACnC;;OAEG;IACH,WAAW,EAAE,QAAQ,CAAC,GAAG,CAAC;QAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC,CAAC,CAAA;IAClE;;OAEG;IACH,cAAc,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,IAAI,CAAA;CAC/C"}
1
+ {"version":3,"file":"use-client-point.d.ts","sourceRoot":"","sources":["../../../src/composables/interactions/use-client-point.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAGpD,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,GAAG,EAOT,MAAM,KAAK,CAAA;AAOZ;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,cAAc,CAC5B,aAAa,EAAE,GAAG,CAAC,WAAW,GAAG,IAAI,CAAC,EACtC,OAAO,EAAE,eAAe,EACxB,OAAO,GAAE,qBAA0B,GAClC,oBAAoB,CA4EtB;AA8FD,MAAM,WAAW,qBAAqB;IACpC;;;OAGG;IACH,OAAO,CAAC,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAA;IAEnC;;;OAGG;IACH,IAAI,CAAC,EAAE,gBAAgB,CAAC,GAAG,GAAG,GAAG,GAAG,MAAM,CAAC,CAAA;IAE3C;;;OAGG;IACH,CAAC,CAAC,EAAE,gBAAgB,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;IAEnC;;;OAGG;IACH,CAAC,CAAC,EAAE,gBAAgB,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;CACpC;AAED,MAAM,WAAW,oBAAoB;IACnC;;OAEG;IACH,WAAW,EAAE,QAAQ,CAAC,GAAG,CAAC;QAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC,CAAC,CAAA;IAClE;;OAEG;IACH,cAAc,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,IAAI,CAAA;CAC/C"}
@@ -0,0 +1,24 @@
1
+ import { MaybeRefOrGetter } from 'vue';
2
+ export interface UseEscapeKeyOptions {
3
+ /**
4
+ * Condition to enable the escape key listener.
5
+ * @default true
6
+ */
7
+ enabled?: MaybeRefOrGetter<boolean>;
8
+ /**
9
+ * Whether to use capture phase for document event listeners.
10
+ * @default false
11
+ */
12
+ capture?: boolean;
13
+ /**
14
+ * Callback function to be executed when the escape key is pressed.
15
+ */
16
+ onEscape: (event: KeyboardEvent) => void;
17
+ }
18
+ /**
19
+ * A composable to handle the escape key press, with composition event handling.
20
+ *
21
+ * @param options - {@link UseEscapeKeyOptions}
22
+ */
23
+ export declare function useEscapeKey(options: UseEscapeKeyOptions): void;
24
+ //# sourceMappingURL=use-escape-key.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-escape-key.d.ts","sourceRoot":"","sources":["../../../src/composables/interactions/use-escape-key.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,gBAAgB,EAAgB,MAAM,KAAK,CAAA;AAMzD,MAAM,WAAW,mBAAmB;IAClC;;;OAGG;IACH,OAAO,CAAC,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAA;IAEnC;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;IAEjB;;OAEG;IACH,QAAQ,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAA;CACzC;AAMD;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,IAAI,CAe/D"}