v-float 0.2.1 → 0.4.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 (39) hide show
  1. package/README.md +189 -83
  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 +12 -2
  5. package/dist/composables/interactions/polygon.d.ts.map +1 -1
  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 +21 -3
  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 +7 -0
  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/v-float.es.js +1343 -1176
  36. package/dist/v-float.umd.js +1 -1
  37. package/package.json +31 -24
  38. package/dist/composables/interactions/use-dismiss.d.ts +0 -68
  39. 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
@@ -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
- - **`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,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
- - **`arrow`**: Position arrow elements (via `useArrow`)
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, you need to manage the tree structure explicitly. `useFloating` creates
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
- Here's how you can set up a parent menu with a submenu:
183
+ **Clear Separation of Concerns:**
125
184
 
126
- ```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:
127
189
 
190
+ ```vue
128
191
  <script setup lang="ts">
129
- import { useTemplateRef } from "vue";
130
- import { useFloating, useFloatingTree, offset } from "v-float";
131
-
132
- const parentTriggerEl = useTemplateRef("parentTriggerRef");
133
- const parentMenuEl = useTemplateRef("parentMenuRef");
134
-
135
- const submenuTriggerEl = useTemplateRef("submenuTriggerRef");
136
- const submenuEl = useTemplateRef("submenuRef");
137
-
138
- // 1. Create the floating context for the parent menu.
139
- const parentContext = useFloating(parentTriggerEl, parentMenuEl, {
140
- placement: "bottom-start",
141
- middlewares: [offset(4)],
142
- });
143
-
144
- // 2. Create the floating tree, using the parent's context as the data for the root node.
145
- // useFloatingTree will create a root TreeNode whose `data` is parentContext.
146
- const tree = useFloatingTree(parentContext);
147
-
148
- // 3. Create the floating context for the submenu.
149
- const submenuContext = useFloating(submenuTriggerEl, submenuEl, {
150
- placement: "right-start",
151
- middlewares: [offset(4)],
152
- });
153
-
154
- // 4. Add the submenu to the tree as a child of the parent menu.
155
- // tree.root refers to the TreeNode associated with parentContext.
156
- const submenuNode = tree.addNode(submenuContext, tree.root.id);
157
- // 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
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 Floating Element -->
165
- <div
166
- v-if="parentContext.open.value"
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 (an item within the parent menu) -->
235
+ <!-- Submenu Trigger -->
174
236
  <div
175
237
  ref="submenuTriggerEl"
176
- style="padding: 5px; cursor: pointer; hover: background-color: #e0e0e0;"
177
- @mouseenter="() => submenuContext?.setOpen(true)" @mouseleave="() => submenuContext?.setOpen(false)"
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
- <div>Submenu Item A</div>
189
- <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>
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>
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
+ })
193
302
  ```
194
303
 
195
- This example demonstrates the manual process of creating contexts and then linking them within the tree. For more
196
- complex scenarios, you would integrate interaction composables (`useClick`, `useHover`, `useDismiss`) to manage the
197
- `open` state of each context, potentially using tree methods like `tree.isTopmost()` or `tree.forEach()` to coordinate
198
- 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`).
199
305
 
200
306
  ## TypeScript Support
201
307
 
@@ -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"}
@@ -1,4 +1,5 @@
1
- import { FloatingContext, FloatingElement, AnchorElement } from '../use-floating';
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): ({ x, y, placement, elements, buffer: contextBuffer, onClose, }: CreateSafePolygonHandlerContext) => (event: MouseEvent) => void;
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":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAGtF,KAAK,KAAK,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;AAC7B,KAAK,OAAO,GAAG,KAAK,EAAE,CAAA;AAyCtB,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;CACpB;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,OAAO,GAAE,kBAAuB,oEAuCvD,+BAA+B,aASG,UAAU,UA6ShD"}
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"}
@@ -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 `useDismiss`.
8
+ * it should be composed with other hooks like `useClick`, `useHover`, and `useEscapeKey`.
8
9
  *
9
- * @param context - The floating context with open state and change handler.
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, options?: UseFocusOptions): UseFocusReturn;
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
@@ -1 +1 @@
1
- {"version":3,"file":"use-focus.d.ts","sourceRoot":"","sources":["../../../src/composables/interactions/use-focus.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAEpD,OAAO,EAEL,KAAK,gBAAgB,EAMtB,MAAM,KAAK,CAAA;AAMZ;;;;;;;;GAQG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,eAAe,EAAE,OAAO,GAAE,eAAoB,GAAG,cAAc,CA+HhG;AAMD,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,OAAO,CAAC,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAA;IAEnC;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAA;CAChD;AAED;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,SAAS,CAAA"}
1
+ {"version":3,"file":"use-focus.d.ts","sourceRoot":"","sources":["../../../src/composables/interactions/use-focus.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AACpD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AAEtD,OAAO,EACL,KAAK,gBAAgB,EAOtB,MAAM,KAAK,CAAA;AAgBZ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,QAAQ,CACtB,OAAO,EAAE,eAAe,GAAG,QAAQ,CAAC,eAAe,CAAC,EACpD,OAAO,GAAE,eAAoB,GAC5B,cAAc,CAwIhB;AAMD,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,OAAO,CAAC,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAA;IAEnC;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAA;CAChD;AAED;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,SAAS,CAAA"}
@@ -1,3 +1,4 @@
1
+ import { TreeNode } from '../use-tree';
1
2
  import { MaybeRef } from 'vue';
2
3
  import { FloatingContext } from '../use-floating';
3
4
  import { SafePolygonOptions } from './polygon';
@@ -44,10 +45,13 @@ export interface UseHoverOptions {
44
45
  * with enhanced behaviors like delayed open/close, rest detection, and custom
45
46
  * exit handling.
46
47
  *
47
- * @param context - The floating context with open state and change handler
48
+ * The composable supports both standalone usage with FloatingContext and tree-aware
49
+ * usage with TreeNode<FloatingContext> for complex nested floating UI structures.
50
+ *
51
+ * @param context - The floating context or tree node with open state and change handler
48
52
  * @param options - Configuration options for hover behavior
49
53
  *
50
- * @example
54
+ * @example Basic standalone usage
51
55
  * ```ts
52
56
  * const context = useFloating(...)
53
57
  * useHover(context, {
@@ -55,6 +59,20 @@ export interface UseHoverOptions {
55
59
  * restMs: 150
56
60
  * })
57
61
  * ```
62
+ *
63
+ * @example Tree-aware usage for nested floating elements
64
+ * ```ts
65
+ * const tree = useFloatingTree(rootContext)
66
+ * const parentNode = tree.root
67
+ * const childNode = tree.addNode(childContext, parentNode.id)
68
+ *
69
+ * // Tree-aware behavior: child hover won't end when hovering over child,
70
+ * // but will end when hovering outside the entire hierarchy
71
+ * useHover(childNode, {
72
+ * delay: { close: 300 },
73
+ * safePolygon: true
74
+ * })
75
+ * ```
58
76
  */
59
- export declare function useHover(context: FloatingContext, options?: UseHoverOptions): void;
77
+ export declare function useHover(context: FloatingContext | TreeNode<FloatingContext>, options?: UseHoverOptions): void;
60
78
  //# sourceMappingURL=use-hover.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-hover.d.ts","sourceRoot":"","sources":["../../../src/composables/interactions/use-hover.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,QAAQ,EAMd,MAAM,KAAK,CAAA;AACZ,OAAO,KAAK,EAAE,eAAe,EAAkC,MAAM,iBAAiB,CAAA;AACtF,OAAO,EAAe,KAAK,kBAAkB,EAAE,MAAM,WAAW,CAAA;AAQhE,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,OAAO,CAAC,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAA;IAE3B;;;;;OAKG;IACH,KAAK,CAAC,EAAE,QAAQ,CAAC,MAAM,GAAG;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAE5D;;;;;OAKG;IACH,MAAM,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAA;IAEzB;;;OAGG;IACH,SAAS,CAAC,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAA;IAE7B;;;;;;;OAOG;IACH,WAAW,CAAC,EAAE,QAAQ,CAAC,OAAO,GAAG,kBAAkB,CAAC,CAAA;CACrD;AAqED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,eAAe,EAAE,OAAO,GAAE,eAAoB,GAAG,IAAI,CA8LtF"}
1
+ {"version":3,"file":"use-hover.d.ts","sourceRoot":"","sources":["../../../src/composables/interactions/use-hover.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AAGtD,OAAO,EACL,KAAK,QAAQ,EAMd,MAAM,KAAK,CAAA;AACZ,OAAO,KAAK,EAAiB,eAAe,EAAmB,MAAM,iBAAiB,CAAA;AACtF,OAAO,EAAE,KAAK,kBAAkB,EAAe,MAAM,WAAW,CAAA;AAehE,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,OAAO,CAAC,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAA;IAE3B;;;;;OAKG;IACH,KAAK,CAAC,EAAE,QAAQ,CAAC,MAAM,GAAG;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAE5D;;;;;OAKG;IACH,MAAM,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAA;IAEzB;;;OAGG;IACH,SAAS,CAAC,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAA;IAE7B;;;;;;;OAOG;IACH,WAAW,CAAC,EAAE,QAAQ,CAAC,OAAO,GAAG,kBAAkB,CAAC,CAAA;CACrD;AAiED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAgB,QAAQ,CACtB,OAAO,EAAE,eAAe,GAAG,QAAQ,CAAC,eAAe,CAAC,EACpD,OAAO,GAAE,eAAoB,GAC5B,IAAI,CA8ON"}