v-float 0.2.1 → 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.
- package/README.md +248 -83
- package/dist/composables/interactions/index.d.ts +2 -1
- package/dist/composables/interactions/index.d.ts.map +1 -1
- package/dist/composables/interactions/polygon.d.ts +12 -2
- package/dist/composables/interactions/polygon.d.ts.map +1 -1
- package/dist/composables/interactions/use-click.d.ts +78 -10
- package/dist/composables/interactions/use-click.d.ts.map +1 -1
- package/dist/composables/interactions/use-client-point.d.ts +1 -1
- package/dist/composables/interactions/use-client-point.d.ts.map +1 -1
- package/dist/composables/interactions/use-escape-key.d.ts +24 -0
- package/dist/composables/interactions/use-escape-key.d.ts.map +1 -0
- package/dist/composables/interactions/use-focus.d.ts +28 -3
- package/dist/composables/interactions/use-focus.d.ts.map +1 -1
- package/dist/composables/interactions/use-hover.d.ts +21 -3
- package/dist/composables/interactions/use-hover.d.ts.map +1 -1
- package/dist/composables/interactions/utils/browser-detection.d.ts +23 -0
- package/dist/composables/interactions/utils/browser-detection.d.ts.map +1 -0
- package/dist/composables/interactions/utils/element-detection.d.ts +53 -0
- package/dist/composables/interactions/utils/element-detection.d.ts.map +1 -0
- package/dist/composables/interactions/utils/event-utils.d.ts +30 -0
- package/dist/composables/interactions/utils/event-utils.d.ts.map +1 -0
- package/dist/composables/interactions/utils/index.d.ts +11 -0
- package/dist/composables/interactions/utils/index.d.ts.map +1 -0
- package/dist/composables/interactions/utils/tree-context.d.ts +32 -0
- package/dist/composables/interactions/utils/tree-context.d.ts.map +1 -0
- package/dist/composables/middlewares/index.d.ts +0 -1
- package/dist/composables/middlewares/index.d.ts.map +1 -1
- package/dist/composables/use-arrow.d.ts +10 -3
- package/dist/composables/use-arrow.d.ts.map +1 -1
- package/dist/composables/use-floating-tree.d.ts +13 -13
- package/dist/composables/use-floating-tree.d.ts.map +1 -1
- package/dist/composables/use-floating.d.ts +7 -0
- package/dist/composables/use-floating.d.ts.map +1 -1
- package/dist/composables/use-tree.d.ts.map +1 -1
- package/dist/v-float.es.js +1343 -1176
- package/dist/v-float.umd.js +1 -1
- package/package.json +29 -22
- package/dist/composables/interactions/use-dismiss.d.ts +0 -68
- 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
|
-
|
|
38
|
-
|
|
36
|
+
import { useTemplateRef } from "vue"
|
|
37
|
+
import { useFloating, useHover, offset } from "v-float"
|
|
39
38
|
|
|
40
|
-
|
|
41
|
-
|
|
39
|
+
const anchorEl = useTemplateRef("anchorEl")
|
|
40
|
+
const floatingEl = useTemplateRef("floatingEl")
|
|
42
41
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
42
|
+
const context = useFloating(anchorEl, floatingEl, {
|
|
43
|
+
placement: "top",
|
|
44
|
+
middlewares: [offset(8)],
|
|
45
|
+
})
|
|
47
46
|
|
|
48
|
-
|
|
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
|
-
|
|
66
|
-
|
|
63
|
+
import { useTemplateRef } from "vue"
|
|
64
|
+
import { useFloating, useClick, useEscapeKey, offset, flip, shift } from "v-float"
|
|
67
65
|
|
|
68
|
-
|
|
69
|
-
|
|
66
|
+
const triggerEl = useTemplateRef("triggerEl")
|
|
67
|
+
const menuEl = useTemplateRef("menuEl")
|
|
70
68
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
69
|
+
const context = useFloating(triggerEl, menuEl, {
|
|
70
|
+
placement: "bottom-start",
|
|
71
|
+
middlewares: [offset(4), flip(), shift({ padding: 8 })],
|
|
72
|
+
})
|
|
75
73
|
|
|
76
|
-
|
|
77
|
-
|
|
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
|
|
@@ -101,7 +160,7 @@ yarn add v-float
|
|
|
101
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
|
-
- **`
|
|
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,90 +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
|
-
|
|
174
|
+
|
|
175
|
+
**Arrow positioning** is handled by the [`useArrow`](/api/use-arrow) composable, which automatically registers the necessary middleware.
|
|
116
176
|
|
|
117
177
|
## Advanced Features
|
|
118
178
|
|
|
119
179
|
### Floating Trees
|
|
120
180
|
|
|
121
|
-
For nested floating elements like submenus,
|
|
122
|
-
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.
|
|
123
182
|
|
|
124
|
-
|
|
183
|
+
**Clear Separation of Concerns:**
|
|
125
184
|
|
|
126
|
-
|
|
185
|
+
- Use `useFloating` for isolated floating elements
|
|
186
|
+
- Use `useFloatingTree` for hierarchical structures
|
|
127
187
|
|
|
188
|
+
Here's how you can set up a parent menu with a submenu using the new API:
|
|
189
|
+
|
|
190
|
+
```vue
|
|
128
191
|
<script setup lang="ts">
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
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
|
|
158
225
|
</script>
|
|
159
226
|
|
|
160
227
|
<template>
|
|
161
228
|
<!-- Parent Menu Trigger -->
|
|
162
|
-
<button ref="parentTriggerEl">Open Menu</button>
|
|
229
|
+
<button ref="parentTriggerEl" @click="isParentOpen = !isParentOpen">Open Menu</button>
|
|
163
230
|
|
|
164
|
-
<!-- Parent Menu
|
|
165
|
-
<div
|
|
166
|
-
|
|
167
|
-
ref="parentMenuEl"
|
|
168
|
-
:style="parentContext.floatingStyles.value"
|
|
169
|
-
style="background-color: #f0f0f0; border: 1px solid #ccc; padding: 5px; z-index: 1000;"
|
|
170
|
-
>
|
|
171
|
-
<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>
|
|
172
234
|
|
|
173
|
-
<!-- Submenu Trigger
|
|
235
|
+
<!-- Submenu Trigger -->
|
|
174
236
|
<div
|
|
175
237
|
ref="submenuTriggerEl"
|
|
176
|
-
|
|
177
|
-
@
|
|
178
|
-
>
|
|
179
|
-
Parent Menu Item 2 (Hover for Submenu)
|
|
180
|
-
|
|
181
|
-
<!-- Submenu Floating Element -->
|
|
182
|
-
<div
|
|
183
|
-
v-if="submenuContext.open.value"
|
|
184
|
-
ref="submenuEl"
|
|
185
|
-
:style="submenuContext.floatingStyles.value"
|
|
186
|
-
style="background-color: #e0e0e0; border: 1px solid #bbb; padding: 5px; margin-left: 10px; z-index: 1010;"
|
|
238
|
+
class="menu-item menu-item--submenu"
|
|
239
|
+
@click="isSubmenuOpen = !isSubmenuOpen"
|
|
187
240
|
>
|
|
188
|
-
|
|
189
|
-
|
|
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>
|
|
190
249
|
</div>
|
|
250
|
+
|
|
251
|
+
<div class="menu-item">Menu Item 3</div>
|
|
191
252
|
</div>
|
|
192
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>
|
|
193
285
|
```
|
|
194
286
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
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
|
+
})
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
This approach eliminates redundant calls and provides a clearer separation between isolated floating elements (`useFloating`) and hierarchical structures (`useFloatingTree`).
|
|
199
305
|
|
|
200
306
|
## TypeScript Support
|
|
201
307
|
|
|
@@ -216,6 +322,65 @@ For complete documentation with interactive examples, visit the [V-Float Documen
|
|
|
216
322
|
Contributions are welcome! Please read our contributing guidelines and submit pull requests to
|
|
217
323
|
our [GitHub repository](https://github.com/sherif414/VFloat).
|
|
218
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
|
+
|
|
219
384
|
## License
|
|
220
385
|
|
|
221
386
|
MIT License - see [LICENSE](LICENSE) file for details.
|
|
@@ -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,
|
|
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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { TreeNode } from '../use-tree';
|
|
2
|
+
import { AnchorElement, FloatingContext, FloatingElement } from '../use-floating';
|
|
2
3
|
type Point = [number, number];
|
|
3
4
|
type Polygon = Point[];
|
|
4
5
|
export interface SafePolygonOptions {
|
|
@@ -17,12 +18,21 @@ export interface CreateSafePolygonHandlerContext {
|
|
|
17
18
|
};
|
|
18
19
|
buffer: number;
|
|
19
20
|
onClose: () => void;
|
|
21
|
+
nodeId?: string;
|
|
22
|
+
tree?: {
|
|
23
|
+
nodes: Map<string, TreeNode<FloatingContext>>;
|
|
24
|
+
};
|
|
20
25
|
}
|
|
21
26
|
/**
|
|
22
27
|
* Generates a safe polygon area that the user can traverse without closing the
|
|
23
28
|
* floating element once leaving the reference element.
|
|
24
29
|
* @see https://floating-ui.com/docs/useHover#safepolygon
|
|
25
30
|
*/
|
|
26
|
-
export declare function safePolygon(options?: SafePolygonOptions):
|
|
31
|
+
export declare function safePolygon(options?: SafePolygonOptions): {
|
|
32
|
+
(context: CreateSafePolygonHandlerContext): (event: MouseEvent) => void;
|
|
33
|
+
__options: {
|
|
34
|
+
blockPointerEvents: boolean;
|
|
35
|
+
};
|
|
36
|
+
};
|
|
27
37
|
export {};
|
|
28
38
|
//# sourceMappingURL=polygon.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"polygon.d.ts","sourceRoot":"","sources":["../../../src/composables/interactions/polygon.ts"],"names":[],"mappings":"
|
|
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
|
|
7
|
-
* to
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
|
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
|
|
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
|
-
|
|
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":"
|
|
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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-client-point.d.ts","sourceRoot":"","sources":["../../../src/composables/interactions/use-client-point.ts"],"names":[],"mappings":"
|
|
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"}
|
|
@@ -1,15 +1,40 @@
|
|
|
1
1
|
import { FloatingContext } from '..';
|
|
2
|
+
import { TreeNode } from '../use-tree';
|
|
2
3
|
import { MaybeRefOrGetter } from 'vue';
|
|
3
4
|
/**
|
|
4
5
|
* Enables showing/hiding the floating element when focusing the reference element.
|
|
5
6
|
*
|
|
6
7
|
* This composable is responsible for KEYBOARD-ONLY interactions. For a complete user experience,
|
|
7
|
-
* it should be composed with other hooks like `useClick`, `useHover`, and `
|
|
8
|
+
* it should be composed with other hooks like `useClick`, `useHover`, and `useEscapeKey`.
|
|
8
9
|
*
|
|
9
|
-
*
|
|
10
|
+
* The composable supports both standalone usage with FloatingContext and tree-aware
|
|
11
|
+
* usage with TreeNode<FloatingContext> for complex nested floating UI structures.
|
|
12
|
+
*
|
|
13
|
+
* @param context - The floating context or tree node with open state and change handler.
|
|
10
14
|
* @param options - Configuration options for focus behavior.
|
|
15
|
+
*
|
|
16
|
+
* @example Basic standalone usage
|
|
17
|
+
* ```ts
|
|
18
|
+
* const context = useFloating(...)
|
|
19
|
+
* useFocus(context, {
|
|
20
|
+
* enabled: true,
|
|
21
|
+
* requireFocusVisible: true
|
|
22
|
+
* })
|
|
23
|
+
* ```
|
|
24
|
+
*
|
|
25
|
+
* @example Tree-aware usage for nested floating elements
|
|
26
|
+
* ```ts
|
|
27
|
+
* const tree = useFloatingTree(rootContext)
|
|
28
|
+
* const parentNode = tree.root
|
|
29
|
+
* const childNode = tree.addNode(childContext, parentNode.id)
|
|
30
|
+
*
|
|
31
|
+
* // Tree-aware behavior: parent stays open when focus moves to child,
|
|
32
|
+
* // but closes when focus moves outside hierarchy
|
|
33
|
+
* useFocus(parentNode, { requireFocusVisible: true })
|
|
34
|
+
* useFocus(childNode, { requireFocusVisible: true })
|
|
35
|
+
* ```
|
|
11
36
|
*/
|
|
12
|
-
export declare function useFocus(context: FloatingContext
|
|
37
|
+
export declare function useFocus(context: FloatingContext | TreeNode<FloatingContext>, options?: UseFocusOptions): UseFocusReturn;
|
|
13
38
|
export interface UseFocusOptions {
|
|
14
39
|
/**
|
|
15
40
|
* Whether focus event listeners are enabled
|