base-ui-vue 0.2.0 → 0.3.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/dist/content/ScrollAreaContent.cjs +168 -0
- package/dist/content/ScrollAreaContent.cjs.map +1 -0
- package/dist/content/ScrollAreaContent.js +133 -0
- package/dist/content/ScrollAreaContent.js.map +1 -0
- package/dist/corner/ScrollAreaCorner.cjs +77 -0
- package/dist/corner/ScrollAreaCorner.cjs.map +1 -0
- package/dist/corner/ScrollAreaCorner.js +72 -0
- package/dist/corner/ScrollAreaCorner.js.map +1 -0
- package/dist/index.cjs +33 -0
- package/dist/index.d.cts +1067 -352
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +1067 -352
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/index2.cjs +3565 -1373
- package/dist/index2.cjs.map +1 -1
- package/dist/index2.js +3228 -1204
- package/dist/index2.js.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +4 -0
- package/src/input/Input.vue +37 -0
- package/src/input/InputDataAttributes.ts +30 -0
- package/src/input/index.ts +4 -0
- package/src/meter/index.ts +16 -0
- package/src/meter/indicator/MeterIndicator.vue +65 -0
- package/src/meter/label/MeterLabel.vue +63 -0
- package/src/meter/root/MeterRoot.vue +131 -0
- package/src/meter/root/MeterRootContext.ts +41 -0
- package/src/meter/track/MeterTrack.vue +46 -0
- package/src/meter/value/MeterValue.vue +85 -0
- package/src/progress/index.ts +23 -0
- package/src/progress/indicator/ProgressIndicator.vue +74 -0
- package/src/progress/label/ProgressLabel.vue +63 -0
- package/src/progress/root/ProgressRoot.vue +160 -0
- package/src/progress/root/ProgressRootContext.ts +51 -0
- package/src/progress/root/ProgressRootDataAttributes.ts +14 -0
- package/src/progress/root/stateAttributesMapping.ts +18 -0
- package/src/progress/track/ProgressTrack.vue +48 -0
- package/src/progress/value/ProgressValue.vue +92 -0
- package/src/scroll-area/constants.ts +2 -0
- package/src/scroll-area/content/ScrollAreaContent.vue +87 -0
- package/src/scroll-area/corner/ScrollAreaCorner.vue +64 -0
- package/src/scroll-area/index.ts +25 -0
- package/src/scroll-area/root/ScrollAreaRoot.vue +297 -0
- package/src/scroll-area/root/ScrollAreaRootContext.ts +89 -0
- package/src/scroll-area/root/ScrollAreaRootCssVars.ts +4 -0
- package/src/scroll-area/root/ScrollAreaRootDataAttributes.ts +9 -0
- package/src/scroll-area/root/stateAttributes.ts +14 -0
- package/src/scroll-area/scrollbar/ScrollAreaScrollbar.vue +263 -0
- package/src/scroll-area/scrollbar/ScrollAreaScrollbarContext.ts +20 -0
- package/src/scroll-area/scrollbar/ScrollAreaScrollbarCssVars.ts +4 -0
- package/src/scroll-area/scrollbar/ScrollAreaScrollbarDataAttributes.ts +11 -0
- package/src/scroll-area/thumb/ScrollAreaThumb.vue +120 -0
- package/src/scroll-area/thumb/ScrollAreaThumbDataAttributes.ts +3 -0
- package/src/scroll-area/utils/getOffset.ts +34 -0
- package/src/scroll-area/viewport/ScrollAreaViewport.vue +379 -0
- package/src/scroll-area/viewport/ScrollAreaViewportContext.ts +20 -0
- package/src/scroll-area/viewport/ScrollAreaViewportCssVars.ts +6 -0
- package/src/scroll-area/viewport/ScrollAreaViewportDataAttributes.ts +9 -0
- package/src/utils/formatNumber.ts +25 -0
- package/src/utils/scrollEdges.ts +33 -0
- package/src/utils/styles.ts +28 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { BaseUIComponentProps } from '../../utils/types'
|
|
3
|
+
import type { MeterRootState } from '../root/MeterRoot.vue'
|
|
4
|
+
import { computed, useAttrs } from 'vue'
|
|
5
|
+
import { mergeProps } from '../../merge-props/mergeProps'
|
|
6
|
+
import { useRenderElement } from '../../utils/useRenderElement'
|
|
7
|
+
import { valueToPercent } from '../../utils/valueToPercent'
|
|
8
|
+
import { useMeterRootContext } from '../root/MeterRootContext'
|
|
9
|
+
|
|
10
|
+
export interface MeterIndicatorState extends MeterRootState {}
|
|
11
|
+
export interface MeterIndicatorProps extends BaseUIComponentProps<MeterIndicatorState> {}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Visualizes the position of the value along the range.
|
|
15
|
+
* Renders a `<div>` element.
|
|
16
|
+
*
|
|
17
|
+
* Documentation: [Base UI Vue Meter](https://baseui-vue.com/docs/components/meter)
|
|
18
|
+
*/
|
|
19
|
+
defineOptions({
|
|
20
|
+
name: 'MeterIndicator',
|
|
21
|
+
inheritAttrs: false,
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
const props = withDefaults(defineProps<MeterIndicatorProps>(), {
|
|
25
|
+
as: 'div',
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
const attrs = useAttrs()
|
|
29
|
+
const rootContext = useMeterRootContext()
|
|
30
|
+
|
|
31
|
+
const percentageWidth = computed(() =>
|
|
32
|
+
valueToPercent(rootContext.value.value, rootContext.min.value, rootContext.max.value),
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
const state = computed<MeterIndicatorState>(() => ({}))
|
|
36
|
+
|
|
37
|
+
const indicatorProps = computed(() => mergeProps(
|
|
38
|
+
{
|
|
39
|
+
style: {
|
|
40
|
+
insetInlineStart: 0,
|
|
41
|
+
height: 'inherit',
|
|
42
|
+
width: `${percentageWidth.value}%`,
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
attrs as Record<string, unknown>,
|
|
46
|
+
))
|
|
47
|
+
|
|
48
|
+
const {
|
|
49
|
+
tag,
|
|
50
|
+
mergedProps,
|
|
51
|
+
renderless,
|
|
52
|
+
} = useRenderElement({
|
|
53
|
+
componentProps: props,
|
|
54
|
+
state,
|
|
55
|
+
props: indicatorProps,
|
|
56
|
+
defaultTagName: 'div',
|
|
57
|
+
})
|
|
58
|
+
</script>
|
|
59
|
+
|
|
60
|
+
<template>
|
|
61
|
+
<slot v-if="renderless" :props="mergedProps" :state="state" />
|
|
62
|
+
<component :is="tag" v-else v-bind="mergedProps">
|
|
63
|
+
<slot :state="state" />
|
|
64
|
+
</component>
|
|
65
|
+
</template>
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { BaseUIComponentProps } from '../../utils/types'
|
|
3
|
+
import type { MeterRootState } from '../root/MeterRoot.vue'
|
|
4
|
+
import { computed, useAttrs } from 'vue'
|
|
5
|
+
import { useRegisteredLabelId } from '../../utils/useRegisteredLabelId'
|
|
6
|
+
import { useRenderElement } from '../../utils/useRenderElement'
|
|
7
|
+
import { useMeterRootContext } from '../root/MeterRootContext'
|
|
8
|
+
|
|
9
|
+
export interface MeterLabelState extends MeterRootState {}
|
|
10
|
+
export interface MeterLabelProps extends BaseUIComponentProps<MeterLabelState> {
|
|
11
|
+
/**
|
|
12
|
+
* The id of the label element. When provided, it overrides the automatically
|
|
13
|
+
* generated one.
|
|
14
|
+
*/
|
|
15
|
+
id?: string
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* An accessible label for the meter.
|
|
20
|
+
* Renders a `<span>` element.
|
|
21
|
+
*
|
|
22
|
+
* Documentation: [Base UI Vue Meter](https://baseui-vue.com/docs/components/meter)
|
|
23
|
+
*/
|
|
24
|
+
defineOptions({
|
|
25
|
+
name: 'MeterLabel',
|
|
26
|
+
inheritAttrs: false,
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
const props = withDefaults(defineProps<MeterLabelProps>(), {
|
|
30
|
+
as: 'span',
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
const attrs = useAttrs()
|
|
34
|
+
const { setLabelId } = useMeterRootContext()
|
|
35
|
+
|
|
36
|
+
const id = useRegisteredLabelId(() => props.id, setLabelId)
|
|
37
|
+
|
|
38
|
+
const state = computed<MeterLabelState>(() => ({}))
|
|
39
|
+
|
|
40
|
+
const labelProps = computed(() => ({
|
|
41
|
+
...attrs,
|
|
42
|
+
id: id.value,
|
|
43
|
+
role: 'presentation',
|
|
44
|
+
}))
|
|
45
|
+
|
|
46
|
+
const {
|
|
47
|
+
tag,
|
|
48
|
+
mergedProps,
|
|
49
|
+
renderless,
|
|
50
|
+
} = useRenderElement({
|
|
51
|
+
componentProps: props,
|
|
52
|
+
state,
|
|
53
|
+
props: labelProps,
|
|
54
|
+
defaultTagName: 'span',
|
|
55
|
+
})
|
|
56
|
+
</script>
|
|
57
|
+
|
|
58
|
+
<template>
|
|
59
|
+
<slot v-if="renderless" :props="mergedProps" :state="state" />
|
|
60
|
+
<component :is="tag" v-else v-bind="mergedProps">
|
|
61
|
+
<slot :state="state" />
|
|
62
|
+
</component>
|
|
63
|
+
</template>
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { BaseUIComponentProps } from '../../utils/types'
|
|
3
|
+
import { computed, provide, ref, useAttrs } from 'vue'
|
|
4
|
+
import { formatNumberValue } from '../../utils/formatNumber'
|
|
5
|
+
import { useRenderElement } from '../../utils/useRenderElement'
|
|
6
|
+
import { visuallyHidden } from '../../utils/visuallyHidden'
|
|
7
|
+
import { meterRootContextKey } from './MeterRootContext'
|
|
8
|
+
|
|
9
|
+
export interface MeterRootState {}
|
|
10
|
+
|
|
11
|
+
export interface MeterRootProps extends BaseUIComponentProps<MeterRootState> {
|
|
12
|
+
/**
|
|
13
|
+
* A string value that provides a user-friendly name for `aria-valuenow`,
|
|
14
|
+
* the current value of the meter.
|
|
15
|
+
*/
|
|
16
|
+
ariaValuetext?: string
|
|
17
|
+
/**
|
|
18
|
+
* Options to format the value.
|
|
19
|
+
*/
|
|
20
|
+
format?: Intl.NumberFormatOptions
|
|
21
|
+
/**
|
|
22
|
+
* A function that returns a string value that provides a human-readable
|
|
23
|
+
* text alternative for `aria-valuenow`, the current value of the meter.
|
|
24
|
+
*/
|
|
25
|
+
getAriaValueText?: (formattedValue: string, value: number) => string
|
|
26
|
+
/**
|
|
27
|
+
* The locale used by `Intl.NumberFormat` when formatting the value.
|
|
28
|
+
* Defaults to the user's runtime locale.
|
|
29
|
+
*/
|
|
30
|
+
locale?: Intl.LocalesArgument
|
|
31
|
+
/**
|
|
32
|
+
* The maximum value.
|
|
33
|
+
* @default 100
|
|
34
|
+
*/
|
|
35
|
+
max?: number
|
|
36
|
+
/**
|
|
37
|
+
* The minimum value.
|
|
38
|
+
* @default 0
|
|
39
|
+
*/
|
|
40
|
+
min?: number
|
|
41
|
+
/**
|
|
42
|
+
* The current value.
|
|
43
|
+
*/
|
|
44
|
+
value: number
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Groups all parts of the meter and provides the value for screen readers.
|
|
49
|
+
* Renders a `<div>` element.
|
|
50
|
+
*
|
|
51
|
+
* Documentation: [Base UI Vue Meter](https://baseui-vue.com/docs/components/meter)
|
|
52
|
+
*/
|
|
53
|
+
defineOptions({
|
|
54
|
+
name: 'MeterRoot',
|
|
55
|
+
inheritAttrs: false,
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
const props = withDefaults(defineProps<MeterRootProps>(), {
|
|
59
|
+
as: 'div',
|
|
60
|
+
max: 100,
|
|
61
|
+
min: 0,
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
const attrs = useAttrs()
|
|
65
|
+
|
|
66
|
+
const labelId = ref<string | undefined>(undefined)
|
|
67
|
+
|
|
68
|
+
const formattedValue = computed(() =>
|
|
69
|
+
formatNumberValue(props.value, props.locale, props.format),
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
const ariaValueText = computed(() => {
|
|
73
|
+
if (props.ariaValuetext !== undefined) {
|
|
74
|
+
return props.ariaValuetext
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (props.getAriaValueText) {
|
|
78
|
+
return props.getAriaValueText(formattedValue.value, props.value)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (props.format) {
|
|
82
|
+
return formattedValue.value
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return `${props.value}%`
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
provide(meterRootContextKey, {
|
|
89
|
+
formattedValue,
|
|
90
|
+
max: computed(() => props.max),
|
|
91
|
+
min: computed(() => props.min),
|
|
92
|
+
value: computed(() => props.value),
|
|
93
|
+
setLabelId(id) {
|
|
94
|
+
labelId.value = id
|
|
95
|
+
},
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
const state = computed<MeterRootState>(() => ({}))
|
|
99
|
+
|
|
100
|
+
const rootProps = computed(() => ({
|
|
101
|
+
'role': 'meter',
|
|
102
|
+
'aria-labelledby': labelId.value,
|
|
103
|
+
'aria-valuemax': props.max,
|
|
104
|
+
'aria-valuemin': props.min,
|
|
105
|
+
'aria-valuenow': props.value,
|
|
106
|
+
'aria-valuetext': ariaValueText.value,
|
|
107
|
+
...attrs,
|
|
108
|
+
}))
|
|
109
|
+
|
|
110
|
+
const {
|
|
111
|
+
tag,
|
|
112
|
+
mergedProps,
|
|
113
|
+
renderless,
|
|
114
|
+
} = useRenderElement({
|
|
115
|
+
componentProps: props,
|
|
116
|
+
state,
|
|
117
|
+
props: rootProps,
|
|
118
|
+
defaultTagName: 'div',
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
const visuallyHiddenStyle = visuallyHidden
|
|
122
|
+
</script>
|
|
123
|
+
|
|
124
|
+
<template>
|
|
125
|
+
<slot v-if="renderless" :props="mergedProps" :state="state" />
|
|
126
|
+
<component :is="tag" v-else v-bind="mergedProps">
|
|
127
|
+
<slot :state="state" />
|
|
128
|
+
<!-- Force NVDA to read the label https://github.com/mui/base-ui/issues/4184 -->
|
|
129
|
+
<span role="presentation" :style="visuallyHiddenStyle">x</span>
|
|
130
|
+
</component>
|
|
131
|
+
</template>
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { InjectionKey, Ref } from 'vue'
|
|
2
|
+
import { inject } from 'vue'
|
|
3
|
+
|
|
4
|
+
export interface MeterRootContext {
|
|
5
|
+
/**
|
|
6
|
+
* The formatted current value of the meter.
|
|
7
|
+
*/
|
|
8
|
+
formattedValue: Ref<string>
|
|
9
|
+
/**
|
|
10
|
+
* The maximum allowed value of the meter.
|
|
11
|
+
*/
|
|
12
|
+
max: Ref<number>
|
|
13
|
+
/**
|
|
14
|
+
* The minimum allowed value of the meter.
|
|
15
|
+
*/
|
|
16
|
+
min: Ref<number>
|
|
17
|
+
/**
|
|
18
|
+
* The raw current value of the meter.
|
|
19
|
+
*/
|
|
20
|
+
value: Ref<number>
|
|
21
|
+
/**
|
|
22
|
+
* Registers the DOM id of the `<MeterLabel>` for `aria-labelledby`.
|
|
23
|
+
*/
|
|
24
|
+
setLabelId: (id: string | undefined) => void
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export const meterRootContextKey: InjectionKey<MeterRootContext>
|
|
28
|
+
= Symbol('MeterRootContext')
|
|
29
|
+
|
|
30
|
+
export function useMeterRootContext(optional: true): MeterRootContext | undefined
|
|
31
|
+
export function useMeterRootContext(optional?: false): MeterRootContext
|
|
32
|
+
export function useMeterRootContext(optional = false) {
|
|
33
|
+
const context = inject(meterRootContextKey, undefined)
|
|
34
|
+
if (!context && !optional) {
|
|
35
|
+
throw new Error(
|
|
36
|
+
'Base UI Vue: MeterRootContext is missing. Meter parts must be placed within <MeterRoot>.',
|
|
37
|
+
)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return context
|
|
41
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { BaseUIComponentProps } from '../../utils/types'
|
|
3
|
+
import type { MeterRootState } from '../root/MeterRoot.vue'
|
|
4
|
+
import { computed, useAttrs } from 'vue'
|
|
5
|
+
import { useRenderElement } from '../../utils/useRenderElement'
|
|
6
|
+
|
|
7
|
+
export interface MeterTrackState extends MeterRootState {}
|
|
8
|
+
export interface MeterTrackProps extends BaseUIComponentProps<MeterTrackState> {}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Contains the meter indicator and represents the entire range of the meter.
|
|
12
|
+
* Renders a `<div>` element.
|
|
13
|
+
*
|
|
14
|
+
* Documentation: [Base UI Vue Meter](https://baseui-vue.com/docs/components/meter)
|
|
15
|
+
*/
|
|
16
|
+
defineOptions({
|
|
17
|
+
name: 'MeterTrack',
|
|
18
|
+
inheritAttrs: false,
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
const props = withDefaults(defineProps<MeterTrackProps>(), {
|
|
22
|
+
as: 'div',
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
const attrs = useAttrs()
|
|
26
|
+
|
|
27
|
+
const state = computed<MeterTrackState>(() => ({}))
|
|
28
|
+
|
|
29
|
+
const {
|
|
30
|
+
tag,
|
|
31
|
+
mergedProps,
|
|
32
|
+
renderless,
|
|
33
|
+
} = useRenderElement({
|
|
34
|
+
componentProps: props,
|
|
35
|
+
state,
|
|
36
|
+
props: computed(() => ({ ...attrs })),
|
|
37
|
+
defaultTagName: 'div',
|
|
38
|
+
})
|
|
39
|
+
</script>
|
|
40
|
+
|
|
41
|
+
<template>
|
|
42
|
+
<slot v-if="renderless" :props="mergedProps" :state="state" />
|
|
43
|
+
<component :is="tag" v-else v-bind="mergedProps">
|
|
44
|
+
<slot :state="state" />
|
|
45
|
+
</component>
|
|
46
|
+
</template>
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { BaseUIComponentProps } from '../../utils/types'
|
|
3
|
+
import type { MeterRootState } from '../root/MeterRoot.vue'
|
|
4
|
+
import { computed, useAttrs } from 'vue'
|
|
5
|
+
import { useRenderElement } from '../../utils/useRenderElement'
|
|
6
|
+
import { useMeterRootContext } from '../root/MeterRootContext'
|
|
7
|
+
|
|
8
|
+
export interface MeterValueState extends MeterRootState {}
|
|
9
|
+
export interface MeterValueProps extends BaseUIComponentProps<MeterValueState> {}
|
|
10
|
+
|
|
11
|
+
export interface MeterValueSlotProps {
|
|
12
|
+
formattedValue: string
|
|
13
|
+
value: number
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface MeterValueRenderlessSlotProps extends MeterValueSlotProps {
|
|
17
|
+
props: Record<string, unknown>
|
|
18
|
+
state: MeterValueState
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* A text element displaying the current value.
|
|
23
|
+
* Renders a `<span>` element.
|
|
24
|
+
*
|
|
25
|
+
* Documentation: [Base UI Vue Meter](https://baseui-vue.com/docs/components/meter)
|
|
26
|
+
*/
|
|
27
|
+
defineOptions({
|
|
28
|
+
name: 'MeterValue',
|
|
29
|
+
inheritAttrs: false,
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
const props = withDefaults(defineProps<MeterValueProps>(), {
|
|
33
|
+
as: 'span',
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
defineSlots<{
|
|
37
|
+
default?: (props: MeterValueSlotProps | MeterValueRenderlessSlotProps) => unknown
|
|
38
|
+
}>()
|
|
39
|
+
|
|
40
|
+
const attrs = useAttrs()
|
|
41
|
+
const { value, formattedValue } = useMeterRootContext()
|
|
42
|
+
|
|
43
|
+
const state = computed<MeterValueState>(() => ({}))
|
|
44
|
+
|
|
45
|
+
const defaultDisplay = computed(() => {
|
|
46
|
+
if (formattedValue.value) {
|
|
47
|
+
return formattedValue.value
|
|
48
|
+
}
|
|
49
|
+
return value.value != null ? String(value.value) : ''
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
const valueProps = computed(() => ({
|
|
53
|
+
'aria-hidden': true,
|
|
54
|
+
...attrs,
|
|
55
|
+
}))
|
|
56
|
+
|
|
57
|
+
const {
|
|
58
|
+
tag,
|
|
59
|
+
mergedProps,
|
|
60
|
+
renderless,
|
|
61
|
+
} = useRenderElement({
|
|
62
|
+
componentProps: props,
|
|
63
|
+
state,
|
|
64
|
+
props: valueProps,
|
|
65
|
+
defaultTagName: 'span',
|
|
66
|
+
})
|
|
67
|
+
</script>
|
|
68
|
+
|
|
69
|
+
<template>
|
|
70
|
+
<slot
|
|
71
|
+
v-if="renderless"
|
|
72
|
+
:props="mergedProps"
|
|
73
|
+
:state="state"
|
|
74
|
+
:formatted-value="formattedValue"
|
|
75
|
+
:value="value"
|
|
76
|
+
/>
|
|
77
|
+
<component :is="tag" v-else v-bind="mergedProps">
|
|
78
|
+
<slot
|
|
79
|
+
:formatted-value="formattedValue"
|
|
80
|
+
:value="value"
|
|
81
|
+
>
|
|
82
|
+
{{ defaultDisplay }}
|
|
83
|
+
</slot>
|
|
84
|
+
</component>
|
|
85
|
+
</template>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export { default as ProgressIndicator } from './indicator/ProgressIndicator.vue'
|
|
2
|
+
export type { ProgressIndicatorProps, ProgressIndicatorState } from './indicator/ProgressIndicator.vue'
|
|
3
|
+
|
|
4
|
+
export { default as ProgressLabel } from './label/ProgressLabel.vue'
|
|
5
|
+
export type { ProgressLabelProps, ProgressLabelState } from './label/ProgressLabel.vue'
|
|
6
|
+
|
|
7
|
+
export { default as ProgressRoot } from './root/ProgressRoot.vue'
|
|
8
|
+
export type { ProgressRootProps, ProgressRootState, ProgressStatus } from './root/ProgressRoot.vue'
|
|
9
|
+
export { progressRootContextKey, useProgressRootContext } from './root/ProgressRootContext'
|
|
10
|
+
export type { ProgressRootContext } from './root/ProgressRootContext'
|
|
11
|
+
export { ProgressRootDataAttributes } from './root/ProgressRootDataAttributes'
|
|
12
|
+
export { progressStateAttributesMapping } from './root/stateAttributesMapping'
|
|
13
|
+
|
|
14
|
+
export { default as ProgressTrack } from './track/ProgressTrack.vue'
|
|
15
|
+
export type { ProgressTrackProps, ProgressTrackState } from './track/ProgressTrack.vue'
|
|
16
|
+
|
|
17
|
+
export { default as ProgressValue } from './value/ProgressValue.vue'
|
|
18
|
+
export type {
|
|
19
|
+
ProgressValueProps,
|
|
20
|
+
ProgressValueRenderlessSlotProps,
|
|
21
|
+
ProgressValueSlotProps,
|
|
22
|
+
ProgressValueState,
|
|
23
|
+
} from './value/ProgressValue.vue'
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { BaseUIComponentProps } from '../../utils/types'
|
|
3
|
+
import type { ProgressRootState } from '../root/ProgressRoot.vue'
|
|
4
|
+
import { computed, useAttrs } from 'vue'
|
|
5
|
+
import { mergeProps } from '../../merge-props/mergeProps'
|
|
6
|
+
import { useRenderElement } from '../../utils/useRenderElement'
|
|
7
|
+
import { valueToPercent } from '../../utils/valueToPercent'
|
|
8
|
+
import { useProgressRootContext } from '../root/ProgressRootContext'
|
|
9
|
+
import { progressStateAttributesMapping } from '../root/stateAttributesMapping'
|
|
10
|
+
|
|
11
|
+
export interface ProgressIndicatorState extends ProgressRootState {}
|
|
12
|
+
export interface ProgressIndicatorProps extends BaseUIComponentProps<ProgressIndicatorState> {}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Visualizes the completion status of the task.
|
|
16
|
+
* Renders a `<div>` element.
|
|
17
|
+
*
|
|
18
|
+
* Documentation: [Base UI Vue Progress](https://baseui-vue.com/docs/components/progress)
|
|
19
|
+
*/
|
|
20
|
+
defineOptions({
|
|
21
|
+
name: 'ProgressIndicator',
|
|
22
|
+
inheritAttrs: false,
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
const props = withDefaults(defineProps<ProgressIndicatorProps>(), {
|
|
26
|
+
as: 'div',
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
const attrs = useAttrs()
|
|
30
|
+
const { value, min, max, state } = useProgressRootContext()
|
|
31
|
+
|
|
32
|
+
const percentage = computed(() => {
|
|
33
|
+
const v = value.value
|
|
34
|
+
if (v == null || !Number.isFinite(v)) {
|
|
35
|
+
return null
|
|
36
|
+
}
|
|
37
|
+
return valueToPercent(v, min.value, max.value)
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
const indicatorStyles = computed(() => {
|
|
41
|
+
if (percentage.value == null) {
|
|
42
|
+
return {}
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
insetInlineStart: 0,
|
|
46
|
+
height: 'inherit',
|
|
47
|
+
width: `${percentage.value}%`,
|
|
48
|
+
}
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
const indicatorProps = computed(() => mergeProps(
|
|
52
|
+
{ style: indicatorStyles.value },
|
|
53
|
+
attrs as Record<string, unknown>,
|
|
54
|
+
))
|
|
55
|
+
|
|
56
|
+
const {
|
|
57
|
+
tag,
|
|
58
|
+
mergedProps,
|
|
59
|
+
renderless,
|
|
60
|
+
} = useRenderElement({
|
|
61
|
+
componentProps: props,
|
|
62
|
+
state,
|
|
63
|
+
props: indicatorProps,
|
|
64
|
+
defaultTagName: 'div',
|
|
65
|
+
stateAttributesMapping: progressStateAttributesMapping,
|
|
66
|
+
})
|
|
67
|
+
</script>
|
|
68
|
+
|
|
69
|
+
<template>
|
|
70
|
+
<slot v-if="renderless" :props="mergedProps" :state="state" />
|
|
71
|
+
<component :is="tag" v-else v-bind="mergedProps">
|
|
72
|
+
<slot :state="state" />
|
|
73
|
+
</component>
|
|
74
|
+
</template>
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { BaseUIComponentProps } from '../../utils/types'
|
|
3
|
+
import type { ProgressRootState } from '../root/ProgressRoot.vue'
|
|
4
|
+
import { computed, useAttrs } from 'vue'
|
|
5
|
+
import { useRegisteredLabelId } from '../../utils/useRegisteredLabelId'
|
|
6
|
+
import { useRenderElement } from '../../utils/useRenderElement'
|
|
7
|
+
import { useProgressRootContext } from '../root/ProgressRootContext'
|
|
8
|
+
import { progressStateAttributesMapping } from '../root/stateAttributesMapping'
|
|
9
|
+
|
|
10
|
+
export interface ProgressLabelState extends ProgressRootState {}
|
|
11
|
+
export interface ProgressLabelProps extends BaseUIComponentProps<ProgressLabelState> {
|
|
12
|
+
/**
|
|
13
|
+
* The id of the label element. When provided, it overrides the
|
|
14
|
+
* automatically generated one.
|
|
15
|
+
*/
|
|
16
|
+
id?: string
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* An accessible label for the progress bar.
|
|
21
|
+
* Renders a `<span>` element.
|
|
22
|
+
*
|
|
23
|
+
* Documentation: [Base UI Vue Progress](https://baseui-vue.com/docs/components/progress)
|
|
24
|
+
*/
|
|
25
|
+
defineOptions({
|
|
26
|
+
name: 'ProgressLabel',
|
|
27
|
+
inheritAttrs: false,
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
const props = withDefaults(defineProps<ProgressLabelProps>(), {
|
|
31
|
+
as: 'span',
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
const attrs = useAttrs()
|
|
35
|
+
const { setLabelId, state } = useProgressRootContext()
|
|
36
|
+
|
|
37
|
+
const id = useRegisteredLabelId(() => props.id, setLabelId)
|
|
38
|
+
|
|
39
|
+
const labelProps = computed(() => ({
|
|
40
|
+
...attrs,
|
|
41
|
+
id: id.value,
|
|
42
|
+
role: 'presentation',
|
|
43
|
+
}))
|
|
44
|
+
|
|
45
|
+
const {
|
|
46
|
+
tag,
|
|
47
|
+
mergedProps,
|
|
48
|
+
renderless,
|
|
49
|
+
} = useRenderElement({
|
|
50
|
+
componentProps: props,
|
|
51
|
+
state,
|
|
52
|
+
props: labelProps,
|
|
53
|
+
defaultTagName: 'span',
|
|
54
|
+
stateAttributesMapping: progressStateAttributesMapping,
|
|
55
|
+
})
|
|
56
|
+
</script>
|
|
57
|
+
|
|
58
|
+
<template>
|
|
59
|
+
<slot v-if="renderless" :props="mergedProps" :state="state" />
|
|
60
|
+
<component :is="tag" v-else v-bind="mergedProps">
|
|
61
|
+
<slot :state="state" />
|
|
62
|
+
</component>
|
|
63
|
+
</template>
|