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.
- package/README.md +249 -109
- 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 +38 -0
- package/dist/composables/interactions/polygon.d.ts.map +1 -0
- 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 +32 -18
- 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 +12 -20
- package/dist/composables/use-floating.d.ts.map +1 -1
- package/dist/composables/use-tree.d.ts.map +1 -1
- package/dist/utils.d.ts +1 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/v-float.es.js +1457 -1061
- package/dist/v-float.umd.js +1 -1
- package/package.json +34 -21
- 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
|
|
@@ -98,10 +157,10 @@ yarn add v-float
|
|
|
98
157
|
|
|
99
158
|
### Interactions
|
|
100
159
|
|
|
101
|
-
- **`useHover`**: Hover interactions with configurable delays
|
|
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,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
|
-
|
|
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,
|
|
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
|
-
|
|
183
|
+
**Clear Separation of Concerns:**
|
|
149
184
|
|
|
150
|
-
|
|
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
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
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="
|
|
229
|
+
<button ref="parentTriggerEl" @click="isParentOpen = !isParentOpen">Open Menu</button>
|
|
187
230
|
|
|
188
|
-
<!-- Parent Menu
|
|
189
|
-
<div
|
|
190
|
-
|
|
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
|
|
235
|
+
<!-- Submenu Trigger -->
|
|
198
236
|
<div
|
|
199
|
-
ref="
|
|
200
|
-
|
|
201
|
-
@
|
|
202
|
-
<!-- Basic hover for example -->
|
|
237
|
+
ref="submenuTriggerEl"
|
|
238
|
+
class="menu-item menu-item--submenu"
|
|
239
|
+
@click="isSubmenuOpen = !isSubmenuOpen"
|
|
203
240
|
>
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
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
|
|
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 +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"}
|
|
@@ -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
|
|
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"}
|