base-ui-vue 0.4.0 → 0.5.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 (187) hide show
  1. package/dist/arrow/TooltipArrow.cjs +609 -0
  2. package/dist/arrow/TooltipArrow.cjs.map +1 -0
  3. package/dist/arrow/TooltipArrow.js +478 -0
  4. package/dist/arrow/TooltipArrow.js.map +1 -0
  5. package/dist/button/Button.cjs +5 -317
  6. package/dist/button/Button.cjs.map +1 -1
  7. package/dist/button/Button.js +3 -249
  8. package/dist/button/Button.js.map +1 -1
  9. package/dist/button/ToolbarButton.cjs +13 -6
  10. package/dist/button/ToolbarButton.cjs.map +1 -1
  11. package/dist/button/ToolbarButton.js +3 -2
  12. package/dist/button/ToolbarButton.js.map +1 -1
  13. package/dist/checkbox/index.cjs +20 -9
  14. package/dist/checkbox/index.cjs.map +1 -1
  15. package/dist/checkbox/index.js +7 -2
  16. package/dist/checkbox/index.js.map +1 -1
  17. package/dist/checkbox-group/CheckboxGroup.cjs +14 -13
  18. package/dist/checkbox-group/CheckboxGroup.cjs.map +1 -1
  19. package/dist/checkbox-group/CheckboxGroup.js +2 -1
  20. package/dist/checkbox-group/CheckboxGroup.js.map +1 -1
  21. package/dist/components/FloatingPortal.cjs +66 -0
  22. package/dist/components/FloatingPortal.cjs.map +1 -0
  23. package/dist/components/FloatingPortal.js +55 -0
  24. package/dist/components/FloatingPortal.js.map +1 -0
  25. package/dist/components/FloatingRootStore.cjs +101 -0
  26. package/dist/components/FloatingRootStore.cjs.map +1 -0
  27. package/dist/components/FloatingRootStore.js +84 -0
  28. package/dist/components/FloatingRootStore.js.map +1 -0
  29. package/dist/components/FloatingTree.cjs +33 -0
  30. package/dist/components/FloatingTree.cjs.map +1 -0
  31. package/dist/components/FloatingTree.js +22 -0
  32. package/dist/components/FloatingTree.js.map +1 -0
  33. package/dist/composite/composite.cjs +6 -0
  34. package/dist/composite/composite.js +1 -1
  35. package/dist/content/ScrollAreaContent.cjs +3 -3
  36. package/dist/content/ScrollAreaContent.cjs.map +1 -1
  37. package/dist/content/ScrollAreaContent.js +1 -1
  38. package/dist/control/FieldControl.cjs +3 -3
  39. package/dist/control/FieldControl.cjs.map +1 -1
  40. package/dist/control/FieldControl.js +1 -1
  41. package/dist/control/SliderControl.cjs +3 -3
  42. package/dist/control/SliderControl.cjs.map +1 -1
  43. package/dist/control/SliderControl.js +1 -1
  44. package/dist/corner/ScrollAreaCorner.cjs +3 -3
  45. package/dist/corner/ScrollAreaCorner.cjs.map +1 -1
  46. package/dist/corner/ScrollAreaCorner.js +1 -1
  47. package/dist/decrement/NumberFieldDecrement.cjs +10 -3
  48. package/dist/decrement/NumberFieldDecrement.cjs.map +1 -1
  49. package/dist/decrement/NumberFieldDecrement.js +3 -2
  50. package/dist/decrement/NumberFieldDecrement.js.map +1 -1
  51. package/dist/description/FieldDescription.cjs +2 -2
  52. package/dist/description/FieldDescription.cjs.map +1 -1
  53. package/dist/description/FieldDescription.js +1 -1
  54. package/dist/error/FieldError.cjs +2 -2
  55. package/dist/error/FieldError.cjs.map +1 -1
  56. package/dist/error/FieldError.js +1 -1
  57. package/dist/fallback/AvatarFallback.cjs +2 -2
  58. package/dist/fallback/AvatarFallback.cjs.map +1 -1
  59. package/dist/fallback/AvatarFallback.js +1 -1
  60. package/dist/floating-ui-vue/index.js +638 -0
  61. package/dist/floating-ui-vue/index.js.map +1 -0
  62. package/dist/form/Form.cjs +3 -3
  63. package/dist/form/Form.cjs.map +1 -1
  64. package/dist/form/Form.js +1 -1
  65. package/dist/group/NumberFieldGroup.cjs +3 -3
  66. package/dist/group/NumberFieldGroup.cjs.map +1 -1
  67. package/dist/group/NumberFieldGroup.js +1 -1
  68. package/dist/group/ToolbarGroup.cjs +2 -2
  69. package/dist/group/ToolbarGroup.cjs.map +1 -1
  70. package/dist/group/ToolbarGroup.js +1 -1
  71. package/dist/header/AccordionHeader.cjs +2 -2
  72. package/dist/header/AccordionHeader.cjs.map +1 -1
  73. package/dist/header/AccordionHeader.js +1 -1
  74. package/dist/hooks/useDismiss.cjs +502 -0
  75. package/dist/hooks/useDismiss.cjs.map +1 -0
  76. package/dist/hooks/useHoverFloatingInteraction.cjs +233 -0
  77. package/dist/hooks/useHoverFloatingInteraction.cjs.map +1 -0
  78. package/dist/image/AvatarImage.cjs +4 -4
  79. package/dist/image/AvatarImage.cjs.map +1 -1
  80. package/dist/image/AvatarImage.js +1 -1
  81. package/dist/increment/NumberFieldIncrement.cjs +3 -2
  82. package/dist/increment/NumberFieldIncrement.cjs.map +1 -1
  83. package/dist/increment/NumberFieldIncrement.js +2 -1
  84. package/dist/increment/NumberFieldIncrement.js.map +1 -1
  85. package/dist/index.cjs +60 -7
  86. package/dist/index.d.cts +3838 -1726
  87. package/dist/index.d.cts.map +1 -1
  88. package/dist/index.d.ts +3838 -1726
  89. package/dist/index.d.ts.map +1 -1
  90. package/dist/index.js +4 -3
  91. package/dist/index2.cjs +7475 -3089
  92. package/dist/index2.cjs.map +1 -1
  93. package/dist/index2.js +7215 -3106
  94. package/dist/index2.js.map +1 -1
  95. package/dist/rolldown-runtime.js +36 -0
  96. package/package.json +1 -1
  97. package/src/floating-ui-vue/components/FloatingPortal.ts +171 -0
  98. package/src/floating-ui-vue/components/FloatingPortal.vue +259 -0
  99. package/src/floating-ui-vue/components/FloatingRootStore.ts +83 -0
  100. package/src/floating-ui-vue/components/FloatingTree.ts +64 -0
  101. package/src/floating-ui-vue/components/FloatingTreeStore.ts +21 -0
  102. package/src/floating-ui-vue/hooks/useDismiss.ts +689 -0
  103. package/src/floating-ui-vue/hooks/useHoverFloatingInteraction.ts +244 -0
  104. package/src/floating-ui-vue/hooks/useHoverInteractionSharedState.ts +125 -0
  105. package/src/floating-ui-vue/hooks/useHoverShared.ts +53 -0
  106. package/src/floating-ui-vue/index.ts +48 -0
  107. package/src/floating-ui-vue/middleware/arrow.ts +114 -0
  108. package/src/floating-ui-vue/types.ts +117 -0
  109. package/src/floating-ui-vue/utils/composite.ts +20 -0
  110. package/src/floating-ui-vue/utils/constants.ts +2 -0
  111. package/src/floating-ui-vue/utils/createAttribute.ts +3 -0
  112. package/src/floating-ui-vue/utils/createEventEmitter.ts +20 -0
  113. package/src/floating-ui-vue/utils/element.ts +59 -0
  114. package/src/floating-ui-vue/utils/event.ts +15 -0
  115. package/src/floating-ui-vue/utils/nodes.ts +14 -0
  116. package/src/floating-ui-vue/utils/tabbable.ts +309 -0
  117. package/src/index.ts +4 -0
  118. package/src/radio/index.ts +28 -0
  119. package/src/radio/indicator/RadioIndicator.vue +90 -0
  120. package/src/radio/indicator/RadioIndicatorDataAttributes.ts +54 -0
  121. package/src/radio/root/RadioRoot.vue +544 -0
  122. package/src/radio/root/RadioRootContext.ts +18 -0
  123. package/src/radio/root/RadioRootDataAttributes.ts +46 -0
  124. package/src/radio/utils/stateAttributesMapping.ts +29 -0
  125. package/src/radio-group/RadioGroup.vue +381 -0
  126. package/src/radio-group/RadioGroupContext.ts +42 -0
  127. package/src/radio-group/RadioGroupDataAttributes.ts +6 -0
  128. package/src/radio-group/index.ts +10 -0
  129. package/src/tabs/index.ts +38 -0
  130. package/src/tabs/indicator/TabsIndicator.vue +201 -0
  131. package/src/tabs/indicator/TabsIndicatorCssVars.ts +26 -0
  132. package/src/tabs/indicator/TabsIndicatorDataAttributes.ts +12 -0
  133. package/src/tabs/indicator/prehydrationScript.min.ts +5 -0
  134. package/src/tabs/indicator/prehydrationScript.template.js +87 -0
  135. package/src/tabs/list/TabsList.vue +201 -0
  136. package/src/tabs/list/TabsListContext.ts +29 -0
  137. package/src/tabs/list/TabsListDataAttributes.ts +12 -0
  138. package/src/tabs/panel/TabsPanel.vue +167 -0
  139. package/src/tabs/panel/TabsPanelDataAttributes.ts +28 -0
  140. package/src/tabs/root/TabsRoot.vue +468 -0
  141. package/src/tabs/root/TabsRootContext.ts +56 -0
  142. package/src/tabs/root/TabsRootDataAttributes.ts +12 -0
  143. package/src/tabs/root/stateAttributesMapping.ts +9 -0
  144. package/src/tabs/tab/TabsTab.vue +274 -0
  145. package/src/tabs/tab/TabsTabDataAttributes.ts +20 -0
  146. package/src/tabs/utils/areTabValuesEqual.ts +6 -0
  147. package/src/tooltip/arrow/TooltipArrow.vue +116 -0
  148. package/src/tooltip/arrow/TooltipArrowDataAttributes.ts +31 -0
  149. package/src/tooltip/index.ts +54 -0
  150. package/src/tooltip/popup/TooltipPopup.vue +142 -0
  151. package/src/tooltip/popup/TooltipPopupDataAttributes.ts +35 -0
  152. package/src/tooltip/portal/TooltipPortal.vue +83 -0
  153. package/src/tooltip/portal/TooltipPortalContext.ts +19 -0
  154. package/src/tooltip/positioner/TooltipPositioner.vue +221 -0
  155. package/src/tooltip/positioner/TooltipPositionerContext.ts +23 -0
  156. package/src/tooltip/positioner/TooltipPositionerCssVars.ts +27 -0
  157. package/src/tooltip/positioner/TooltipPositionerDataAttributes.ts +26 -0
  158. package/src/tooltip/provider/TooltipProvider.vue +78 -0
  159. package/src/tooltip/provider/TooltipProviderContext.ts +19 -0
  160. package/src/tooltip/root/TooltipRoot.vue +401 -0
  161. package/src/tooltip/root/TooltipRootContext.ts +71 -0
  162. package/src/tooltip/store/TooltipHandle.ts +215 -0
  163. package/src/tooltip/trigger/TooltipTrigger.vue +343 -0
  164. package/src/tooltip/trigger/TooltipTriggerDataAttributes.ts +12 -0
  165. package/src/tooltip/utils/constants.ts +2 -0
  166. package/src/tooltip/viewport/TooltipViewport.vue +149 -0
  167. package/src/tooltip/viewport/TooltipViewportCssVars.ts +14 -0
  168. package/src/tooltip/viewport/TooltipViewportDataAttributes.ts +26 -0
  169. package/src/utils/FloatingPortalLite.vue +66 -0
  170. package/src/utils/FocusGuard.vue +36 -0
  171. package/src/utils/adaptiveOriginMiddleware.ts +79 -0
  172. package/src/utils/addEventListener.ts +16 -0
  173. package/src/utils/constants.ts +11 -0
  174. package/src/utils/createBaseUIEventDetails.ts +2 -0
  175. package/src/utils/getCssDimensions.ts +19 -0
  176. package/src/utils/getDisabledMountTransitionStyles.ts +9 -0
  177. package/src/utils/hideMiddleware.ts +19 -0
  178. package/src/utils/mergeCleanups.ts +7 -0
  179. package/src/utils/platform.ts +18 -0
  180. package/src/utils/popupStateMapping.ts +103 -0
  181. package/src/utils/reasons.ts +4 -0
  182. package/src/utils/serializeValue.ts +17 -0
  183. package/src/utils/useAnchorPositioning.ts +644 -0
  184. package/src/utils/usePopupAutoResize.ts +254 -0
  185. package/src/utils/usePopupViewport.ts +398 -0
  186. package/src/utils/usePositioner.ts +61 -0
  187. package/src/utils/useRenderElement.ts +3 -0
@@ -0,0 +1,83 @@
1
+ <script setup lang="ts">
2
+ import type { FloatingPortal } from '../../floating-ui-vue'
3
+ import type { BaseUIComponentProps } from '../../utils/types'
4
+ import { computed, provide, shallowRef, toRef, unref, useAttrs } from 'vue'
5
+ import FloatingPortalLite from '../../utils/FloatingPortalLite.vue'
6
+ import { useTooltipRootContext } from '../root/TooltipRootContext'
7
+ import { tooltipPortalContextKey } from './TooltipPortalContext'
8
+
9
+ /**
10
+ * A portal element that moves the popup to a different part of the DOM.
11
+ * By default, the portal element is appended to `<body>`.
12
+ * Renders a `<div>` element.
13
+ *
14
+ * Documentation: [Base UI Vue Tooltip](https://baseui-vue.com/docs/components/tooltip)
15
+ */
16
+ defineOptions({
17
+ name: 'TooltipPortal',
18
+ inheritAttrs: false,
19
+ })
20
+
21
+ const props = withDefaults(defineProps<TooltipPortalProps>(), {
22
+ keepMounted: false,
23
+ disabled: false,
24
+ })
25
+
26
+ const attrs = useAttrs()
27
+ const ctx = useTooltipRootContext()
28
+ const keepMounted = toRef(props, 'keepMounted')
29
+ const shouldRender = computed(() => ctx.mounted.value || props.keepMounted)
30
+ const portalRef = shallowRef<{
31
+ element?: HTMLElement | null
32
+ } | null>(null)
33
+ const element = computed(() => unref(portalRef.value?.element) ?? null)
34
+
35
+ provide(tooltipPortalContextKey, keepMounted)
36
+
37
+ defineExpose({
38
+ element,
39
+ })
40
+ </script>
41
+
42
+ <script lang="ts">
43
+ export interface TooltipPortalState {}
44
+
45
+ export interface TooltipPortalProps
46
+ extends BaseUIComponentProps<TooltipPortalState> {
47
+ /**
48
+ * Whether to keep the portal mounted in the DOM while the popup is hidden.
49
+ * @default false
50
+ */
51
+ keepMounted?: boolean
52
+ /**
53
+ * A parent element to render the portal element into.
54
+ */
55
+ container?: FloatingPortal.Container
56
+ /**
57
+ * Teleport target.
58
+ * @default 'body'
59
+ */
60
+ to?: FloatingPortal.Target
61
+ /**
62
+ * Disables Vue Teleport while preserving tooltip mounting behavior.
63
+ * @default false
64
+ */
65
+ disabled?: boolean
66
+ }
67
+ </script>
68
+
69
+ <template>
70
+ <FloatingPortalLite
71
+ v-if="shouldRender"
72
+ ref="portalRef"
73
+ :as="props.as"
74
+ :class="props.class"
75
+ :style="props.style"
76
+ :container="props.container"
77
+ :to="props.to"
78
+ :disabled="props.disabled"
79
+ v-bind="attrs"
80
+ >
81
+ <slot />
82
+ </FloatingPortalLite>
83
+ </template>
@@ -0,0 +1,19 @@
1
+ import type { InjectionKey, Ref } from 'vue'
2
+ import { inject } from 'vue'
3
+
4
+ export type TooltipPortalContext = Ref<boolean>
5
+
6
+ export const tooltipPortalContextKey: InjectionKey<TooltipPortalContext>
7
+ = Symbol('TooltipPortalContext')
8
+
9
+ export function useTooltipPortalContext(): TooltipPortalContext {
10
+ const context = inject(tooltipPortalContextKey, undefined)
11
+
12
+ if (context === undefined) {
13
+ throw new Error(
14
+ 'Base UI Vue: <TooltipPortal> is missing.',
15
+ )
16
+ }
17
+
18
+ return context
19
+ }
@@ -0,0 +1,221 @@
1
+ <script setup lang="ts">
2
+ import type {
3
+ Padding,
4
+ Placement,
5
+ Strategy,
6
+ VirtualElement,
7
+ } from '../../floating-ui-vue'
8
+ import type { BaseUIComponentProps } from '../../utils/types'
9
+ import type {
10
+ Align,
11
+ Boundary,
12
+ CollisionAvoidance,
13
+ OffsetFunction,
14
+ Side,
15
+ } from '../../utils/useAnchorPositioning'
16
+ import type { TooltipInstantType } from '../root/TooltipRoot.vue'
17
+ import { computed, provide, useAttrs } from 'vue'
18
+ import { adaptiveOrigin } from '../../utils/adaptiveOriginMiddleware'
19
+ import { POPUP_COLLISION_AVOIDANCE, useAnchorPositioning } from '../../utils/useAnchorPositioning'
20
+ import { useMergedRefs } from '../../utils/useMergedRefs'
21
+ import { usePositioner } from '../../utils/usePositioner'
22
+ import { useTooltipPortalContext } from '../portal/TooltipPortalContext'
23
+ import { useTooltipRootContext } from '../root/TooltipRootContext'
24
+ import { tooltipPositionerContextKey } from './TooltipPositionerContext'
25
+
26
+ /**
27
+ * Positions the tooltip against the trigger.
28
+ * Renders a `<div>` element.
29
+ *
30
+ * Documentation: [Base UI Vue Tooltip](https://baseui-vue.com/docs/components/tooltip)
31
+ */
32
+ defineOptions({
33
+ name: 'TooltipPositioner',
34
+ inheritAttrs: false,
35
+ })
36
+
37
+ const props = withDefaults(defineProps<TooltipPositionerProps>(), {
38
+ as: 'div',
39
+ positionMethod: 'absolute',
40
+ side: 'top',
41
+ align: 'center',
42
+ sideOffset: 0,
43
+ alignOffset: 0,
44
+ collisionBoundary: 'clipping-ancestors',
45
+ collisionPadding: 5,
46
+ arrowPadding: 5,
47
+ sticky: false,
48
+ disableAnchorTracking: false,
49
+ collisionAvoidance: () => POPUP_COLLISION_AVOIDANCE,
50
+ })
51
+
52
+ const attrs = useAttrs()
53
+ const ctx = useTooltipRootContext()
54
+ const portalKeepMounted = useTooltipPortalContext()
55
+
56
+ const reference = computed(() => props.anchor ?? ctx.activeTrigger.value?.element ?? null)
57
+
58
+ const positioning = useAnchorPositioning({
59
+ anchor: reference,
60
+ positionMethod: () => props.positionMethod,
61
+ mounted: () => ctx.mounted.value,
62
+ keepMounted: () => portalKeepMounted.value,
63
+ side: () => props.side,
64
+ sideOffset: () => props.sideOffset,
65
+ align: () => props.align,
66
+ alignOffset: () => props.alignOffset,
67
+ collisionBoundary: () => props.collisionBoundary,
68
+ collisionPadding: () => props.collisionPadding,
69
+ sticky: () => props.sticky,
70
+ arrowPadding: () => props.arrowPadding,
71
+ disableAnchorTracking: () => props.disableAnchorTracking,
72
+ collisionAvoidance: () => props.collisionAvoidance,
73
+ adaptiveOrigin: () => ctx.hasViewport.value ? adaptiveOrigin : undefined,
74
+ positionerSizeVars: () => !ctx.hasViewport.value,
75
+ autoUpdateOptions: () => ({
76
+ animationFrame: ctx.trackCursorAxis.value === 'both',
77
+ }),
78
+ })
79
+
80
+ const shouldRender = computed(() => ctx.mounted.value || portalKeepMounted.value)
81
+ const inert = computed(() =>
82
+ !ctx.open.value || ctx.trackCursorAxis.value === 'both' || ctx.disableHoverablePopup.value,
83
+ )
84
+
85
+ const state = computed<TooltipPositionerState>(() => ({
86
+ open: ctx.open.value,
87
+ side: positioning.side.value,
88
+ align: positioning.align.value,
89
+ anchorHidden: positioning.anchorHidden.value,
90
+ instant: ctx.trackCursorAxis.value !== 'none' ? 'tracking-cursor' : ctx.instantType.value,
91
+ }))
92
+
93
+ const positionerProps = computed(() => {
94
+ return attrs as Record<string, any>
95
+ })
96
+
97
+ const {
98
+ tag,
99
+ mergedProps,
100
+ renderless,
101
+ ref: renderRef,
102
+ } = usePositioner({
103
+ as: props.as,
104
+ class: props.class,
105
+ style: props.style,
106
+ }, state, {
107
+ styles: positioning.positionerStyles,
108
+ transitionStatus: ctx.transitionStatus,
109
+ props: positionerProps,
110
+ refs: useMergedRefs(positioning.positionerRef, ctx.positionerRef),
111
+ hidden: () => !ctx.mounted.value,
112
+ inert,
113
+ })
114
+
115
+ provide(tooltipPositionerContextKey, positioning)
116
+ </script>
117
+
118
+ <script lang="ts">
119
+ export type TooltipSide = Side
120
+ export type TooltipAlign = Align
121
+ export type TooltipPositionerInstantType = TooltipInstantType | 'tracking-cursor'
122
+ export type TooltipFloatingPlacement = Placement
123
+
124
+ export interface TooltipPositionerState {
125
+ /**
126
+ * Whether the tooltip is currently open.
127
+ */
128
+ open: boolean
129
+ /**
130
+ * The side of the anchor the component is placed on.
131
+ */
132
+ side: TooltipSide
133
+ /**
134
+ * The alignment of the component relative to the anchor.
135
+ */
136
+ align: TooltipAlign
137
+ /**
138
+ * Whether the anchor element is hidden.
139
+ */
140
+ anchorHidden: boolean
141
+ /**
142
+ * Whether CSS transitions should be disabled.
143
+ */
144
+ instant: TooltipPositionerInstantType
145
+ }
146
+
147
+ export interface TooltipPositionerProps
148
+ extends BaseUIComponentProps<TooltipPositionerState> {
149
+ /**
150
+ * An element to position the popup against.
151
+ * By default, the popup will be positioned against the trigger.
152
+ */
153
+ anchor?: Element | VirtualElement | null
154
+ /**
155
+ * Determines which CSS `position` property to use.
156
+ * @default 'absolute'
157
+ */
158
+ positionMethod?: Strategy
159
+ /**
160
+ * Which side of the anchor element to align the popup against.
161
+ * May automatically change to avoid collisions.
162
+ * @default 'top'
163
+ */
164
+ side?: TooltipSide
165
+ /**
166
+ * How to align the popup relative to the specified side.
167
+ * @default 'center'
168
+ */
169
+ align?: TooltipAlign
170
+ /**
171
+ * Distance between the anchor and the popup in pixels.
172
+ * @default 0
173
+ */
174
+ sideOffset?: number | OffsetFunction
175
+ /**
176
+ * Additional offset along the alignment axis in pixels.
177
+ * @default 0
178
+ */
179
+ alignOffset?: number | OffsetFunction
180
+ /**
181
+ * An element or a rectangle that delimits the area that the popup is confined to.
182
+ * @default 'clipping-ancestors'
183
+ */
184
+ collisionBoundary?: Boundary
185
+ /**
186
+ * Additional space to maintain from the edge of the collision boundary.
187
+ * @default 5
188
+ */
189
+ collisionPadding?: Padding
190
+ /**
191
+ * Minimum distance to maintain between the arrow and the edges of the popup.
192
+ *
193
+ * Use it to prevent the arrow element from hanging out of the rounded corners of a popup.
194
+ * @default 5
195
+ */
196
+ arrowPadding?: Padding
197
+ /**
198
+ * Whether to maintain the popup in the viewport after
199
+ * the anchor element was scrolled out of view.
200
+ * @default false
201
+ */
202
+ sticky?: boolean
203
+ /**
204
+ * Whether to disable the popup from tracking any layout shift of its positioning anchor.
205
+ * @default false
206
+ */
207
+ disableAnchorTracking?: boolean
208
+ /**
209
+ * Determines how to handle collisions when positioning the popup.
210
+ * @default { fallbackAxisSide: 'end' }
211
+ */
212
+ collisionAvoidance?: CollisionAvoidance
213
+ }
214
+ </script>
215
+
216
+ <template>
217
+ <slot v-if="renderless && shouldRender" :ref="renderRef" :props="mergedProps" :state="state" />
218
+ <component :is="tag" v-else-if="shouldRender" :ref="renderRef" v-bind="mergedProps">
219
+ <slot :state="state" />
220
+ </component>
221
+ </template>
@@ -0,0 +1,23 @@
1
+ import type { InjectionKey } from 'vue'
2
+ import type { UseAnchorPositioningReturnValue } from '../../utils/useAnchorPositioning'
3
+ import { inject } from 'vue'
4
+
5
+ export type TooltipPositionerContext = Pick<
6
+ UseAnchorPositioningReturnValue,
7
+ 'side' | 'align' | 'arrowRef' | 'arrowUncentered' | 'arrowStyles'
8
+ >
9
+
10
+ export const tooltipPositionerContextKey: InjectionKey<TooltipPositionerContext>
11
+ = Symbol('TooltipPositionerContext')
12
+
13
+ export function useTooltipPositionerContext(): TooltipPositionerContext {
14
+ const context = inject(tooltipPositionerContextKey, undefined)
15
+
16
+ if (context === undefined) {
17
+ throw new Error(
18
+ 'Base UI Vue: TooltipPositionerContext is missing. Tooltip parts must be placed within <TooltipPositioner>.',
19
+ )
20
+ }
21
+
22
+ return context
23
+ }
@@ -0,0 +1,27 @@
1
+ export enum TooltipPositionerCssVars {
2
+ /**
3
+ * The available width between the trigger and the edge of the viewport.
4
+ * @type {number}
5
+ */
6
+ availableWidth = '--available-width',
7
+ /**
8
+ * The available height between the trigger and the edge of the viewport.
9
+ * @type {number}
10
+ */
11
+ availableHeight = '--available-height',
12
+ /**
13
+ * The anchor's width.
14
+ * @type {number}
15
+ */
16
+ anchorWidth = '--anchor-width',
17
+ /**
18
+ * The anchor's height.
19
+ * @type {number}
20
+ */
21
+ anchorHeight = '--anchor-height',
22
+ /**
23
+ * The coordinates that this element is anchored to. Used for animations and transitions.
24
+ * @type {string}
25
+ */
26
+ transformOrigin = '--transform-origin',
27
+ }
@@ -0,0 +1,26 @@
1
+ import { CommonPopupDataAttributes } from '../../utils/popupStateMapping'
2
+
3
+ export enum TooltipPositionerDataAttributes {
4
+ /**
5
+ * Present when the tooltip is open.
6
+ */
7
+ open = CommonPopupDataAttributes.open,
8
+ /**
9
+ * Present when the tooltip is closed.
10
+ */
11
+ closed = CommonPopupDataAttributes.closed,
12
+ /**
13
+ * Present when the anchor is hidden.
14
+ */
15
+ anchorHidden = CommonPopupDataAttributes.anchorHidden,
16
+ /**
17
+ * Indicates which side the popup is positioned relative to the trigger.
18
+ * @type {'top' | 'bottom' | 'left' | 'right' | 'inline-end' | 'inline-start'}
19
+ */
20
+ side = CommonPopupDataAttributes.side,
21
+ /**
22
+ * Indicates how the popup is aligned relative to specified side.
23
+ * @type {'start' | 'center' | 'end'}
24
+ */
25
+ align = CommonPopupDataAttributes.align,
26
+ }
@@ -0,0 +1,78 @@
1
+ <script setup lang="ts">
2
+ import { computed, provide, shallowRef, toRef } from 'vue'
3
+ import { OPEN_DELAY } from '../utils/constants'
4
+ import { tooltipProviderContextKey } from './TooltipProviderContext'
5
+
6
+ /**
7
+ * Provides a shared delay for multiple tooltips. The grouping logic ensures that
8
+ * once a tooltip becomes visible, the adjacent tooltips will be shown instantly.
9
+ *
10
+ * Documentation: [Base UI Vue Tooltip](https://baseui-vue.com/docs/components/tooltip)
11
+ */
12
+ defineOptions({
13
+ name: 'TooltipProvider',
14
+ })
15
+
16
+ const props = withDefaults(defineProps<TooltipProviderProps>(), {
17
+ timeout: 400,
18
+ })
19
+
20
+ const lastCloseTime = shallowRef<number | null>(null)
21
+
22
+ const delay = toRef(props, 'delay')
23
+ const closeDelay = toRef(props, 'closeDelay')
24
+ const timeout = computed(() => props.timeout)
25
+
26
+ provide(tooltipProviderContextKey, {
27
+ delay,
28
+ closeDelay,
29
+ timeout,
30
+ getOpenDelay(triggerDelay) {
31
+ const now = Date.now()
32
+ const instant = lastCloseTime.value != null && now - lastCloseTime.value <= timeout.value
33
+
34
+ if (instant) {
35
+ return { delay: 0, instant: true }
36
+ }
37
+
38
+ return {
39
+ delay: triggerDelay ?? delay.value ?? OPEN_DELAY,
40
+ instant: false,
41
+ }
42
+ },
43
+ getCloseDelay(triggerCloseDelay) {
44
+ return triggerCloseDelay ?? closeDelay.value ?? 0
45
+ },
46
+ notifyOpen() {
47
+ lastCloseTime.value = null
48
+ },
49
+ notifyClose() {
50
+ lastCloseTime.value = Date.now()
51
+ },
52
+ })
53
+ </script>
54
+
55
+ <script lang="ts">
56
+ export interface TooltipProviderState {}
57
+
58
+ export interface TooltipProviderProps {
59
+ /**
60
+ * How long to wait before opening a tooltip. Specified in milliseconds.
61
+ */
62
+ delay?: number
63
+ /**
64
+ * How long to wait before closing a tooltip. Specified in milliseconds.
65
+ */
66
+ closeDelay?: number
67
+ /**
68
+ * Another tooltip will open instantly if the previous tooltip
69
+ * is closed within this timeout. Specified in milliseconds.
70
+ * @default 400
71
+ */
72
+ timeout?: number
73
+ }
74
+ </script>
75
+
76
+ <template>
77
+ <slot />
78
+ </template>
@@ -0,0 +1,19 @@
1
+ import type { InjectionKey, Ref } from 'vue'
2
+ import { inject } from 'vue'
3
+
4
+ export interface TooltipProviderContext {
5
+ delay: Ref<number | undefined>
6
+ closeDelay: Ref<number | undefined>
7
+ timeout: Readonly<Ref<number>>
8
+ getOpenDelay: (triggerDelay: number | undefined) => { delay: number, instant: boolean }
9
+ getCloseDelay: (triggerCloseDelay: number | undefined) => number
10
+ notifyOpen: () => void
11
+ notifyClose: () => void
12
+ }
13
+
14
+ export const tooltipProviderContextKey: InjectionKey<TooltipProviderContext>
15
+ = Symbol('TooltipProviderContext')
16
+
17
+ export function useTooltipProviderContext(): TooltipProviderContext | undefined {
18
+ return inject(tooltipProviderContextKey, undefined)
19
+ }