base-ui-vue 0.1.0 → 0.2.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.
- package/README.md +41 -1
- package/dist/button/Button.cjs +53 -12
- package/dist/button/Button.cjs.map +1 -1
- package/dist/button/Button.js +26 -15
- package/dist/button/Button.js.map +1 -1
- package/dist/button/ToolbarButton.cjs +367 -0
- package/dist/button/ToolbarButton.cjs.map +1 -0
- package/dist/button/ToolbarButton.js +320 -0
- package/dist/button/ToolbarButton.js.map +1 -0
- package/dist/button/ToolbarButtonDataAttributes.cjs +27 -0
- package/dist/button/ToolbarButtonDataAttributes.cjs.map +1 -0
- package/dist/button/ToolbarButtonDataAttributes.js +21 -0
- package/dist/button/ToolbarButtonDataAttributes.js.map +1 -0
- package/dist/checkbox/index.cjs +1173 -0
- package/dist/checkbox/index.cjs.map +1 -0
- package/dist/checkbox/index.js +1048 -0
- package/dist/checkbox/index.js.map +1 -0
- package/dist/checkbox-group/CheckboxGroup.cjs +629 -0
- package/dist/checkbox-group/CheckboxGroup.cjs.map +1 -0
- package/dist/checkbox-group/CheckboxGroup.js +540 -0
- package/dist/checkbox-group/CheckboxGroup.js.map +1 -0
- package/dist/checkbox-group/CheckboxGroupDataAttributes.cjs +18 -0
- package/dist/checkbox-group/CheckboxGroupDataAttributes.cjs.map +1 -0
- package/dist/checkbox-group/CheckboxGroupDataAttributes.js +12 -0
- package/dist/checkbox-group/CheckboxGroupDataAttributes.js.map +1 -0
- package/dist/composite/composite.cjs +167 -0
- package/dist/composite/composite.cjs.map +1 -1
- package/dist/composite/composite.js +96 -1
- package/dist/composite/composite.js.map +1 -1
- package/dist/composite/constants.cjs +12 -0
- package/dist/composite/constants.cjs.map +1 -0
- package/dist/composite/constants.js +6 -0
- package/dist/composite/constants.js.map +1 -0
- package/dist/control/FieldControl.cjs +18 -343
- package/dist/control/FieldControl.cjs.map +1 -1
- package/dist/control/FieldControl.js +14 -285
- package/dist/control/FieldControl.js.map +1 -1
- package/dist/control/SliderControl.cjs +636 -0
- package/dist/control/SliderControl.cjs.map +1 -0
- package/dist/control/SliderControl.js +553 -0
- package/dist/control/SliderControl.js.map +1 -0
- package/dist/control/SliderControlDataAttributes.cjs +47 -0
- package/dist/control/SliderControlDataAttributes.cjs.map +1 -0
- package/dist/control/SliderControlDataAttributes.js +41 -0
- package/dist/control/SliderControlDataAttributes.js.map +1 -0
- package/dist/csp-provider/CSPContext.cjs +32 -0
- package/dist/csp-provider/CSPContext.cjs.map +1 -0
- package/dist/csp-provider/CSPContext.js +21 -0
- package/dist/csp-provider/CSPContext.js.map +1 -0
- package/dist/csp-provider/CSPProvider.cjs +46 -0
- package/dist/csp-provider/CSPProvider.cjs.map +1 -0
- package/dist/csp-provider/CSPProvider.js +41 -0
- package/dist/csp-provider/CSPProvider.js.map +1 -0
- package/dist/description/FieldDescription.cjs +5 -5
- package/dist/description/FieldDescription.cjs.map +1 -1
- package/dist/description/FieldDescription.js +1 -1
- package/dist/direction-provider/DirectionProvider.cjs +2 -2
- package/dist/direction-provider/DirectionProvider.cjs.map +1 -1
- package/dist/direction-provider/DirectionProvider.js +1 -1
- package/dist/error/FieldError.cjs +10 -288
- package/dist/error/FieldError.cjs.map +1 -1
- package/dist/error/FieldError.js +4 -246
- package/dist/error/FieldError.js.map +1 -1
- package/dist/form/Form.cjs +5 -4
- package/dist/form/Form.cjs.map +1 -1
- package/dist/form/Form.js +5 -4
- package/dist/form/Form.js.map +1 -1
- package/dist/group/ToolbarGroup.cjs +92 -0
- package/dist/group/ToolbarGroup.cjs.map +1 -0
- package/dist/group/ToolbarGroup.js +87 -0
- package/dist/group/ToolbarGroup.js.map +1 -0
- package/dist/group/ToolbarGroupDataAttributes.cjs +23 -0
- package/dist/group/ToolbarGroupDataAttributes.cjs.map +1 -0
- package/dist/group/ToolbarGroupDataAttributes.js +17 -0
- package/dist/group/ToolbarGroupDataAttributes.js.map +1 -0
- package/dist/header/AccordionHeader.cjs +2 -2
- package/dist/header/AccordionHeader.js +1 -1
- package/dist/image/AvatarImage.cjs +4 -4
- package/dist/image/AvatarImage.cjs.map +1 -1
- package/dist/image/AvatarImage.js +1 -1
- package/dist/index.cjs +80 -10
- package/dist/index.d.cts +2751 -612
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +2751 -612
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -5
- package/dist/index2.cjs +3651 -370
- package/dist/index2.cjs.map +1 -1
- package/dist/index2.js +3365 -270
- package/dist/index2.js.map +1 -1
- package/package.json +8 -4
- package/src/accordion/root/AccordionRoot.vue +2 -1
- package/src/checkbox/index.ts +23 -0
- package/src/checkbox/indicator/CheckboxIndicator.vue +102 -0
- package/src/checkbox/indicator/CheckboxIndicatorDataAttributes.ts +61 -0
- package/src/checkbox/root/CheckboxRoot.vue +632 -0
- package/src/checkbox/root/CheckboxRootContext.ts +22 -0
- package/src/checkbox/root/CheckboxRootDataAttributes.ts +54 -0
- package/src/checkbox/utils/useStateAttributesMapping.ts +30 -0
- package/src/checkbox-group/CheckboxGroup.vue +241 -0
- package/src/checkbox-group/CheckboxGroupContext.ts +39 -0
- package/src/checkbox-group/CheckboxGroupDataAttributes.ts +6 -0
- package/src/checkbox-group/index.ts +11 -0
- package/src/checkbox-group/useCheckboxGroupParent.ts +173 -0
- package/src/collapsible/panel/useCollapsiblePanel.ts +2 -1
- package/src/collapsible/root/useCollapsibleRoot.ts +3 -1
- package/src/composite/composite.ts +2 -0
- package/src/composite/item/CompositeItem.vue +7 -8
- package/src/composite/root/CompositeRoot.vue +12 -1
- package/src/csp-provider/CSPContext.ts +26 -0
- package/src/csp-provider/CSPProvider.vue +40 -0
- package/src/csp-provider/index.ts +5 -0
- package/src/field/item/FieldItem.vue +6 -1
- package/src/field/label/FieldLabel.vue +10 -51
- package/src/field/root/FieldRoot.vue +16 -3
- package/src/floating-ui-vue/types.ts +1 -4
- package/src/floating-ui-vue/utils/element.ts +12 -0
- package/src/floating-ui-vue/utils/shadowDom.ts +44 -0
- package/src/floating-ui-vue/utils.ts +3 -0
- package/src/form/Form.vue +5 -3
- package/src/index.ts +9 -0
- package/src/labelable-provider/LabelableContext.ts +2 -2
- package/src/labelable-provider/LabelableProvider.vue +21 -4
- package/src/labelable-provider/index.ts +2 -0
- package/src/labelable-provider/useAriaLabelledBy.ts +9 -9
- package/src/labelable-provider/useLabel.ts +115 -0
- package/src/labelable-provider/useLabelableId.ts +12 -10
- package/src/separator/Separator.vue +65 -0
- package/src/separator/SeparatorDataAttributes.ts +7 -0
- package/src/separator/index.ts +3 -0
- package/src/slider/control/SliderControl.vue +497 -0
- package/src/slider/control/SliderControlDataAttributes.ts +35 -0
- package/src/slider/index.ts +35 -0
- package/src/slider/indicator/SliderIndicator.vue +144 -0
- package/src/slider/indicator/SliderIndicatorDataAttributes.ts +35 -0
- package/src/slider/label/SliderLabel.vue +75 -0
- package/src/slider/root/SliderRoot.vue +557 -0
- package/src/slider/root/SliderRootContext.ts +126 -0
- package/src/slider/root/SliderRootDataAttributes.ts +35 -0
- package/src/slider/root/stateAttributesMapping.ts +13 -0
- package/src/slider/thumb/SliderThumb.vue +601 -0
- package/src/slider/thumb/SliderThumbDataAttributes.ts +39 -0
- package/src/slider/thumb/prehydrationScript.min.ts +5 -0
- package/src/slider/thumb/prehydrationScript.template.js +69 -0
- package/src/slider/track/SliderTrack.vue +48 -0
- package/src/slider/track/SliderTrackDataAttributes.ts +10 -0
- package/src/slider/utils/asc.ts +3 -0
- package/src/slider/utils/getMidpoint.ts +9 -0
- package/src/slider/utils/getPushedThumbValues.ts +68 -0
- package/src/slider/utils/getSliderValue.ts +25 -0
- package/src/slider/utils/replaceArrayItemAtIndex.ts +15 -0
- package/src/slider/utils/resolveThumbCollision.ts +177 -0
- package/src/slider/utils/roundValueToStep.ts +19 -0
- package/src/slider/utils/test-utils.ts +25 -0
- package/src/slider/utils/validateMinimumDistance.ts +20 -0
- package/src/slider/utils/valueArrayToPercentages.ts +10 -0
- package/src/slider/value/SliderValue.vue +90 -0
- package/src/slider/value/SliderValueDataAttributes.ts +35 -0
- package/src/switch/index.ts +14 -0
- package/src/switch/root/SwitchRoot.vue +448 -0
- package/src/switch/root/SwitchRootContext.ts +22 -0
- package/src/switch/root/SwitchRootDataAttributes.ts +46 -0
- package/src/switch/stateAttributesMapping.ts +23 -0
- package/src/switch/thumb/SwitchThumb.vue +59 -0
- package/src/switch/thumb/SwitchThumbDataAttributes.ts +46 -0
- package/src/toggle/Toggle.vue +211 -0
- package/src/toggle/ToggleDataAttributes.ts +6 -0
- package/src/toggle/index.ts +3 -0
- package/src/toggle-group/ToggleGroup.vue +224 -0
- package/src/toggle-group/ToggleGroupContext.ts +45 -0
- package/src/toggle-group/ToggleGroupDataAttributes.ts +15 -0
- package/src/toggle-group/index.ts +5 -0
- package/src/toolbar/button/ToolbarButton.vue +99 -0
- package/src/toolbar/button/ToolbarButtonDataAttributes.ts +15 -0
- package/src/toolbar/group/ToolbarGroup.vue +70 -0
- package/src/toolbar/group/ToolbarGroupContext.ts +23 -0
- package/src/toolbar/group/ToolbarGroupDataAttributes.ts +11 -0
- package/src/toolbar/index.ts +27 -0
- package/src/toolbar/input/ToolbarInput.vue +114 -0
- package/src/toolbar/input/ToolbarInputDataAttributes.ts +15 -0
- package/src/toolbar/link/ToolbarLink.vue +54 -0
- package/src/toolbar/link/ToolbarLinkDataAttributes.ts +7 -0
- package/src/toolbar/root/ToolbarRoot.vue +144 -0
- package/src/toolbar/root/ToolbarRootContext.ts +29 -0
- package/src/toolbar/root/ToolbarRootDataAttributes.ts +11 -0
- package/src/toolbar/separator/ToolbarSeparator.vue +41 -0
- package/src/toolbar/separator/ToolbarSeparatorDataAttributes.ts +7 -0
- package/src/use-button/useButton.ts +2 -1
- package/src/utils/areArraysEqual.ts +12 -0
- package/src/utils/clamp.ts +7 -0
- package/src/utils/createBaseUIEventDetails.ts +9 -0
- package/src/utils/formatNumber.ts +7 -0
- package/src/utils/owner.ts +5 -0
- package/src/utils/resolveAriaLabelledBy.ts +10 -0
- package/src/utils/useControllableState.ts +78 -14
- package/src/utils/useFocusableWhenDisabled.ts +6 -1
- package/src/utils/useMergedRefs.ts +26 -2
- package/src/utils/useRegisteredLabelId.ts +21 -0
- package/src/utils/valueToPercent.ts +7 -0
- package/src/utils/visuallyHidden.ts +24 -0
- package/dist/direction-provider/DirectionContext.cjs +0 -26
- package/dist/direction-provider/DirectionContext.cjs.map +0 -1
- package/dist/direction-provider/DirectionContext.js +0 -15
- package/dist/direction-provider/DirectionContext.js.map +0 -1
|
@@ -0,0 +1,557 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { ShallowRef } from 'vue'
|
|
3
|
+
import type { CompositeMetadata } from '../../composite/list/CompositeList.vue'
|
|
4
|
+
import type { FieldRootState } from '../../field/root/FieldRoot.vue'
|
|
5
|
+
import type { BaseUIChangeEventDetails, BaseUIGenericEventDetails } from '../../utils/createBaseUIEventDetails'
|
|
6
|
+
import type { BaseUIComponentProps, Orientation } from '../../utils/types'
|
|
7
|
+
import type { ThumbMetadata } from '../thumb/SliderThumb.vue'
|
|
8
|
+
import { computed, provide, ref, shallowRef, useAttrs, watch } from 'vue'
|
|
9
|
+
import CompositeList from '../../composite/list/CompositeList.vue'
|
|
10
|
+
import { useFieldRootContext } from '../../field/root/FieldRootContext'
|
|
11
|
+
import { useField } from '../../field/useField'
|
|
12
|
+
import { activeElement, contains } from '../../floating-ui-vue/utils'
|
|
13
|
+
import { useFormContext } from '../../form/FormContext'
|
|
14
|
+
import { useLabelableContext } from '../../labelable-provider/LabelableContext'
|
|
15
|
+
import { mergeProps } from '../../merge-props/mergeProps'
|
|
16
|
+
import { areArraysEqual } from '../../utils/areArraysEqual'
|
|
17
|
+
import { clamp } from '../../utils/clamp'
|
|
18
|
+
import { createChangeEventDetails, createGenericEventDetails } from '../../utils/createBaseUIEventDetails'
|
|
19
|
+
import { ownerDocument } from '../../utils/owner'
|
|
20
|
+
import { REASONS } from '../../utils/reasons'
|
|
21
|
+
import { getDefaultLabelId, resolveAriaLabelledBy } from '../../utils/resolveAriaLabelledBy'
|
|
22
|
+
import { useBaseUiId } from '../../utils/useBaseUiId'
|
|
23
|
+
import { useControllableState } from '../../utils/useControllableState'
|
|
24
|
+
import { useMergedRefs } from '../../utils/useMergedRefs'
|
|
25
|
+
import { useRenderElement } from '../../utils/useRenderElement'
|
|
26
|
+
import { warn } from '../../utils/warn'
|
|
27
|
+
import { asc } from '../utils/asc'
|
|
28
|
+
import { getSliderValue } from '../utils/getSliderValue'
|
|
29
|
+
import { validateMinimumDistance } from '../utils/validateMinimumDistance'
|
|
30
|
+
import { sliderRootContextKey } from './SliderRootContext'
|
|
31
|
+
import { sliderStateAttributesMapping } from './stateAttributesMapping'
|
|
32
|
+
|
|
33
|
+
export type SliderRootChangeEventReason
|
|
34
|
+
= | typeof REASONS.inputChange
|
|
35
|
+
| typeof REASONS.trackPress
|
|
36
|
+
| typeof REASONS.drag
|
|
37
|
+
| typeof REASONS.keyboard
|
|
38
|
+
| typeof REASONS.none
|
|
39
|
+
|
|
40
|
+
export type SliderRootCommitEventReason = SliderRootChangeEventReason
|
|
41
|
+
|
|
42
|
+
export type SliderRootChangeEventDetails = BaseUIChangeEventDetails<
|
|
43
|
+
SliderRootChangeEventReason,
|
|
44
|
+
{
|
|
45
|
+
/**
|
|
46
|
+
* The index of the active thumb at the time of the change.
|
|
47
|
+
*/
|
|
48
|
+
activeThumbIndex: number
|
|
49
|
+
}
|
|
50
|
+
>
|
|
51
|
+
export type SliderRootCommitEventDetails = BaseUIGenericEventDetails<SliderRootCommitEventReason>
|
|
52
|
+
|
|
53
|
+
export interface SliderRootState extends FieldRootState {
|
|
54
|
+
/**
|
|
55
|
+
* The index of the active thumb.
|
|
56
|
+
*/
|
|
57
|
+
activeThumbIndex: number
|
|
58
|
+
/**
|
|
59
|
+
* Whether the component should ignore user interaction.
|
|
60
|
+
*/
|
|
61
|
+
disabled: boolean
|
|
62
|
+
/**
|
|
63
|
+
* Whether the thumb is currently being dragged.
|
|
64
|
+
*/
|
|
65
|
+
dragging: boolean
|
|
66
|
+
/**
|
|
67
|
+
* The maximum value.
|
|
68
|
+
*/
|
|
69
|
+
max: number
|
|
70
|
+
/**
|
|
71
|
+
* The minimum value.
|
|
72
|
+
*/
|
|
73
|
+
min: number
|
|
74
|
+
/**
|
|
75
|
+
* The minimum steps between values in a range slider.
|
|
76
|
+
* @default 0
|
|
77
|
+
*/
|
|
78
|
+
minStepsBetweenValues: number
|
|
79
|
+
/**
|
|
80
|
+
* The component orientation.
|
|
81
|
+
*/
|
|
82
|
+
orientation: Orientation
|
|
83
|
+
/**
|
|
84
|
+
* The step increment of the slider when incrementing or decrementing. It will snap
|
|
85
|
+
* to multiples of this value. Decimal values are supported.
|
|
86
|
+
* @default 1
|
|
87
|
+
*/
|
|
88
|
+
step: number
|
|
89
|
+
/**
|
|
90
|
+
* The raw number value of the slider.
|
|
91
|
+
*/
|
|
92
|
+
values: readonly number[]
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export interface SliderRootProps<Value extends number | readonly number[] = number | readonly number[]>
|
|
96
|
+
extends BaseUIComponentProps<SliderRootState> {
|
|
97
|
+
/**
|
|
98
|
+
* The uncontrolled value of the slider when it's initially rendered.
|
|
99
|
+
*
|
|
100
|
+
* To render a controlled slider, use the `value` prop instead.
|
|
101
|
+
*/
|
|
102
|
+
defaultValue?: Value
|
|
103
|
+
/**
|
|
104
|
+
* Whether the slider should ignore user interaction.
|
|
105
|
+
* @default false
|
|
106
|
+
*/
|
|
107
|
+
disabled?: boolean
|
|
108
|
+
/**
|
|
109
|
+
* Options to format the input value.
|
|
110
|
+
*/
|
|
111
|
+
format?: Intl.NumberFormatOptions
|
|
112
|
+
/**
|
|
113
|
+
* The locale used by `Intl.NumberFormat` when formatting the value.
|
|
114
|
+
* Defaults to the user's runtime locale.
|
|
115
|
+
*/
|
|
116
|
+
locale?: Intl.LocalesArgument
|
|
117
|
+
/**
|
|
118
|
+
* The maximum allowed value of the slider.
|
|
119
|
+
* Should not be equal to min.
|
|
120
|
+
* @default 100
|
|
121
|
+
*/
|
|
122
|
+
max?: number
|
|
123
|
+
/**
|
|
124
|
+
* The minimum allowed value of the slider.
|
|
125
|
+
* Should not be equal to min.
|
|
126
|
+
* @default 0
|
|
127
|
+
*/
|
|
128
|
+
min?: number
|
|
129
|
+
/**
|
|
130
|
+
* The minimum steps between values in a range slider.
|
|
131
|
+
* @default 0
|
|
132
|
+
*/
|
|
133
|
+
minStepsBetweenValues?: number
|
|
134
|
+
/**
|
|
135
|
+
* Identifies the field when a form is submitted.
|
|
136
|
+
*/
|
|
137
|
+
name?: string
|
|
138
|
+
/**
|
|
139
|
+
* Identifies the form that owns the slider inputs.
|
|
140
|
+
* Useful when the slider is rendered outside the form.
|
|
141
|
+
*/
|
|
142
|
+
form?: string
|
|
143
|
+
/**
|
|
144
|
+
* The component orientation.
|
|
145
|
+
* @default 'horizontal'
|
|
146
|
+
*/
|
|
147
|
+
orientation?: Orientation
|
|
148
|
+
/**
|
|
149
|
+
* The granularity with which the slider can step through values. (A "discrete" slider.)
|
|
150
|
+
* The `min` prop serves as the origin for the valid values.
|
|
151
|
+
* We recommend (max - min) to be evenly divisible by the step.
|
|
152
|
+
* @default 1
|
|
153
|
+
*/
|
|
154
|
+
step?: number
|
|
155
|
+
/**
|
|
156
|
+
* The granularity with which the slider can step through values when using Page Up/Page Down or Shift + Arrow Up/Arrow Down.
|
|
157
|
+
* @default 10
|
|
158
|
+
*/
|
|
159
|
+
largeStep?: number
|
|
160
|
+
/**
|
|
161
|
+
* How the thumb(s) are aligned relative to `Slider.Control` when the value is at `min` or `max`:
|
|
162
|
+
* - `center`: The center of the thumb is aligned with the control edge
|
|
163
|
+
* - `edge`: The thumb is inset within the control such that its edge is aligned with the control edge
|
|
164
|
+
* - `edge-client-only`: Same as `edge` but renders after React hydration on the client, reducing bundle size in return
|
|
165
|
+
* @default 'center'
|
|
166
|
+
*/
|
|
167
|
+
thumbAlignment?: 'center' | 'edge' | 'edge-client-only'
|
|
168
|
+
/**
|
|
169
|
+
* Controls how thumbs behave when they collide during pointer interactions.
|
|
170
|
+
*
|
|
171
|
+
* - `'push'` (default): Thumbs push each other without restoring their previous positions when dragged back.
|
|
172
|
+
* - `'swap'`: Thumbs swap places when dragged past each other.
|
|
173
|
+
* - `'none'`: Thumbs cannot move past each other; excess movement is ignored.
|
|
174
|
+
*
|
|
175
|
+
* @default 'push'
|
|
176
|
+
*/
|
|
177
|
+
thumbCollisionBehavior?: 'push' | 'swap' | 'none'
|
|
178
|
+
/**
|
|
179
|
+
* The value of the slider.
|
|
180
|
+
* For ranged sliders, provide an array with two values.
|
|
181
|
+
*/
|
|
182
|
+
value?: Value
|
|
183
|
+
id?: string
|
|
184
|
+
ariaLabelledby?: string
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
export type IntlNumberFormatOptionsRef = Readonly<{ value: Intl.NumberFormatOptions | undefined }>
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Groups all parts of the slider.
|
|
191
|
+
* Renders a `<div>` element.
|
|
192
|
+
*
|
|
193
|
+
* Documentation: [Base UI Vue Slider](https://baseui-vue.com/docs/components/slider)
|
|
194
|
+
*/
|
|
195
|
+
defineOptions({
|
|
196
|
+
name: 'SliderRoot',
|
|
197
|
+
inheritAttrs: false,
|
|
198
|
+
})
|
|
199
|
+
|
|
200
|
+
const props = withDefaults(defineProps<SliderRootProps>(), {
|
|
201
|
+
as: 'div',
|
|
202
|
+
disabled: false,
|
|
203
|
+
largeStep: 10,
|
|
204
|
+
max: 100,
|
|
205
|
+
min: 0,
|
|
206
|
+
minStepsBetweenValues: 0,
|
|
207
|
+
orientation: 'horizontal',
|
|
208
|
+
step: 1,
|
|
209
|
+
thumbAlignment: 'center',
|
|
210
|
+
thumbCollisionBehavior: 'push',
|
|
211
|
+
})
|
|
212
|
+
|
|
213
|
+
const emit = defineEmits<{
|
|
214
|
+
/**
|
|
215
|
+
* Callback function that is fired when the slider's value changed.
|
|
216
|
+
* You can pull out the new value by accessing `event.target.value` (any).
|
|
217
|
+
*
|
|
218
|
+
* The `eventDetails.reason` indicates what triggered the change:
|
|
219
|
+
*
|
|
220
|
+
* - `'input-change'` when the hidden range input emits a change event (for example, via form integration)
|
|
221
|
+
* - `'track-press'` when the control track is pressed
|
|
222
|
+
* - `'drag'` while dragging a thumb
|
|
223
|
+
* - `'keyboard'` for keyboard input
|
|
224
|
+
* - `'none'` when the change is triggered without a specific interaction
|
|
225
|
+
*/
|
|
226
|
+
valueChange: [value: number | readonly number[], details: SliderRootChangeEventDetails]
|
|
227
|
+
/**
|
|
228
|
+
* Callback function that is fired when the `pointerup` is triggered.
|
|
229
|
+
* **Warning**: This is a generic event not a change event.
|
|
230
|
+
*
|
|
231
|
+
* The `eventDetails.reason` indicates what triggered the commit:
|
|
232
|
+
*
|
|
233
|
+
* - `'drag'` while dragging a thumb
|
|
234
|
+
* - `'track-press'` when the control track is pressed
|
|
235
|
+
* - `'keyboard'` for keyboard input
|
|
236
|
+
* - `'input-change'` when the hidden range input emits a change event (for example, via form integration)
|
|
237
|
+
* - `'none'` when the commit occurs without a specific interaction
|
|
238
|
+
*/
|
|
239
|
+
valueCommitted: [value: number | readonly number[], details: SliderRootCommitEventDetails]
|
|
240
|
+
}>()
|
|
241
|
+
|
|
242
|
+
const attrs = useAttrs()
|
|
243
|
+
const attrsObject = attrs as Record<string, unknown>
|
|
244
|
+
const explicitAriaLabelledBy = computed(() =>
|
|
245
|
+
props.ariaLabelledby ?? attrs['aria-labelledby'] as string | undefined,
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
const id = useBaseUiId(props.id)
|
|
249
|
+
const idRef = computed(() => id)
|
|
250
|
+
const defaultLabelId = computed(() => getDefaultLabelId(id))
|
|
251
|
+
|
|
252
|
+
const { clearErrors } = useFormContext()
|
|
253
|
+
const {
|
|
254
|
+
state: fieldState,
|
|
255
|
+
disabled: fieldDisabled,
|
|
256
|
+
name: fieldName,
|
|
257
|
+
setTouched,
|
|
258
|
+
setDirty,
|
|
259
|
+
validation,
|
|
260
|
+
validityData,
|
|
261
|
+
shouldValidateOnChange,
|
|
262
|
+
} = useFieldRootContext()
|
|
263
|
+
const { labelId: fieldLabelId } = useLabelableContext()
|
|
264
|
+
|
|
265
|
+
const localLabelId = ref<string | undefined>(undefined)
|
|
266
|
+
|
|
267
|
+
const ariaLabelledBy = computed(() =>
|
|
268
|
+
explicitAriaLabelledBy.value ?? resolveAriaLabelledBy(fieldLabelId.value, localLabelId.value),
|
|
269
|
+
)
|
|
270
|
+
const disabled = computed(() => fieldDisabled.value || props.disabled)
|
|
271
|
+
const name = computed(() => fieldName.value ?? props.name)
|
|
272
|
+
|
|
273
|
+
const controllableValue = useControllableState<number | readonly number[]>({
|
|
274
|
+
controlled: () => props.value,
|
|
275
|
+
default: () => props.defaultValue ?? props.min,
|
|
276
|
+
name: 'Slider',
|
|
277
|
+
state: 'value',
|
|
278
|
+
})
|
|
279
|
+
const valueUnwrapped = controllableValue.value
|
|
280
|
+
const setValueUnwrapped = controllableValue.setValue
|
|
281
|
+
|
|
282
|
+
const sliderRef = ref<HTMLElement | null>(null)
|
|
283
|
+
const controlRef = ref<HTMLElement | null>(null)
|
|
284
|
+
const thumbRefs = ref<(HTMLElement | null)[]>([])
|
|
285
|
+
const pressedInputRef = ref<HTMLInputElement | null>(null)
|
|
286
|
+
const pressedThumbCenterOffsetRef = ref<number | null>(null)
|
|
287
|
+
const pressedThumbIndexRef = ref(-1)
|
|
288
|
+
const pressedValuesRef = ref<readonly number[] | null>(null)
|
|
289
|
+
const lastChangedValueRef = ref<number | readonly number[] | null>(null)
|
|
290
|
+
const lastChangeReasonRef = ref<SliderRootChangeEventReason>(REASONS.none)
|
|
291
|
+
const formatOptionsRef = computed(() => props.format)
|
|
292
|
+
|
|
293
|
+
const active = ref(-1)
|
|
294
|
+
const lastUsedThumbIndex = ref(-1)
|
|
295
|
+
const dragging = ref(false)
|
|
296
|
+
const thumbMap = shallowRef<Map<Element, CompositeMetadata<ThumbMetadata> | null>>(new Map())
|
|
297
|
+
const indicatorPosition = ref<(number | undefined)[]>([undefined, undefined])
|
|
298
|
+
|
|
299
|
+
function setActive(value: number) {
|
|
300
|
+
active.value = value
|
|
301
|
+
if (value !== -1) {
|
|
302
|
+
lastUsedThumbIndex.value = value
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
function registerFieldControlRef(element: HTMLElement | null) {
|
|
307
|
+
if (element) {
|
|
308
|
+
controlRef.value = element
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
function setThumbMap(nextMap: Map<Element, CompositeMetadata<ThumbMetadata> | null>) {
|
|
313
|
+
thumbMap.value = nextMap
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
const compositeListProps = {
|
|
317
|
+
elementsRef: thumbRefs,
|
|
318
|
+
onMapChange: setThumbMap,
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
const range = computed(() => Array.isArray(valueUnwrapped.value))
|
|
322
|
+
const values = computed<readonly number[]>(() => {
|
|
323
|
+
if (!range.value) {
|
|
324
|
+
return [clamp(valueUnwrapped.value as number, props.min, props.max)]
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
return [...(valueUnwrapped.value as readonly number[])].sort(asc)
|
|
328
|
+
})
|
|
329
|
+
|
|
330
|
+
useField({
|
|
331
|
+
id: idRef,
|
|
332
|
+
commit: (value: unknown) => validation.commit(value),
|
|
333
|
+
value: computed(() => valueUnwrapped.value),
|
|
334
|
+
controlRef,
|
|
335
|
+
name,
|
|
336
|
+
getValue: () => valueUnwrapped.value,
|
|
337
|
+
})
|
|
338
|
+
|
|
339
|
+
watch(
|
|
340
|
+
() => valueUnwrapped.value,
|
|
341
|
+
() => {
|
|
342
|
+
clearErrors(name.value)
|
|
343
|
+
|
|
344
|
+
if (shouldValidateOnChange()) {
|
|
345
|
+
validation.commit(valueUnwrapped.value)
|
|
346
|
+
}
|
|
347
|
+
else {
|
|
348
|
+
validation.commit(valueUnwrapped.value, true)
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
const initialValue = validityData.value.initialValue as number | readonly number[] | undefined
|
|
352
|
+
let isDirty: boolean
|
|
353
|
+
if (Array.isArray(valueUnwrapped.value) && Array.isArray(initialValue)) {
|
|
354
|
+
isDirty = !areArraysEqual(valueUnwrapped.value, initialValue)
|
|
355
|
+
}
|
|
356
|
+
else {
|
|
357
|
+
isDirty = valueUnwrapped.value !== initialValue
|
|
358
|
+
}
|
|
359
|
+
setDirty(isDirty)
|
|
360
|
+
},
|
|
361
|
+
)
|
|
362
|
+
|
|
363
|
+
function areValuesEqual(
|
|
364
|
+
newValue: number | readonly number[],
|
|
365
|
+
oldValue: number | readonly number[],
|
|
366
|
+
) {
|
|
367
|
+
if (typeof newValue === 'number' && typeof oldValue === 'number') {
|
|
368
|
+
return newValue === oldValue
|
|
369
|
+
}
|
|
370
|
+
if (Array.isArray(newValue) && Array.isArray(oldValue)) {
|
|
371
|
+
return areArraysEqual(newValue, oldValue)
|
|
372
|
+
}
|
|
373
|
+
return false
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
function setValue(
|
|
377
|
+
newValue: number | number[],
|
|
378
|
+
details?: SliderRootChangeEventDetails,
|
|
379
|
+
) {
|
|
380
|
+
if (Number.isNaN(newValue) || areValuesEqual(newValue, valueUnwrapped.value)) {
|
|
381
|
+
return
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
const changeDetails
|
|
385
|
+
= details
|
|
386
|
+
?? createChangeEventDetails(REASONS.none, undefined, undefined, { activeThumbIndex: -1 })
|
|
387
|
+
|
|
388
|
+
lastChangeReasonRef.value = changeDetails.reason
|
|
389
|
+
|
|
390
|
+
const nativeEvent = changeDetails.event
|
|
391
|
+
const EventConstructor = (nativeEvent.constructor as typeof Event | undefined) ?? Event
|
|
392
|
+
const clonedEvent = new EventConstructor(nativeEvent.type, nativeEvent as EventInit)
|
|
393
|
+
Object.defineProperty(clonedEvent, 'target', {
|
|
394
|
+
writable: true,
|
|
395
|
+
value: { value: newValue, name: name.value },
|
|
396
|
+
})
|
|
397
|
+
|
|
398
|
+
changeDetails.event = clonedEvent as typeof changeDetails.event
|
|
399
|
+
lastChangedValueRef.value = newValue
|
|
400
|
+
emit('valueChange', newValue, changeDetails)
|
|
401
|
+
|
|
402
|
+
if (changeDetails.isCanceled) {
|
|
403
|
+
return
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
setValueUnwrapped(newValue)
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
function getSliderChangeEventReason(event: KeyboardEvent | Event): SliderRootChangeEventReason {
|
|
410
|
+
return event instanceof KeyboardEvent ? REASONS.keyboard : REASONS.inputChange
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
function handleInputChange(valueInput: number, index: number, event: KeyboardEvent | Event) {
|
|
414
|
+
const newValue = getSliderValue(
|
|
415
|
+
valueInput,
|
|
416
|
+
index,
|
|
417
|
+
props.min,
|
|
418
|
+
props.max,
|
|
419
|
+
range.value,
|
|
420
|
+
values.value,
|
|
421
|
+
)
|
|
422
|
+
|
|
423
|
+
if (validateMinimumDistance(newValue, props.step, props.minStepsBetweenValues)) {
|
|
424
|
+
const reason = getSliderChangeEventReason(event)
|
|
425
|
+
setValue(
|
|
426
|
+
newValue,
|
|
427
|
+
createChangeEventDetails(reason, event, undefined, {
|
|
428
|
+
activeThumbIndex: index,
|
|
429
|
+
}),
|
|
430
|
+
)
|
|
431
|
+
setTouched(true)
|
|
432
|
+
|
|
433
|
+
const nextValue = lastChangedValueRef.value ?? newValue
|
|
434
|
+
emit('valueCommitted', nextValue, createGenericEventDetails(reason, event))
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
if (process.env.NODE_ENV !== 'production' && props.min >= props.max) {
|
|
439
|
+
warn('Slider `max` must be greater than `min`.')
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
watch(
|
|
443
|
+
() => disabled.value,
|
|
444
|
+
(nextDisabled) => {
|
|
445
|
+
const activeEl = sliderRef.value ? activeElement(ownerDocument(sliderRef.value)!) : null
|
|
446
|
+
if (nextDisabled && activeEl instanceof HTMLElement && contains(sliderRef.value, activeEl)) {
|
|
447
|
+
activeEl.blur()
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
if (nextDisabled && active.value !== -1) {
|
|
451
|
+
setActive(-1)
|
|
452
|
+
}
|
|
453
|
+
},
|
|
454
|
+
)
|
|
455
|
+
|
|
456
|
+
const state = computed<SliderRootState>(() => ({
|
|
457
|
+
...fieldState.value,
|
|
458
|
+
activeThumbIndex: active.value,
|
|
459
|
+
disabled: disabled.value,
|
|
460
|
+
dragging: dragging.value,
|
|
461
|
+
orientation: props.orientation,
|
|
462
|
+
max: props.max,
|
|
463
|
+
min: props.min,
|
|
464
|
+
minStepsBetweenValues: props.minStepsBetweenValues,
|
|
465
|
+
step: props.step,
|
|
466
|
+
values: values.value,
|
|
467
|
+
}))
|
|
468
|
+
|
|
469
|
+
provide(sliderRootContextKey, {
|
|
470
|
+
active,
|
|
471
|
+
lastUsedThumbIndex,
|
|
472
|
+
controlRef,
|
|
473
|
+
dragging,
|
|
474
|
+
disabled,
|
|
475
|
+
validation,
|
|
476
|
+
formatOptionsRef,
|
|
477
|
+
handleInputChange,
|
|
478
|
+
indicatorPosition,
|
|
479
|
+
inset: computed(() => props.thumbAlignment !== 'center'),
|
|
480
|
+
labelId: computed(() => ariaLabelledBy.value),
|
|
481
|
+
rootLabelId: defaultLabelId,
|
|
482
|
+
largeStep: computed(() => props.largeStep),
|
|
483
|
+
lastChangedValueRef,
|
|
484
|
+
lastChangeReasonRef,
|
|
485
|
+
locale: computed(() => props.locale),
|
|
486
|
+
max: computed(() => props.max),
|
|
487
|
+
min: computed(() => props.min),
|
|
488
|
+
minStepsBetweenValues: computed(() => props.minStepsBetweenValues),
|
|
489
|
+
form: computed(() => props.form),
|
|
490
|
+
name,
|
|
491
|
+
onValueCommitted(value, details) {
|
|
492
|
+
emit('valueCommitted', value, details)
|
|
493
|
+
},
|
|
494
|
+
orientation: computed(() => props.orientation),
|
|
495
|
+
pressedInputRef,
|
|
496
|
+
pressedThumbCenterOffsetRef,
|
|
497
|
+
pressedThumbIndexRef,
|
|
498
|
+
pressedValuesRef,
|
|
499
|
+
registerFieldControlRef,
|
|
500
|
+
renderBeforeHydration: computed(() => props.thumbAlignment === 'edge'),
|
|
501
|
+
setActive,
|
|
502
|
+
setDragging(value: boolean) {
|
|
503
|
+
dragging.value = value
|
|
504
|
+
},
|
|
505
|
+
setIndicatorPosition(updater) {
|
|
506
|
+
indicatorPosition.value = updater(indicatorPosition.value)
|
|
507
|
+
},
|
|
508
|
+
setLabelId(value) {
|
|
509
|
+
localLabelId.value = value
|
|
510
|
+
},
|
|
511
|
+
setValue,
|
|
512
|
+
state,
|
|
513
|
+
step: computed(() => props.step),
|
|
514
|
+
thumbCollisionBehavior: computed(() => props.thumbCollisionBehavior),
|
|
515
|
+
thumbMap: thumbMap as ShallowRef<Map<Element, CompositeMetadata<ThumbMetadata> | null>>,
|
|
516
|
+
thumbRefs,
|
|
517
|
+
values,
|
|
518
|
+
})
|
|
519
|
+
|
|
520
|
+
const rootProps = computed(() => mergeProps(
|
|
521
|
+
attrsObject,
|
|
522
|
+
validation.getValidationProps(),
|
|
523
|
+
{
|
|
524
|
+
'aria-labelledby': ariaLabelledBy.value,
|
|
525
|
+
'id': id,
|
|
526
|
+
'role': 'group',
|
|
527
|
+
},
|
|
528
|
+
))
|
|
529
|
+
|
|
530
|
+
const {
|
|
531
|
+
tag,
|
|
532
|
+
mergedProps,
|
|
533
|
+
renderless,
|
|
534
|
+
ref: renderRef,
|
|
535
|
+
} = useRenderElement({
|
|
536
|
+
componentProps: props,
|
|
537
|
+
state,
|
|
538
|
+
ref: useMergedRefs(sliderRef),
|
|
539
|
+
props: rootProps,
|
|
540
|
+
defaultTagName: 'div',
|
|
541
|
+
stateAttributesMapping: sliderStateAttributesMapping,
|
|
542
|
+
})
|
|
543
|
+
</script>
|
|
544
|
+
|
|
545
|
+
<template>
|
|
546
|
+
<CompositeList v-bind="compositeListProps">
|
|
547
|
+
<slot v-if="renderless" :ref="renderRef" :props="mergedProps" :state="state" />
|
|
548
|
+
<component
|
|
549
|
+
:is="tag"
|
|
550
|
+
v-else
|
|
551
|
+
:ref="renderRef"
|
|
552
|
+
v-bind="mergedProps"
|
|
553
|
+
>
|
|
554
|
+
<slot />
|
|
555
|
+
</component>
|
|
556
|
+
</CompositeList>
|
|
557
|
+
</template>
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import type { InjectionKey, Ref, ShallowRef } from 'vue'
|
|
2
|
+
import type { CompositeMetadata } from '../../composite/list/CompositeList.vue'
|
|
3
|
+
import type { UseFieldValidationReturnValue } from '../../field/root/useFieldValidation'
|
|
4
|
+
import type { BaseUIChangeEventDetails, BaseUIGenericEventDetails } from '../../utils/createBaseUIEventDetails'
|
|
5
|
+
import type { REASONS } from '../../utils/reasons'
|
|
6
|
+
import type { Orientation } from '../../utils/types'
|
|
7
|
+
import type { ThumbMetadata } from '../thumb/SliderThumb.vue'
|
|
8
|
+
import type { IntlNumberFormatOptionsRef, SliderRootState } from './SliderRoot.vue'
|
|
9
|
+
import { inject } from 'vue'
|
|
10
|
+
|
|
11
|
+
export interface SliderRootContext {
|
|
12
|
+
/**
|
|
13
|
+
* The index of the active thumb.
|
|
14
|
+
*/
|
|
15
|
+
active: Ref<number>
|
|
16
|
+
/**
|
|
17
|
+
* The index of the most recently interacted thumb.
|
|
18
|
+
*/
|
|
19
|
+
lastUsedThumbIndex: Ref<number>
|
|
20
|
+
controlRef: Ref<HTMLElement | null>
|
|
21
|
+
dragging: Ref<boolean>
|
|
22
|
+
disabled: Ref<boolean>
|
|
23
|
+
validation: UseFieldValidationReturnValue
|
|
24
|
+
formatOptionsRef: IntlNumberFormatOptionsRef
|
|
25
|
+
handleInputChange: (
|
|
26
|
+
valueInput: number,
|
|
27
|
+
index: number,
|
|
28
|
+
event: KeyboardEvent | Event,
|
|
29
|
+
) => void
|
|
30
|
+
indicatorPosition: Ref<(number | undefined)[]>
|
|
31
|
+
inset: Ref<boolean>
|
|
32
|
+
labelId: Ref<string | undefined>
|
|
33
|
+
rootLabelId: Ref<string | undefined>
|
|
34
|
+
/**
|
|
35
|
+
* The large step value of the slider when incrementing or decrementing while the shift key is held,
|
|
36
|
+
* or when using Page-Up or Page-Down keys. Snaps to multiples of this value.
|
|
37
|
+
* @default 10
|
|
38
|
+
*/
|
|
39
|
+
largeStep: Ref<number>
|
|
40
|
+
lastChangedValueRef: Ref<number | readonly number[] | null>
|
|
41
|
+
lastChangeReasonRef: Ref<SliderRootChangeReason>
|
|
42
|
+
/**
|
|
43
|
+
* The locale used by `Intl.NumberFormat` when formatting the value.
|
|
44
|
+
* Defaults to the user's runtime locale.
|
|
45
|
+
*/
|
|
46
|
+
locale: Ref<Intl.LocalesArgument | undefined>
|
|
47
|
+
/**
|
|
48
|
+
* The maximum allowed value of the slider.
|
|
49
|
+
*/
|
|
50
|
+
max: Ref<number>
|
|
51
|
+
/**
|
|
52
|
+
* The minimum allowed value of the slider.
|
|
53
|
+
*/
|
|
54
|
+
min: Ref<number>
|
|
55
|
+
/**
|
|
56
|
+
* The minimum steps between values in a range slider.
|
|
57
|
+
*/
|
|
58
|
+
minStepsBetweenValues: Ref<number>
|
|
59
|
+
form: Ref<string | undefined>
|
|
60
|
+
name: Ref<string | undefined>
|
|
61
|
+
/**
|
|
62
|
+
* Function to be called when drag ends and the pointer is released.
|
|
63
|
+
*/
|
|
64
|
+
onValueCommitted: (
|
|
65
|
+
value: number | readonly number[],
|
|
66
|
+
details: BaseUIGenericEventDetails<SliderRootChangeReason>,
|
|
67
|
+
) => void
|
|
68
|
+
/**
|
|
69
|
+
* The component orientation.
|
|
70
|
+
* @default 'horizontal'
|
|
71
|
+
*/
|
|
72
|
+
orientation: Ref<Orientation>
|
|
73
|
+
pressedInputRef: Ref<HTMLInputElement | null>
|
|
74
|
+
pressedThumbCenterOffsetRef: Ref<number | null>
|
|
75
|
+
pressedThumbIndexRef: Ref<number>
|
|
76
|
+
pressedValuesRef: Ref<readonly number[] | null>
|
|
77
|
+
registerFieldControlRef: (element: HTMLElement | null) => void
|
|
78
|
+
renderBeforeHydration: Ref<boolean>
|
|
79
|
+
setActive: (value: number) => void
|
|
80
|
+
setDragging: (value: boolean) => void
|
|
81
|
+
setIndicatorPosition: (updater: (prev: (number | undefined)[]) => (number | undefined)[]) => void
|
|
82
|
+
setLabelId: (value: string | undefined) => void
|
|
83
|
+
/**
|
|
84
|
+
* Callback fired when dragging and invokes onValueChange.
|
|
85
|
+
*/
|
|
86
|
+
setValue: (
|
|
87
|
+
value: number | number[],
|
|
88
|
+
details?: BaseUIChangeEventDetails<SliderRootChangeReason, { activeThumbIndex: number }>,
|
|
89
|
+
) => void
|
|
90
|
+
state: Ref<SliderRootState>
|
|
91
|
+
/**
|
|
92
|
+
* The step increment of the slider when incrementing or decrementing. It will snap
|
|
93
|
+
* to multiples of this value. Decimal values are supported.
|
|
94
|
+
* @default 1
|
|
95
|
+
*/
|
|
96
|
+
step: Ref<number>
|
|
97
|
+
thumbCollisionBehavior: Ref<'push' | 'swap' | 'none'>
|
|
98
|
+
thumbMap: ShallowRef<Map<Element, CompositeMetadata<ThumbMetadata> | null>>
|
|
99
|
+
thumbRefs: Ref<(HTMLElement | null)[]>
|
|
100
|
+
/**
|
|
101
|
+
* The value(s) of the slider
|
|
102
|
+
*/
|
|
103
|
+
values: Ref<readonly number[]>
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export type SliderRootChangeReason
|
|
107
|
+
= | typeof REASONS.inputChange
|
|
108
|
+
| typeof REASONS.trackPress
|
|
109
|
+
| typeof REASONS.drag
|
|
110
|
+
| typeof REASONS.keyboard
|
|
111
|
+
| typeof REASONS.none
|
|
112
|
+
|
|
113
|
+
export const sliderRootContextKey: InjectionKey<SliderRootContext> = Symbol('SliderRootContext')
|
|
114
|
+
|
|
115
|
+
export function useSliderRootContext(optional: true): SliderRootContext | undefined
|
|
116
|
+
export function useSliderRootContext(optional?: false): SliderRootContext
|
|
117
|
+
export function useSliderRootContext(optional = false) {
|
|
118
|
+
const context = inject(sliderRootContextKey, undefined)
|
|
119
|
+
if (!context && !optional) {
|
|
120
|
+
throw new Error(
|
|
121
|
+
'Base UI Vue: SliderRootContext is missing. Slider parts must be placed within <SliderRoot>.',
|
|
122
|
+
)
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return context
|
|
126
|
+
}
|