@byyuurin/ui 0.0.8 → 0.0.10
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 +0 -3
- package/dist/module.json +1 -1
- package/dist/module.mjs +4 -3
- package/dist/module.mjs.map +1 -1
- package/dist/runtime/app/injections.d.ts +9299 -8
- package/dist/runtime/app/injections.js +35 -5
- package/dist/runtime/components/Accordion.vue +17 -19
- package/dist/runtime/components/Alert.vue +6 -9
- package/dist/runtime/components/App.vue +14 -19
- package/dist/runtime/components/Avatar.vue +5 -8
- package/dist/runtime/components/AvatarGroup.vue +2 -5
- package/dist/runtime/components/Badge.vue +3 -6
- package/dist/runtime/components/Breadcrumb.vue +22 -23
- package/dist/runtime/components/Button.vue +2 -3
- package/dist/runtime/components/ButtonGroup.vue +2 -5
- package/dist/runtime/components/Calendar.vue +185 -0
- package/dist/runtime/components/Card.vue +2 -5
- package/dist/runtime/components/Carousel.vue +11 -16
- package/dist/runtime/components/Checkbox.vue +13 -11
- package/dist/runtime/components/Chip.vue +6 -9
- package/dist/runtime/components/Collapsible.vue +2 -5
- package/dist/runtime/components/Drawer.vue +88 -45
- package/dist/runtime/components/DropdownMenu.vue +143 -0
- package/dist/runtime/components/DropdownMenuContent.vue +188 -0
- package/dist/runtime/components/Form.vue +311 -0
- package/dist/runtime/components/FormItem.vue +129 -0
- package/dist/runtime/components/Input.vue +34 -23
- package/dist/runtime/components/InputNumber.vue +23 -18
- package/dist/runtime/components/Kbd.vue +2 -6
- package/dist/runtime/components/Link.vue +25 -7
- package/dist/runtime/components/Modal.vue +31 -22
- package/dist/runtime/components/OverlayProvider.vue +29 -0
- package/dist/runtime/components/Pagination.vue +34 -27
- package/dist/runtime/components/PinInput.vue +23 -17
- package/dist/runtime/components/Popover.vue +5 -8
- package/dist/runtime/components/Progress.vue +2 -5
- package/dist/runtime/components/RadioGroup.vue +52 -49
- package/dist/runtime/components/ScrollArea.vue +2 -6
- package/dist/runtime/components/Select.vue +96 -89
- package/dist/runtime/components/Separator.vue +2 -6
- package/dist/runtime/components/Skeleton.vue +2 -5
- package/dist/runtime/components/Slider.vue +13 -11
- package/dist/runtime/components/Switch.vue +18 -11
- package/dist/runtime/components/Table.vue +23 -13
- package/dist/runtime/components/Tabs.vue +14 -16
- package/dist/runtime/components/Textarea.vue +20 -17
- package/dist/runtime/components/Toast.vue +12 -13
- package/dist/runtime/components/{Toaster.vue → ToastProvider.vue} +18 -16
- package/dist/runtime/components/Tooltip.vue +5 -8
- package/dist/runtime/composables/useFormItem.d.ts +27 -0
- package/dist/runtime/composables/useFormItem.js +64 -0
- package/dist/runtime/composables/useKbd.d.ts +1 -1
- package/dist/runtime/composables/useOverlay.d.ts +29 -0
- package/dist/runtime/composables/useOverlay.js +69 -0
- package/dist/runtime/composables/useTheme.d.ts +6 -2
- package/dist/runtime/composables/useTheme.js +10 -3
- package/dist/runtime/composables/useToast.d.ts +4 -20
- package/dist/runtime/composables/useToast.js +6 -5
- package/dist/runtime/index.d.ts +6 -2
- package/dist/runtime/index.js +6 -2
- package/dist/runtime/locale/en.js +6 -0
- package/dist/runtime/locale/zh-tw.js +6 -0
- package/dist/runtime/theme/accordion.js +3 -3
- package/dist/runtime/theme/alert.js +3 -3
- package/dist/runtime/theme/app.d.ts +1 -0
- package/dist/runtime/theme/app.js +2 -1
- package/dist/runtime/theme/avatar.js +2 -2
- package/dist/runtime/theme/badge.d.ts +21 -45
- package/dist/runtime/theme/breadcrumb.d.ts +3 -3
- package/dist/runtime/theme/breadcrumb.js +5 -5
- package/dist/runtime/theme/button.d.ts +111 -57
- package/dist/runtime/theme/button.js +13 -13
- package/dist/runtime/theme/calendar.d.ts +56 -0
- package/dist/runtime/theme/calendar.js +69 -0
- package/dist/runtime/theme/card.js +6 -6
- package/dist/runtime/theme/carousel.js +1 -1
- package/dist/runtime/theme/checkbox.js +5 -5
- package/dist/runtime/theme/chip.d.ts +11 -44
- package/dist/runtime/theme/chip.js +3 -3
- package/dist/runtime/theme/drawer.d.ts +85 -47
- package/dist/runtime/theme/drawer.js +46 -19
- package/dist/runtime/theme/dropdown-menu.d.ts +71 -0
- package/dist/runtime/theme/dropdown-menu.js +83 -0
- package/dist/runtime/theme/form-item.d.ts +76 -0
- package/dist/runtime/theme/form-item.js +34 -0
- package/dist/runtime/theme/form.d.ts +8 -0
- package/dist/runtime/theme/form.js +7 -0
- package/dist/runtime/theme/index.d.ts +5 -1
- package/dist/runtime/theme/index.js +5 -1
- package/dist/runtime/theme/input-number.d.ts +41 -61
- package/dist/runtime/theme/input-number.js +1 -1
- package/dist/runtime/theme/input.d.ts +99 -71
- package/dist/runtime/theme/input.js +15 -15
- package/dist/runtime/theme/kbd.d.ts +2 -2
- package/dist/runtime/theme/kbd.js +1 -1
- package/dist/runtime/theme/link.d.ts +1 -1
- package/dist/runtime/theme/link.js +3 -3
- package/dist/runtime/theme/modal.d.ts +5 -33
- package/dist/runtime/theme/modal.js +4 -4
- package/dist/runtime/theme/pagination.d.ts +27 -3
- package/dist/runtime/theme/pagination.js +6 -2
- package/dist/runtime/theme/pinInput.d.ts +42 -42
- package/dist/runtime/theme/pinInput.js +13 -13
- package/dist/runtime/theme/progress.d.ts +117 -53
- package/dist/runtime/theme/progress.js +4 -4
- package/dist/runtime/theme/radio-group.d.ts +2 -2
- package/dist/runtime/theme/radio-group.js +7 -7
- package/dist/runtime/theme/select.d.ts +100 -84
- package/dist/runtime/theme/select.js +21 -20
- package/dist/runtime/theme/separator.d.ts +13 -28
- package/dist/runtime/theme/separator.js +1 -1
- package/dist/runtime/theme/skeleton.d.ts +1 -1
- package/dist/runtime/theme/skeleton.js +1 -1
- package/dist/runtime/theme/slider.js +1 -1
- package/dist/runtime/theme/switch.js +5 -5
- package/dist/runtime/theme/table.d.ts +3 -0
- package/dist/runtime/theme/table.js +8 -7
- package/dist/runtime/theme/tabs.d.ts +51 -68
- package/dist/runtime/theme/tabs.js +10 -10
- package/dist/runtime/theme/textarea.d.ts +37 -43
- package/dist/runtime/theme/textarea.js +13 -13
- package/dist/runtime/theme/{toaster.d.ts → toast-provider.d.ts} +26 -41
- package/dist/runtime/theme/toast.js +5 -5
- package/dist/runtime/theme/tooltip.js +1 -1
- package/dist/runtime/types/components.d.ts +6 -1
- package/dist/runtime/types/form.d.ts +45 -0
- package/dist/runtime/types/form.js +0 -0
- package/dist/runtime/types/index.d.ts +5 -2
- package/dist/runtime/types/index.js +1 -0
- package/dist/runtime/types/locale.d.ts +6 -0
- package/dist/runtime/types/utils.d.ts +35 -12
- package/dist/runtime/utils/extend-theme.js +15 -4
- package/dist/runtime/utils/form.d.ts +5 -0
- package/dist/runtime/utils/form.js +24 -0
- package/dist/runtime/utils/index.d.ts +2 -0
- package/dist/runtime/utils/index.js +4 -0
- package/dist/runtime/utils/link.d.ts +4 -26
- package/dist/runtime/utils/link.js +10 -3
- package/dist/shared/ui.3e7fad19.mjs +5 -0
- package/dist/shared/ui.3e7fad19.mjs.map +1 -0
- package/dist/unocss.mjs +21 -16
- package/dist/unocss.mjs.map +1 -1
- package/dist/unplugin.mjs +1 -1
- package/dist/vite.mjs +1 -1
- package/package.json +20 -18
- package/dist/runtime/components/ModalProvider.vue +0 -11
- package/dist/runtime/composables/useModal.d.ts +0 -10
- package/dist/runtime/composables/useModal.js +0 -47
- package/dist/shared/ui.ba24b380.mjs +0 -4
- package/dist/shared/ui.ba24b380.mjs.map +0 -1
- /package/dist/runtime/theme/{toaster.js → toast-provider.js} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import type { HoverCardRootProps, PopoverArrowProps, PopoverContentProps, PopoverRootEmits, PopoverRootProps } from 'reka-ui'
|
|
2
|
+
import type { HoverCardRootProps, PopoverArrowProps, PopoverContentEmits, PopoverContentProps, PopoverRootEmits, PopoverRootProps } from 'reka-ui'
|
|
3
3
|
import type { popover } from '../theme'
|
|
4
|
-
import type { ComponentAttrs } from '../types'
|
|
4
|
+
import type { ComponentAttrs, EmitsToProps } from '../types'
|
|
5
5
|
|
|
6
6
|
export interface PopoverEmits extends PopoverRootEmits {}
|
|
7
7
|
|
|
@@ -17,7 +17,7 @@ export interface PopoverProps extends ComponentAttrs<typeof popover>, PopoverRoo
|
|
|
17
17
|
*/
|
|
18
18
|
mode?: 'click' | 'hover'
|
|
19
19
|
/** @default { side: 'bottom', sideOffset: 8, collisionPadding: 8 } */
|
|
20
|
-
content?: Omit<PopoverContentProps, 'as' | 'asChild' | 'forceMount'>
|
|
20
|
+
content?: Omit<PopoverContentProps, 'as' | 'asChild' | 'forceMount'> & Partial<EmitsToProps<PopoverContentEmits>>
|
|
21
21
|
arrow?: boolean | Omit<PopoverArrowProps, 'as' | 'asChild'>
|
|
22
22
|
/** @default true */
|
|
23
23
|
portal?: boolean
|
|
@@ -69,11 +69,8 @@ const arrowProps = toRef(() => props.arrow as PopoverArrowProps)
|
|
|
69
69
|
|
|
70
70
|
const Component = computed(() => props.mode === 'hover' ? HoverCard : Popover)
|
|
71
71
|
|
|
72
|
-
const {
|
|
73
|
-
const style = computed(() =>
|
|
74
|
-
const styler = createStyler(theme.value.popover)
|
|
75
|
-
return styler(props)
|
|
76
|
-
})
|
|
72
|
+
const { generateStyle } = useTheme()
|
|
73
|
+
const style = computed(() => generateStyle('popover', props))
|
|
77
74
|
</script>
|
|
78
75
|
|
|
79
76
|
<template>
|
|
@@ -83,11 +83,8 @@ const percent = computed(() => {
|
|
|
83
83
|
})
|
|
84
84
|
|
|
85
85
|
const { dir } = useLocale()
|
|
86
|
-
const {
|
|
87
|
-
const style = computed(() =>
|
|
88
|
-
const styler = createStyler(theme.value.progress)
|
|
89
|
-
return styler(props)
|
|
90
|
-
})
|
|
86
|
+
const { generateStyle } = useTheme()
|
|
87
|
+
const style = computed(() => generateStyle('progress', props))
|
|
91
88
|
|
|
92
89
|
const indicatorStyle = computed(() => {
|
|
93
90
|
if (percent.value === undefined)
|
|
@@ -1,44 +1,35 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { VariantProps } from '@byyuurin/ui-kit'
|
|
3
|
-
import type {
|
|
3
|
+
import type { PrimitiveProps, RadioGroupRootProps } from 'reka-ui'
|
|
4
4
|
import type { radioGroup } from '../theme'
|
|
5
|
-
import type { ComponentAttrs } from '../types'
|
|
5
|
+
import type { AcceptableValue, ComponentAttrs } from '../types'
|
|
6
6
|
|
|
7
7
|
export interface RadioGroupEmits {
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
'update:modelValue': [payload: string]
|
|
9
|
+
'change': [payload: Event]
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
type
|
|
12
|
+
export type RadioGroupValue = AcceptableValue
|
|
13
13
|
|
|
14
|
-
export
|
|
15
|
-
|
|
14
|
+
export type RadioGroupItem = {
|
|
15
|
+
label?: string
|
|
16
|
+
description?: string
|
|
17
|
+
disabled?: boolean
|
|
18
|
+
value?: RadioGroupValue
|
|
19
|
+
[key: string]: any
|
|
20
|
+
} | RadioGroupValue
|
|
21
|
+
|
|
22
|
+
type SlotProps<T extends RadioGroupItem> = (props: { item: T & { id: string }, modelValue?: RadioGroupValue }) => any
|
|
23
|
+
|
|
24
|
+
export interface RadioGroupSlots<T extends RadioGroupItem = RadioGroupItem> {
|
|
25
|
+
legend?: any
|
|
16
26
|
label?: SlotProps<T>
|
|
17
27
|
description?: SlotProps<T>
|
|
18
28
|
}
|
|
19
29
|
|
|
20
|
-
type NormalizeItem<T> = { id: string } & (
|
|
21
|
-
T extends RadioOption
|
|
22
|
-
? T
|
|
23
|
-
: {
|
|
24
|
-
id: string
|
|
25
|
-
label: string
|
|
26
|
-
value: any
|
|
27
|
-
description: string
|
|
28
|
-
disabled: false
|
|
29
|
-
}
|
|
30
|
-
)
|
|
31
|
-
|
|
32
30
|
type RadioGroupVariants = VariantProps<typeof radioGroup>
|
|
33
31
|
|
|
34
|
-
export interface
|
|
35
|
-
label?: string
|
|
36
|
-
description?: string
|
|
37
|
-
disabled?: boolean
|
|
38
|
-
value?: string
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export interface RadioGroupProps<T> extends ComponentAttrs<typeof radioGroup>, Pick<RadioGroupRootProps, 'defaultValue' | 'disabled' | 'loop' | 'modelValue' | 'name' | 'required'> {
|
|
32
|
+
export interface RadioGroupProps<T extends RadioGroupItem = RadioGroupItem> extends ComponentAttrs<typeof radioGroup>, Pick<RadioGroupRootProps, 'defaultValue' | 'disabled' | 'loop' | 'modelValue' | 'name' | 'required'> {
|
|
42
33
|
/**
|
|
43
34
|
* The element or component this component should render as.
|
|
44
35
|
* @default "div"
|
|
@@ -70,10 +61,11 @@ export interface RadioGroupProps<T> extends ComponentAttrs<typeof radioGroup>, P
|
|
|
70
61
|
}
|
|
71
62
|
</script>
|
|
72
63
|
|
|
73
|
-
<script lang="ts" setup generic="T extends
|
|
64
|
+
<script lang="ts" setup generic="T extends RadioGroupItem">
|
|
74
65
|
import { reactivePick } from '@vueuse/core'
|
|
75
66
|
import { Label, RadioGroupIndicator, RadioGroupItem, RadioGroupRoot, useForwardPropsEmits } from 'reka-ui'
|
|
76
67
|
import { computed, useId } from 'vue'
|
|
68
|
+
import { useFormItem } from '../composables/useFormItem'
|
|
77
69
|
import { useTheme } from '../composables/useTheme'
|
|
78
70
|
import { get } from '../utils'
|
|
79
71
|
|
|
@@ -88,22 +80,33 @@ const emit = defineEmits<RadioGroupEmits>()
|
|
|
88
80
|
const slots = defineSlots<RadioGroupSlots<T>>()
|
|
89
81
|
|
|
90
82
|
const rootProps = useForwardPropsEmits(reactivePick(props, 'as', 'modelValue', 'defaultValue', 'orientation', 'loop', 'required'), emit)
|
|
91
|
-
const id = useId()
|
|
92
83
|
|
|
93
|
-
const {
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
84
|
+
const { id: _id, name, size, disabled, ariaAttrs, emitFormChange, emitFormInput } = useFormItem<RadioGroupProps<T>>(props)
|
|
85
|
+
const id = _id.value ?? useId()
|
|
86
|
+
|
|
87
|
+
const { generateStyle } = useTheme()
|
|
88
|
+
const style = computed(() => generateStyle('radioGroup', {
|
|
89
|
+
...props,
|
|
90
|
+
size: size.value,
|
|
91
|
+
disabled: disabled.value,
|
|
92
|
+
}))
|
|
93
|
+
|
|
94
|
+
function normalizeItem(item: any) {
|
|
95
|
+
if (item === null) {
|
|
96
|
+
return {
|
|
97
|
+
id: `${id}:null`,
|
|
98
|
+
label: undefined,
|
|
99
|
+
value: undefined,
|
|
100
|
+
}
|
|
101
|
+
}
|
|
98
102
|
|
|
99
|
-
|
|
100
|
-
if (['string', 'number', 'boolean'].includes(typeof item)) {
|
|
103
|
+
if (typeof item === 'string' || typeof item === 'number') {
|
|
101
104
|
return {
|
|
102
105
|
id: `${id}:${item}`,
|
|
106
|
+
label: String(item),
|
|
103
107
|
value: item,
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
} as any
|
|
108
|
+
disabled: disabled.value,
|
|
109
|
+
}
|
|
107
110
|
}
|
|
108
111
|
|
|
109
112
|
const value = get(item, props.valueKey)
|
|
@@ -112,10 +115,11 @@ function normalizeItem(item: any): NormalizeItem<T> {
|
|
|
112
115
|
|
|
113
116
|
return {
|
|
114
117
|
...item,
|
|
115
|
-
value
|
|
118
|
+
id: `${id}:${value}`,
|
|
116
119
|
label,
|
|
120
|
+
value,
|
|
117
121
|
description,
|
|
118
|
-
|
|
122
|
+
disabled: disabled.value || item.disabled,
|
|
119
123
|
}
|
|
120
124
|
}
|
|
121
125
|
|
|
@@ -130,26 +134,25 @@ function onUpdate(value: any) {
|
|
|
130
134
|
// @ts-expect-error - 'target' does not exist in type 'EventInit'
|
|
131
135
|
const event = new Event('change', { target: { value } })
|
|
132
136
|
emit('change', event)
|
|
137
|
+
emitFormChange()
|
|
138
|
+
emitFormInput()
|
|
133
139
|
}
|
|
134
140
|
</script>
|
|
135
141
|
|
|
136
142
|
<template>
|
|
137
143
|
<RadioGroupRoot
|
|
138
|
-
:id="id"
|
|
139
144
|
v-slot="{ modelValue }"
|
|
140
|
-
v-bind="rootProps"
|
|
141
|
-
:name="props.name"
|
|
142
|
-
:disabled="props.disabled"
|
|
145
|
+
v-bind="{ ...rootProps, id, name, disabled }"
|
|
143
146
|
:class="style.root({ class: [props.class, props.ui?.root] })"
|
|
144
147
|
@update:model-value="onUpdate"
|
|
145
148
|
>
|
|
146
|
-
<fieldset :class="style.fieldset({ class: props.ui?.fieldset })">
|
|
149
|
+
<fieldset v-bind="ariaAttrs" :class="style.fieldset({ class: props.ui?.fieldset })">
|
|
147
150
|
<legend v-if="props.legend || slots.legend" :class="style.legend({ class: props.ui?.legend })">
|
|
148
151
|
<slot name="legend">
|
|
149
152
|
{{ props.legend }}
|
|
150
153
|
</slot>
|
|
151
154
|
</legend>
|
|
152
|
-
<div v-for="item in normalizedItems" :key="item.value" :class="style.item({ class: props.ui?.item })">
|
|
155
|
+
<div v-for="item in normalizedItems" :key="item.value" :class="style.item({ class: props.ui?.item, disabled: item.disabled })">
|
|
153
156
|
<div :class="style.container({ class: props.ui?.container })">
|
|
154
157
|
<RadioGroupItem
|
|
155
158
|
:id="item.id"
|
|
@@ -163,10 +166,10 @@ function onUpdate(value: any) {
|
|
|
163
166
|
|
|
164
167
|
<div :class="style.wrapper({ class: props.ui?.wrapper })">
|
|
165
168
|
<Label :for="item.id" :class="style.label({ class: props.ui?.label })">
|
|
166
|
-
<slot name="label" :item="item" :model-value="modelValue">{{ item.label }}</slot>
|
|
169
|
+
<slot name="label" :item="item" :model-value="(modelValue as RadioGroupValue)">{{ item.label }}</slot>
|
|
167
170
|
</Label>
|
|
168
171
|
<p v-if="item.description || slots.description" :class="style.description({ class: props.ui?.description })">
|
|
169
|
-
<slot name="description" :item="item" :model-value="modelValue">
|
|
172
|
+
<slot name="description" :item="item" :model-value="(modelValue as RadioGroupValue)">
|
|
170
173
|
{{ item.description }}
|
|
171
174
|
</slot>
|
|
172
175
|
</p>
|
|
@@ -17,12 +17,8 @@ const props = withDefaults(defineProps<ScrollAreaProps>(), {})
|
|
|
17
17
|
const rootRef = ref<InstanceType<typeof ScrollAreaRoot>>()
|
|
18
18
|
const rootProps = reactivePick(props, 'type', 'dir', 'scrollHideDelay')
|
|
19
19
|
|
|
20
|
-
const {
|
|
21
|
-
|
|
22
|
-
const style = computed(() => {
|
|
23
|
-
const styler = createStyler(theme.value.scrollArea)
|
|
24
|
-
return styler(props)
|
|
25
|
-
})
|
|
20
|
+
const { generateStyle } = useTheme()
|
|
21
|
+
const style = computed(() => generateStyle('scrollArea', props))
|
|
26
22
|
|
|
27
23
|
defineExpose({
|
|
28
24
|
scrollTop,
|
|
@@ -1,33 +1,11 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { VariantProps } from '@byyuurin/ui-kit'
|
|
3
|
-
import type {
|
|
3
|
+
import type { SelectArrowProps, SelectContentEmits, SelectContentProps, SelectRootEmits, SelectRootProps } from 'reka-ui'
|
|
4
4
|
import type { UseComponentIconsProps } from '../composables/useComponentIcons'
|
|
5
5
|
import type { select } from '../theme'
|
|
6
|
-
import type { ComponentAttrs,
|
|
6
|
+
import type { AcceptableValue, ArrayOrNested, ComponentAttrs, EmitsToProps, GetItemKeys, GetItemValue, GetModelValue, GetModelValueEmits, MaybeArray, NestedItem } from '../types'
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
(event: 'update:open', value: boolean): void
|
|
10
|
-
(event: 'update:modelValue', payload: SelectModelValue<T, V, M, T extends { value: infer U } ? U : never>): void
|
|
11
|
-
(event: 'change', payload: Event): void
|
|
12
|
-
(event: 'blur', payload: FocusEvent): void
|
|
13
|
-
(event: 'focus', payload: FocusEvent): void
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
type SlotProps<T> = (props: { item: T, index: number }) => any
|
|
17
|
-
|
|
18
|
-
export interface SelectSlots<T, M extends boolean> {
|
|
19
|
-
'leading'?: (props: { modelValue?: M extends true ? AcceptableValue[] : AcceptableValue, open: boolean, ui: ComponentAttrs<typeof select>['ui'] }) => any
|
|
20
|
-
'default'?: (props: { modelValue?: M extends true ? AcceptableValue[] : AcceptableValue, open: boolean }) => any
|
|
21
|
-
'trailing'?: (props: { modelValue?: M extends true ? AcceptableValue[] : AcceptableValue, open: boolean, ui: ComponentAttrs<typeof select>['ui'] }) => any
|
|
22
|
-
'item'?: SlotProps<T>
|
|
23
|
-
'item-leading'?: SlotProps<T>
|
|
24
|
-
'item-label'?: SlotProps<T>
|
|
25
|
-
'item-trailing'?: SlotProps<T>
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
type SelectVariants = VariantProps<typeof select>
|
|
29
|
-
|
|
30
|
-
export interface SelectOption {
|
|
8
|
+
interface SelectItemBase {
|
|
31
9
|
label?: string
|
|
32
10
|
icon?: string
|
|
33
11
|
/**
|
|
@@ -35,18 +13,43 @@ export interface SelectOption {
|
|
|
35
13
|
* @default "option"
|
|
36
14
|
*/
|
|
37
15
|
type?: 'label' | 'separator' | 'option'
|
|
38
|
-
value?:
|
|
16
|
+
value?: AcceptableValue
|
|
39
17
|
disabled?: boolean
|
|
18
|
+
[key: string]: any
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export type SelectItem = SelectItemBase | AcceptableValue | boolean
|
|
22
|
+
|
|
23
|
+
export type SelectEmits<T extends ArrayOrNested<SelectItem>, VK extends GetItemKeys<T> | undefined, M extends boolean> = Omit<SelectRootEmits, 'update:modelValue'> & {
|
|
24
|
+
change: [payload: Event]
|
|
25
|
+
blur: [payload: FocusEvent]
|
|
26
|
+
focus: [payload: FocusEvent]
|
|
27
|
+
} & GetModelValueEmits<T, VK, M>
|
|
28
|
+
|
|
29
|
+
type SlotProps<T extends SelectItem> = (props: { item: T, index: number }) => any
|
|
30
|
+
|
|
31
|
+
export interface SelectSlots<
|
|
32
|
+
T extends ArrayOrNested<SelectItem> = ArrayOrNested<SelectItem>,
|
|
33
|
+
VK extends GetItemKeys<T> | undefined = undefined,
|
|
34
|
+
M extends boolean = false,
|
|
35
|
+
I extends NestedItem<T> = NestedItem<T>,
|
|
36
|
+
> {
|
|
37
|
+
'leading'?: (props: { modelValue?: GetModelValue<T, VK, M>, open: boolean, ui: ComponentAttrs<typeof select>['ui'] }) => any
|
|
38
|
+
'default'?: (props: { modelValue?: GetModelValue<T, VK, M>, open: boolean }) => any
|
|
39
|
+
'trailing'?: (props: { modelValue?: GetModelValue<T, VK, M>, open: boolean, ui: ComponentAttrs<typeof select>['ui'] }) => any
|
|
40
|
+
'item'?: SlotProps<I>
|
|
41
|
+
'item-leading'?: SlotProps<I>
|
|
42
|
+
'item-label'?: SlotProps<I>
|
|
43
|
+
'item-trailing'?: SlotProps<I>
|
|
40
44
|
}
|
|
41
45
|
|
|
42
|
-
|
|
46
|
+
type SelectVariants = VariantProps<typeof select>
|
|
43
47
|
|
|
44
48
|
export interface SelectProps<
|
|
45
|
-
T extends
|
|
46
|
-
|
|
47
|
-
V extends SelectOptionKey<T> | undefined = undefined,
|
|
49
|
+
T extends ArrayOrNested<SelectItem> = ArrayOrNested<SelectItem>,
|
|
50
|
+
VK extends GetItemKeys<T> = 'value',
|
|
48
51
|
M extends boolean = false,
|
|
49
|
-
> extends Omit<SelectRootProps<T>, 'dir' | 'multiple' | 'modelValue' | 'defaultValue' | 'by'
|
|
52
|
+
> extends ComponentAttrs<typeof select>, UseComponentIconsProps, Omit<SelectRootProps<T>, 'dir' | 'multiple' | 'modelValue' | 'defaultValue' | 'by'> {
|
|
50
53
|
id?: string
|
|
51
54
|
/** The placeholder text when the select is empty. */
|
|
52
55
|
placeholder?: string
|
|
@@ -66,7 +69,7 @@ export interface SelectProps<
|
|
|
66
69
|
* The content of the menu.
|
|
67
70
|
* @default { side: 'bottom', sideOffset: 8, collisionPadding: 8, position: 'popper' }
|
|
68
71
|
*/
|
|
69
|
-
content?: Omit<SelectContentProps, 'as' | 'asChild' | 'forceMount'>
|
|
72
|
+
content?: Omit<SelectContentProps, 'as' | 'asChild' | 'forceMount'> & Partial<EmitsToProps<SelectContentEmits>>
|
|
70
73
|
/**
|
|
71
74
|
* Display an arrow alongside the menu.
|
|
72
75
|
* @default false
|
|
@@ -81,17 +84,17 @@ export interface SelectProps<
|
|
|
81
84
|
* When `options` is an array of objects, select the field to use as the value.
|
|
82
85
|
* @default "value"
|
|
83
86
|
*/
|
|
84
|
-
valueKey?:
|
|
87
|
+
valueKey?: VK
|
|
85
88
|
/**
|
|
86
89
|
* When `options` is an array of objects, select the field to use as the label.
|
|
87
90
|
* @default "label"
|
|
88
91
|
*/
|
|
89
|
-
labelKey?:
|
|
90
|
-
options?:
|
|
92
|
+
labelKey?: VK
|
|
93
|
+
options?: T
|
|
91
94
|
/** The value of the Select when initially rendered. Use when you do not need to control the state of the Select. */
|
|
92
|
-
defaultValue?:
|
|
95
|
+
defaultValue?: GetModelValue<T, VK, M>
|
|
93
96
|
/** The controlled value of the Select. Can be bind as `v-model`. */
|
|
94
|
-
modelValue?:
|
|
97
|
+
modelValue?: GetModelValue<T, VK, M>
|
|
95
98
|
/** Whether multiple options can be selected or not. */
|
|
96
99
|
multiple?: M & boolean
|
|
97
100
|
/** Highlight the ring color like a focus state. */
|
|
@@ -100,85 +103,89 @@ export interface SelectProps<
|
|
|
100
103
|
}
|
|
101
104
|
</script>
|
|
102
105
|
|
|
103
|
-
<script lang="ts" setup generic="T extends
|
|
106
|
+
<script lang="ts" setup generic="T extends ArrayOrNested<SelectItem>, VK extends GetItemKeys<T> = 'value', M extends boolean = false">
|
|
104
107
|
import { reactivePick } from '@vueuse/core'
|
|
105
108
|
import { defu } from 'defu'
|
|
106
109
|
import { SelectArrow, SelectContent, SelectGroup, SelectItem, SelectItemIndicator, SelectItemText, SelectLabel, SelectPortal, SelectRoot, SelectSeparator, SelectTrigger, SelectViewport, useForwardPropsEmits } from 'reka-ui'
|
|
107
110
|
import { computed, toRef } from 'vue'
|
|
108
111
|
import { useButtonGroup } from '../composables/useButtonGroup'
|
|
109
112
|
import { useComponentIcons } from '../composables/useComponentIcons'
|
|
113
|
+
import { useFormItem } from '../composables/useFormItem'
|
|
110
114
|
import { useTheme } from '../composables/useTheme'
|
|
111
|
-
import { compare, get } from '../utils'
|
|
115
|
+
import { compare, get, isArrayOfArray } from '../utils'
|
|
116
|
+
|
|
117
|
+
defineOptions({
|
|
118
|
+
inheritAttrs: false,
|
|
119
|
+
})
|
|
112
120
|
|
|
113
|
-
const props = withDefaults(defineProps<SelectProps<T,
|
|
114
|
-
variant: 'outline',
|
|
121
|
+
const props = withDefaults(defineProps<SelectProps<T, VK, M>>(), {
|
|
115
122
|
valueKey: 'value' as never,
|
|
116
123
|
labelKey: 'label' as never,
|
|
117
124
|
portal: true,
|
|
118
125
|
})
|
|
119
126
|
|
|
120
|
-
const emit = defineEmits<SelectEmits<T,
|
|
121
|
-
const slots = defineSlots<SelectSlots<T, M>>()
|
|
127
|
+
const emit = defineEmits<SelectEmits<T, VK, M>>()
|
|
128
|
+
const slots = defineSlots<SelectSlots<T, VK, M>>()
|
|
122
129
|
|
|
123
130
|
const rootProps = useForwardPropsEmits(reactivePick(props, 'open', 'defaultOpen', 'disabled', 'autocomplete', 'required', 'multiple'), emit)
|
|
124
131
|
const contentProps = toRef(() => defu(props.content, { side: 'bottom', sideOffset: 8, collisionPadding: 8, position: 'popper' }) as SelectContentProps)
|
|
125
132
|
const arrowProps = toRef(() => props.arrow as SelectArrowProps)
|
|
126
133
|
|
|
127
|
-
const {
|
|
134
|
+
const { id, name, size: formItemSize, highlight, disabled, ariaAttrs, emitFormChange, emitFormInput, emitFormBlur, emitFormFocus } = useFormItem<SelectProps<T, VK, M>>(props)
|
|
135
|
+
const { size: buttonGroupSize, orientation } = useButtonGroup(props)
|
|
128
136
|
|
|
129
|
-
const {
|
|
137
|
+
const { theme, generateStyle } = useTheme()
|
|
130
138
|
const { isLeading, isTrailing, leadingIconName, trailingIconName } = useComponentIcons(toRef(() => defu(props, {
|
|
131
139
|
trailingIcon: theme.value.app.icons.chevronDown,
|
|
132
140
|
})))
|
|
133
141
|
|
|
134
|
-
const
|
|
135
|
-
|
|
142
|
+
const style = computed(() => generateStyle('select', {
|
|
143
|
+
...props,
|
|
144
|
+
groupOrientation: orientation.value,
|
|
145
|
+
size: buttonGroupSize.value || formItemSize.value,
|
|
146
|
+
highlight: highlight.value,
|
|
147
|
+
leading: isLeading.value,
|
|
148
|
+
trailing: isTrailing.value,
|
|
149
|
+
}))
|
|
136
150
|
|
|
137
|
-
const
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
groupOrientation: orientation.value,
|
|
143
|
-
leading: isLeading.value,
|
|
144
|
-
trailing: isTrailing.value,
|
|
145
|
-
})
|
|
146
|
-
})
|
|
147
|
-
|
|
148
|
-
function typedItem(item: SelectOption) {
|
|
149
|
-
return item as unknown as T
|
|
150
|
-
}
|
|
151
|
+
const groups = computed<SelectItem[][]>(
|
|
152
|
+
() => props.options?.length
|
|
153
|
+
? isArrayOfArray(props.options) ? props.options : [props.options]
|
|
154
|
+
: [],
|
|
155
|
+
)
|
|
151
156
|
|
|
152
|
-
|
|
153
|
-
return value as unknown as M extends true ? AcceptableValue[] : AcceptableValue
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
function typedModelValue(value: any) {
|
|
157
|
-
return value as MaybeArray<AcceptableValue> | undefined
|
|
158
|
-
}
|
|
157
|
+
const items = computed(() => groups.value.flat() as T[])
|
|
159
158
|
|
|
160
|
-
function displayValue(value?: MaybeArray<
|
|
159
|
+
function displayValue(value?: MaybeArray<GetItemValue<T, VK>>): string {
|
|
161
160
|
if (props.multiple && Array.isArray(value))
|
|
162
161
|
return value.map((v) => displayValue(v)).filter(Boolean).join(', ')
|
|
163
162
|
|
|
164
163
|
const item = items.value.find((item) => compare(typeof item === 'object' ? get(item as Record<string, any>, props.valueKey as string) : item, value))
|
|
165
|
-
return item && (typeof item === 'object' ? get(item, props.labelKey as string) : item)
|
|
164
|
+
return (item != null) && (typeof item === 'object' ? get(item, props.labelKey as string) : String(item))
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function isSelectItem(item: SelectItem): item is SelectItemBase {
|
|
168
|
+
return typeof item === 'object' && item !== null
|
|
166
169
|
}
|
|
167
170
|
|
|
168
171
|
function onUpdate(value: any) {
|
|
169
172
|
// @ts-expect-error - 'target' does not exist in type 'EventInit'
|
|
170
173
|
const event = new Event('change', { target: { value } })
|
|
171
174
|
emit('change', event)
|
|
175
|
+
emitFormChange()
|
|
176
|
+
emitFormInput()
|
|
172
177
|
}
|
|
173
178
|
|
|
174
179
|
function onUpdateOpen(value: boolean) {
|
|
175
180
|
if (value) {
|
|
176
181
|
const event = new FocusEvent('focus')
|
|
177
182
|
emit('focus', event)
|
|
183
|
+
emitFormFocus()
|
|
178
184
|
}
|
|
179
185
|
else {
|
|
180
186
|
const event = new FocusEvent('blur')
|
|
181
187
|
emit('blur', event)
|
|
188
|
+
emitFormBlur()
|
|
182
189
|
}
|
|
183
190
|
}
|
|
184
191
|
</script>
|
|
@@ -186,24 +193,24 @@ function onUpdateOpen(value: boolean) {
|
|
|
186
193
|
<template>
|
|
187
194
|
<SelectRoot
|
|
188
195
|
v-slot="{ modelValue: innerValue, open }"
|
|
189
|
-
:name="props.name"
|
|
190
196
|
v-bind="rootProps"
|
|
197
|
+
:name="name"
|
|
191
198
|
:autocomplete="props.autocomplete"
|
|
192
|
-
:disabled="
|
|
193
|
-
:default-value="
|
|
194
|
-
:model-value="
|
|
199
|
+
:disabled="disabled"
|
|
200
|
+
:default-value="(props.defaultValue as MaybeArray<AcceptableValue>)"
|
|
201
|
+
:model-value="(props.modelValue as MaybeArray<AcceptableValue>)"
|
|
195
202
|
@update:model-value="onUpdate"
|
|
196
203
|
@update:open="onUpdateOpen"
|
|
197
204
|
>
|
|
198
|
-
<SelectTrigger
|
|
205
|
+
<SelectTrigger v-bind="{ ...$attrs, ...ariaAttrs, id }" :class="style.base({ class: [props.class, props.ui?.base] })">
|
|
199
206
|
<span v-if="isLeading || slots.leading" :class="style.leading({ class: props.ui?.leading })">
|
|
200
|
-
<slot name="leading" :model-value="
|
|
207
|
+
<slot name="leading" :model-value="(innerValue as GetModelValue<T, VK, M>)" :open="open" :ui="props.ui">
|
|
201
208
|
<span v-if="isLeading && leadingIconName" :class="style.leadingIcon({ class: [leadingIconName, props.ui?.leadingIcon] })"></span>
|
|
202
209
|
</slot>
|
|
203
210
|
</span>
|
|
204
211
|
|
|
205
|
-
<slot :model-value="
|
|
206
|
-
<template v-for="displayedModelValue in [displayValue(innerValue)]" :key="displayedModelValue">
|
|
212
|
+
<slot :model-value="(innerValue as GetModelValue<T, VK, M>)" :open="open">
|
|
213
|
+
<template v-for="displayedModelValue in [displayValue((innerValue as GetModelValue<T, VK, M>))]" :key="displayedModelValue">
|
|
207
214
|
<span v-if="displayedModelValue" :class="style.value({ class: props.ui?.value })">
|
|
208
215
|
{{ displayedModelValue }}
|
|
209
216
|
</span>
|
|
@@ -214,7 +221,7 @@ function onUpdateOpen(value: boolean) {
|
|
|
214
221
|
</slot>
|
|
215
222
|
|
|
216
223
|
<span v-if="isTrailing || !!slots.trailing" :class="style.trailing({ class: props.ui?.trailing })">
|
|
217
|
-
<slot name="trailing" :model-value="
|
|
224
|
+
<slot name="trailing" :model-value="(innerValue as GetModelValue<T, VK, M>)" :open="open" :ui="props.ui">
|
|
218
225
|
<span v-if="trailingIconName" :class="style.trailingIcon({ class: [trailingIconName, props.ui?.trailingIcon] })"></span>
|
|
219
226
|
</slot>
|
|
220
227
|
</span>
|
|
@@ -225,30 +232,30 @@ function onUpdateOpen(value: boolean) {
|
|
|
225
232
|
<SelectViewport :class="style.viewport({ class: props.ui?.viewport })">
|
|
226
233
|
<SelectGroup v-for="(group, groupIndex) in groups" :key="`group-${groupIndex}`" :class="style.group({ class: props.ui?.group })">
|
|
227
234
|
<template v-for="(item, index) in group" :key="`group-${groupIndex}-${index}`">
|
|
228
|
-
<SelectLabel v-if="item.type === 'label'" :class="style.label({ class: props.ui?.label })">
|
|
235
|
+
<SelectLabel v-if="isSelectItem(item) && item.type === 'label'" :class="style.label({ class: props.ui?.label })">
|
|
229
236
|
{{ get(item, props.labelKey as string) }}
|
|
230
237
|
</SelectLabel>
|
|
231
|
-
<SelectSeparator v-else-if="item.type === 'separator'" :class="style.separator({ class: props.ui?.separator })" />
|
|
238
|
+
<SelectSeparator v-else-if="isSelectItem(item) && item.type === 'separator'" :class="style.separator({ class: props.ui?.separator })" />
|
|
232
239
|
|
|
233
240
|
<SelectItem
|
|
234
241
|
v-else
|
|
235
242
|
:class="style.item({ class: props.ui?.item })"
|
|
236
|
-
:disabled="item.disabled"
|
|
237
|
-
:value="
|
|
243
|
+
:disabled="isSelectItem(item) && item.disabled"
|
|
244
|
+
:value="isSelectItem(item) ? get(item, props.valueKey as string) : item"
|
|
238
245
|
>
|
|
239
|
-
<slot name="item" :item="
|
|
240
|
-
<slot name="item-leading" :item="
|
|
241
|
-
<span v-if="item.icon" :class="style.itemLeadingIcon({ class: [item.icon, props.ui?.itemLeadingIcon] })"></span>
|
|
246
|
+
<slot name="item" :item="(item as NestedItem<T>)" :index="index">
|
|
247
|
+
<slot name="item-leading" :item="(item as NestedItem<T>)" :index="index">
|
|
248
|
+
<span v-if="isSelectItem(item) && item.icon" :class="style.itemLeadingIcon({ class: [item.icon, props.ui?.itemLeadingIcon] })"></span>
|
|
242
249
|
</slot>
|
|
243
250
|
|
|
244
251
|
<SelectItemText :class="style.itemLabel({ class: props.ui?.itemLabel })">
|
|
245
|
-
<slot name="item-label" :item="
|
|
246
|
-
{{
|
|
252
|
+
<slot name="item-label" :item="(item as NestedItem<T>)" :index="index">
|
|
253
|
+
{{ isSelectItem(item) ? get(item, props.labelKey as string) : item }}
|
|
247
254
|
</slot>
|
|
248
255
|
</SelectItemText>
|
|
249
256
|
|
|
250
257
|
<span :class="style.itemTrailing({ class: props.ui?.itemTrailing })">
|
|
251
|
-
<slot name="item-trailing" :item="
|
|
258
|
+
<slot name="item-trailing" :item="(item as NestedItem<T>)" :index="index"></slot>
|
|
252
259
|
|
|
253
260
|
<SelectItemIndicator as-child>
|
|
254
261
|
<span :class="style.itemTrailingIcon({ class: [props.selectedIcon || theme.app.icons.check, props.ui?.itemTrailingIcon] })"></span>
|
|
@@ -37,12 +37,8 @@ const slots = defineSlots<SeparatorSlots>()
|
|
|
37
37
|
|
|
38
38
|
const rootProps = useForwardProps(reactivePick(props, 'as', 'decorative', 'orientation'))
|
|
39
39
|
|
|
40
|
-
const {
|
|
41
|
-
|
|
42
|
-
const style = computed(() => {
|
|
43
|
-
const styler = createStyler(theme.value.separator)
|
|
44
|
-
return styler(props)
|
|
45
|
-
})
|
|
40
|
+
const { generateStyle } = useTheme()
|
|
41
|
+
const style = computed(() => generateStyle('separator', props))
|
|
46
42
|
</script>
|
|
47
43
|
|
|
48
44
|
<template>
|
|
@@ -19,11 +19,8 @@ import { useTheme } from '../composables/useTheme'
|
|
|
19
19
|
|
|
20
20
|
const props = withDefaults(defineProps<SkeletonProps>(), {})
|
|
21
21
|
|
|
22
|
-
const {
|
|
23
|
-
const styler = computed(() =>
|
|
24
|
-
const styler = createStyler(theme.value.skeleton)
|
|
25
|
-
return styler(props)
|
|
26
|
-
})
|
|
22
|
+
const { generateStyle } = useTheme()
|
|
23
|
+
const styler = computed(() => generateStyle('skeleton', props))
|
|
27
24
|
</script>
|
|
28
25
|
|
|
29
26
|
<template>
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
import type { VariantProps } from '@byyuurin/ui-kit'
|
|
3
3
|
import type { SliderRootProps } from 'reka-ui'
|
|
4
4
|
import type { slider } from '../theme'
|
|
5
|
-
import type { ComponentAttrs } from '../types'
|
|
5
|
+
import type { ComponentAttrs, MaybeArray } from '../types'
|
|
6
6
|
|
|
7
7
|
export interface SliderEmits {
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
'update:modelValue': [payload: MaybeArray<number>]
|
|
9
|
+
'change': [payload: Event]
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
type SliderVariants = VariantProps<typeof slider>
|
|
@@ -28,6 +28,7 @@ export interface SliderProps extends ComponentAttrs<typeof slider>, Pick<SliderR
|
|
|
28
28
|
import { reactivePick } from '@vueuse/core'
|
|
29
29
|
import { SliderRange, SliderRoot, SliderThumb, SliderTrack, useForwardPropsEmits } from 'reka-ui'
|
|
30
30
|
import { computed } from 'vue'
|
|
31
|
+
import { useFormItem } from '../composables/useFormItem'
|
|
31
32
|
import { useTheme } from '../composables/useTheme'
|
|
32
33
|
|
|
33
34
|
const props = withDefaults(defineProps<SliderProps>(), {
|
|
@@ -63,25 +64,26 @@ const sliderValue = computed({
|
|
|
63
64
|
|
|
64
65
|
const thumbsCount = computed(() => sliderValue.value?.length ?? 1)
|
|
65
66
|
|
|
66
|
-
const {
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
67
|
+
const { id, size, name, disabled, ariaAttrs, emitFormChange, emitFormInput } = useFormItem<SliderProps>(props)
|
|
68
|
+
const { generateStyle } = useTheme()
|
|
69
|
+
const style = computed(() => generateStyle('slider', {
|
|
70
|
+
...props,
|
|
71
|
+
size: size.value,
|
|
72
|
+
}))
|
|
71
73
|
|
|
72
74
|
function onChange(value: any) {
|
|
73
75
|
// @ts-expect-error - 'target' does not exist in type 'EventInit'
|
|
74
76
|
const event = new Event('change', { target: { value } })
|
|
75
77
|
emit('change', event)
|
|
78
|
+
emitFormChange()
|
|
79
|
+
emitFormInput()
|
|
76
80
|
}
|
|
77
81
|
</script>
|
|
78
82
|
|
|
79
83
|
<template>
|
|
80
84
|
<SliderRoot
|
|
81
|
-
v-bind="rootProps"
|
|
85
|
+
v-bind="{ ...rootProps, ...ariaAttrs, id, name, disabled }"
|
|
82
86
|
v-model="sliderValue"
|
|
83
|
-
:name="props.name"
|
|
84
|
-
:disabled="props.disabled"
|
|
85
87
|
:class="style.root({ class: [props.class, props.ui?.root] })"
|
|
86
88
|
:default-value="defaultSliderValue"
|
|
87
89
|
:data-steps="thumbsCount"
|