@nuxt/ui 3.0.1 → 3.0.2
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/.nuxt/ui/button.ts +36 -36
- package/.nuxt/ui/container.ts +1 -1
- package/.nuxt/ui/navigation-menu.ts +2 -2
- package/.nuxt/ui/switch.ts +1 -1
- package/.nuxt/ui/tabs.ts +1 -1
- package/dist/module.cjs +1 -1
- package/dist/module.d.cts +2 -1
- package/dist/module.d.mts +2 -1
- package/dist/module.d.ts +2 -1
- package/dist/module.json +1 -1
- package/dist/module.mjs +1 -1
- package/dist/runtime/components/Accordion.vue +9 -8
- package/dist/runtime/components/Alert.vue +1 -1
- package/dist/runtime/components/App.vue +1 -1
- package/dist/runtime/components/Avatar.vue +7 -5
- package/dist/runtime/components/Breadcrumb.vue +11 -10
- package/dist/runtime/components/Button.vue +1 -1
- package/dist/runtime/components/Calendar.vue +40 -11
- package/dist/runtime/components/Carousel.vue +7 -3
- package/dist/runtime/components/CommandPalette.vue +12 -11
- package/dist/runtime/components/ContextMenu.vue +24 -12
- package/dist/runtime/components/ContextMenuContent.vue +22 -15
- package/dist/runtime/components/Drawer.vue +1 -5
- package/dist/runtime/components/DropdownMenu.vue +23 -12
- package/dist/runtime/components/DropdownMenuContent.vue +22 -15
- package/dist/runtime/components/Form.vue +1 -0
- package/dist/runtime/components/FormField.vue +1 -0
- package/dist/runtime/components/InputMenu.vue +92 -54
- package/dist/runtime/components/Link.vue +3 -0
- package/dist/runtime/components/LinkBase.vue +1 -0
- package/dist/runtime/components/Modal.vue +1 -1
- package/dist/runtime/components/NavigationMenu.vue +49 -25
- package/dist/runtime/components/RadioGroup.vue +23 -12
- package/dist/runtime/components/Select.vue +69 -42
- package/dist/runtime/components/SelectMenu.vue +83 -48
- package/dist/runtime/components/Slideover.vue +1 -1
- package/dist/runtime/components/Stepper.vue +11 -10
- package/dist/runtime/components/Table.vue +7 -2
- package/dist/runtime/components/Tabs.vue +6 -5
- package/dist/runtime/components/Toast.vue +1 -1
- package/dist/runtime/components/Tree.vue +46 -32
- package/dist/runtime/composables/defineShortcuts.js +0 -1
- package/dist/runtime/composables/useFormField.js +1 -1
- package/dist/runtime/composables/useOverlay.d.ts +3 -2
- package/dist/runtime/locale/hy.d.ts +3 -0
- package/dist/runtime/locale/hy.js +54 -0
- package/dist/runtime/locale/index.d.ts +1 -0
- package/dist/runtime/locale/index.js +1 -0
- package/dist/runtime/types/form.d.ts +1 -0
- package/dist/runtime/types/index.d.ts +1 -0
- package/dist/runtime/types/index.js +1 -0
- package/dist/runtime/types/utils.d.ts +28 -8
- package/dist/runtime/utils/index.d.ts +1 -0
- package/dist/runtime/utils/index.js +3 -0
- package/dist/runtime/utils/link.d.ts +2 -25
- package/dist/runtime/utils/link.js +31 -1
- package/dist/runtime/vue/components/Link.vue +3 -0
- package/dist/runtime/vue/stubs.d.ts +7 -2
- package/dist/runtime/vue/stubs.js +11 -2
- package/dist/shared/{ui.C6uTSFTI.cjs → ui.BL-XB3u1.cjs} +16 -16
- package/dist/shared/{ui.BCaWD5Ek.mjs → ui.BkNUP964.mjs} +16 -16
- package/dist/types.d.mts +7 -1
- package/dist/types.d.ts +7 -1
- package/dist/unplugin.cjs +1 -1
- package/dist/unplugin.d.cts +2 -1
- package/dist/unplugin.d.mts +2 -1
- package/dist/unplugin.d.ts +2 -1
- package/dist/unplugin.mjs +1 -1
- package/dist/vite.cjs +1 -1
- package/dist/vite.mjs +1 -1
- package/package.json +39 -22
|
@@ -1,19 +1,29 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { VariantProps } from 'tailwind-variants'
|
|
3
|
-
import type { ComboboxRootProps, ComboboxRootEmits, ComboboxContentProps, ComboboxContentEmits, ComboboxArrowProps
|
|
3
|
+
import type { ComboboxRootProps, ComboboxRootEmits, ComboboxContentProps, ComboboxContentEmits, ComboboxArrowProps } from 'reka-ui'
|
|
4
4
|
import type { AppConfig } from '@nuxt/schema'
|
|
5
5
|
import _appConfig from '#build/app.config'
|
|
6
6
|
import theme from '#build/ui/select-menu'
|
|
7
7
|
import type { UseComponentIconsProps } from '../composables/useComponentIcons'
|
|
8
8
|
import { tv } from '../utils/tv'
|
|
9
9
|
import type { AvatarProps, ChipProps, InputProps } from '../types'
|
|
10
|
-
import type {
|
|
10
|
+
import type {
|
|
11
|
+
AcceptableValue,
|
|
12
|
+
ArrayOrNested,
|
|
13
|
+
GetItemKeys,
|
|
14
|
+
GetItemValue,
|
|
15
|
+
GetModelValue,
|
|
16
|
+
GetModelValueEmits,
|
|
17
|
+
NestedItem,
|
|
18
|
+
PartialString,
|
|
19
|
+
EmitsToProps
|
|
20
|
+
} from '../types/utils'
|
|
11
21
|
|
|
12
22
|
const appConfigSelectMenu = _appConfig as AppConfig & { ui: { selectMenu: Partial<typeof theme> } }
|
|
13
23
|
|
|
14
24
|
const selectMenu = tv({ extend: tv(theme), ...(appConfigSelectMenu.ui?.selectMenu || {}) })
|
|
15
25
|
|
|
16
|
-
|
|
26
|
+
interface _SelectMenuItem {
|
|
17
27
|
label?: string
|
|
18
28
|
/**
|
|
19
29
|
* @IconifyIcon
|
|
@@ -26,13 +36,16 @@ export interface SelectMenuItem {
|
|
|
26
36
|
* @defaultValue 'item'
|
|
27
37
|
*/
|
|
28
38
|
type?: 'label' | 'separator' | 'item'
|
|
39
|
+
value?: string | number
|
|
29
40
|
disabled?: boolean
|
|
30
41
|
onSelect?(e?: Event): void
|
|
42
|
+
[key: string]: any
|
|
31
43
|
}
|
|
44
|
+
export type SelectMenuItem = _SelectMenuItem | AcceptableValue | boolean
|
|
32
45
|
|
|
33
46
|
type SelectMenuVariants = VariantProps<typeof selectMenu>
|
|
34
47
|
|
|
35
|
-
export interface SelectMenuProps<T extends
|
|
48
|
+
export interface SelectMenuProps<T extends ArrayOrNested<SelectMenuItem> = ArrayOrNested<SelectMenuItem>, VK extends GetItemKeys<T> | undefined = undefined, M extends boolean = false> extends Pick<ComboboxRootProps<T>, 'open' | 'defaultOpen' | 'disabled' | 'name' | 'resetSearchTermOnBlur' | 'highlightOnHover'>, UseComponentIconsProps {
|
|
36
49
|
id?: string
|
|
37
50
|
/** The placeholder text when the select is empty. */
|
|
38
51
|
placeholder?: string
|
|
@@ -88,17 +101,17 @@ export interface SelectMenuProps<T extends MaybeArrayOfArrayItem<I>, I extends M
|
|
|
88
101
|
* When `items` is an array of objects, select the field to use as the value instead of the object itself.
|
|
89
102
|
* @defaultValue undefined
|
|
90
103
|
*/
|
|
91
|
-
valueKey?:
|
|
104
|
+
valueKey?: VK
|
|
92
105
|
/**
|
|
93
106
|
* When `items` is an array of objects, select the field to use as the label.
|
|
94
107
|
* @defaultValue 'label'
|
|
95
108
|
*/
|
|
96
|
-
labelKey?:
|
|
97
|
-
items?:
|
|
109
|
+
labelKey?: keyof NestedItem<T>
|
|
110
|
+
items?: T
|
|
98
111
|
/** The value of the SelectMenu when initially rendered. Use when you do not need to control the state of the SelectMenu. */
|
|
99
|
-
defaultValue?:
|
|
112
|
+
defaultValue?: GetModelValue<T, VK, M>
|
|
100
113
|
/** The controlled value of the SelectMenu. Can be binded-with with `v-model`. */
|
|
101
|
-
modelValue?:
|
|
114
|
+
modelValue?: GetModelValue<T, VK, M>
|
|
102
115
|
/** Whether multiple options can be selected or not. */
|
|
103
116
|
multiple?: M & boolean
|
|
104
117
|
/** Highlight the ring color like a focus state. */
|
|
@@ -122,19 +135,29 @@ export interface SelectMenuProps<T extends MaybeArrayOfArrayItem<I>, I extends M
|
|
|
122
135
|
ui?: PartialString<typeof selectMenu.slots>
|
|
123
136
|
}
|
|
124
137
|
|
|
125
|
-
export type SelectMenuEmits<
|
|
138
|
+
export type SelectMenuEmits<A extends ArrayOrNested<SelectMenuItem>, VK extends GetItemKeys<A> | undefined, M extends boolean> = Pick<ComboboxRootEmits, 'update:open'> & {
|
|
126
139
|
change: [payload: Event]
|
|
127
140
|
blur: [payload: FocusEvent]
|
|
128
141
|
focus: [payload: FocusEvent]
|
|
129
142
|
create: [item: string]
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
143
|
+
/** Event handler when highlighted element changes. */
|
|
144
|
+
highlight: [payload: {
|
|
145
|
+
ref: HTMLElement
|
|
146
|
+
value: GetModelValue<A, VK, M>
|
|
147
|
+
} | undefined]
|
|
148
|
+
} & GetModelValueEmits<A, VK, M>
|
|
149
|
+
|
|
150
|
+
type SlotProps<T extends SelectMenuItem> = (props: { item: T, index: number }) => any
|
|
151
|
+
|
|
152
|
+
export interface SelectMenuSlots<
|
|
153
|
+
A extends ArrayOrNested<SelectMenuItem> = ArrayOrNested<SelectMenuItem>,
|
|
154
|
+
VK extends GetItemKeys<A> | undefined = undefined,
|
|
155
|
+
M extends boolean = false,
|
|
156
|
+
T extends NestedItem<A> = NestedItem<A>
|
|
157
|
+
> {
|
|
158
|
+
'leading'(props: { modelValue?: GetModelValue<A, VK, M>, open: boolean, ui: ReturnType<typeof selectMenu> }): any
|
|
159
|
+
'default'(props: { modelValue?: GetModelValue<A, VK, M>, open: boolean }): any
|
|
160
|
+
'trailing'(props: { modelValue?: GetModelValue<A, VK, M>, open: boolean, ui: ReturnType<typeof selectMenu> }): any
|
|
138
161
|
'empty'(props: { searchTerm?: string }): any
|
|
139
162
|
'item': SlotProps<T>
|
|
140
163
|
'item-leading': SlotProps<T>
|
|
@@ -144,7 +167,7 @@ export interface SelectMenuSlots<T, M extends boolean> {
|
|
|
144
167
|
}
|
|
145
168
|
</script>
|
|
146
169
|
|
|
147
|
-
<script setup lang="ts" generic="T extends
|
|
170
|
+
<script setup lang="ts" generic="T extends ArrayOrNested<SelectMenuItem>, VK extends GetItemKeys<T> | undefined = undefined, M extends boolean = false">
|
|
148
171
|
import { computed, toRef, toRaw } from 'vue'
|
|
149
172
|
import { ComboboxRoot, ComboboxArrow, ComboboxAnchor, ComboboxInput, ComboboxTrigger, ComboboxPortal, ComboboxContent, ComboboxViewport, ComboboxEmpty, ComboboxGroup, ComboboxLabel, ComboboxSeparator, ComboboxItem, ComboboxItemIndicator, FocusScope, useForwardPropsEmits, useFilter } from 'reka-ui'
|
|
150
173
|
import { defu } from 'defu'
|
|
@@ -154,7 +177,7 @@ import { useButtonGroup } from '../composables/useButtonGroup'
|
|
|
154
177
|
import { useComponentIcons } from '../composables/useComponentIcons'
|
|
155
178
|
import { useFormField } from '../composables/useFormField'
|
|
156
179
|
import { useLocale } from '../composables/useLocale'
|
|
157
|
-
import { get,
|
|
180
|
+
import { compare, get, isArrayOfArray } from '../utils'
|
|
158
181
|
import UIcon from './Icon.vue'
|
|
159
182
|
import UAvatar from './Avatar.vue'
|
|
160
183
|
import UChip from './Chip.vue'
|
|
@@ -162,14 +185,14 @@ import UInput from './Input.vue'
|
|
|
162
185
|
|
|
163
186
|
defineOptions({ inheritAttrs: false })
|
|
164
187
|
|
|
165
|
-
const props = withDefaults(defineProps<SelectMenuProps<T,
|
|
188
|
+
const props = withDefaults(defineProps<SelectMenuProps<T, VK, M>>(), {
|
|
166
189
|
portal: true,
|
|
167
190
|
searchInput: true,
|
|
168
191
|
labelKey: 'label' as never,
|
|
169
192
|
resetSearchTermOnBlur: true
|
|
170
193
|
})
|
|
171
|
-
const emits = defineEmits<SelectMenuEmits<T,
|
|
172
|
-
const slots = defineSlots<SelectMenuSlots<T, M>>()
|
|
194
|
+
const emits = defineEmits<SelectMenuEmits<T, VK, M>>()
|
|
195
|
+
const slots = defineSlots<SelectMenuSlots<T, VK, M>>()
|
|
173
196
|
|
|
174
197
|
const searchTerm = defineModel<string>('searchTerm', { default: '' })
|
|
175
198
|
|
|
@@ -201,7 +224,7 @@ const ui = computed(() => selectMenu({
|
|
|
201
224
|
buttonGroup: orientation.value
|
|
202
225
|
}))
|
|
203
226
|
|
|
204
|
-
function displayValue(value: T | T[]): string {
|
|
227
|
+
function displayValue(value: GetItemValue<T, VK> | GetItemValue<T, VK>[]): string {
|
|
205
228
|
if (props.multiple && Array.isArray(value)) {
|
|
206
229
|
return value.map(v => displayValue(v)).filter(Boolean).join(', ')
|
|
207
230
|
}
|
|
@@ -214,7 +237,13 @@ function displayValue(value: T | T[]): string {
|
|
|
214
237
|
return item && (typeof item === 'object' ? get(item, props.labelKey as string) : item)
|
|
215
238
|
}
|
|
216
239
|
|
|
217
|
-
const groups = computed
|
|
240
|
+
const groups = computed<SelectMenuItem[][]>(() =>
|
|
241
|
+
props.items?.length
|
|
242
|
+
? isArrayOfArray(props.items)
|
|
243
|
+
? props.items
|
|
244
|
+
: [props.items]
|
|
245
|
+
: []
|
|
246
|
+
)
|
|
218
247
|
// eslint-disable-next-line vue/no-dupe-keys
|
|
219
248
|
const items = computed(() => groups.value.flatMap(group => group) as T[])
|
|
220
249
|
|
|
@@ -226,8 +255,8 @@ const filteredGroups = computed(() => {
|
|
|
226
255
|
const fields = Array.isArray(props.filterFields) ? props.filterFields : [props.labelKey] as string[]
|
|
227
256
|
|
|
228
257
|
return groups.value.map(items => items.filter((item) => {
|
|
229
|
-
if (typeof item !== 'object') {
|
|
230
|
-
return contains(item, searchTerm.value)
|
|
258
|
+
if (typeof item !== 'object' || item === null) {
|
|
259
|
+
return contains(String(item), searchTerm.value)
|
|
231
260
|
}
|
|
232
261
|
|
|
233
262
|
if (item.type && ['label', 'separator'].includes(item.type)) {
|
|
@@ -235,19 +264,21 @@ const filteredGroups = computed(() => {
|
|
|
235
264
|
}
|
|
236
265
|
|
|
237
266
|
return fields.some(field => contains(get(item, field), searchTerm.value))
|
|
238
|
-
})).filter(group => group.filter(item =>
|
|
267
|
+
})).filter(group => group.filter(item =>
|
|
268
|
+
!isSelectItem(item) || (!item.type || !['label', 'separator'].includes(item.type))
|
|
269
|
+
).length > 0)
|
|
239
270
|
})
|
|
240
|
-
const filteredItems = computed(() => filteredGroups.value.flatMap(group => group)
|
|
271
|
+
const filteredItems = computed(() => filteredGroups.value.flatMap(group => group))
|
|
241
272
|
|
|
242
273
|
const createItem = computed(() => {
|
|
243
274
|
if (!props.createItem || !searchTerm.value) {
|
|
244
275
|
return false
|
|
245
276
|
}
|
|
246
277
|
|
|
247
|
-
const newItem = props.valueKey ? { [props.valueKey]: searchTerm.value } as T : searchTerm.value
|
|
278
|
+
const newItem = props.valueKey ? { [props.valueKey]: searchTerm.value } as NestedItem<T> : searchTerm.value
|
|
248
279
|
|
|
249
280
|
if ((typeof props.createItem === 'object' && props.createItem.when === 'always') || props.createItem === 'always') {
|
|
250
|
-
return !filteredItems.value.find(item => compare(item, newItem, props.valueKey))
|
|
281
|
+
return !filteredItems.value.find(item => compare(item, newItem, String(props.valueKey)))
|
|
251
282
|
}
|
|
252
283
|
|
|
253
284
|
return !filteredItems.value.length
|
|
@@ -290,6 +321,10 @@ function onUpdateOpen(value: boolean) {
|
|
|
290
321
|
clearTimeout(timeoutId)
|
|
291
322
|
}
|
|
292
323
|
}
|
|
324
|
+
|
|
325
|
+
function isSelectItem(item: SelectMenuItem): item is _SelectMenuItem {
|
|
326
|
+
return typeof item === 'object' && item !== null
|
|
327
|
+
}
|
|
293
328
|
</script>
|
|
294
329
|
|
|
295
330
|
<!-- eslint-disable vue/no-template-shadow -->
|
|
@@ -324,14 +359,14 @@ function onUpdateOpen(value: boolean) {
|
|
|
324
359
|
<ComboboxAnchor as-child>
|
|
325
360
|
<ComboboxTrigger :class="ui.base({ class: [props.class, props.ui?.base] })" tabindex="0">
|
|
326
361
|
<span v-if="isLeading || !!avatar || !!slots.leading" :class="ui.leading({ class: props.ui?.leading })">
|
|
327
|
-
<slot name="leading" :model-value="(modelValue as
|
|
362
|
+
<slot name="leading" :model-value="(modelValue as GetModelValue<T, VK, M>)" :open="open" :ui="ui">
|
|
328
363
|
<UIcon v-if="isLeading && leadingIconName" :name="leadingIconName" :class="ui.leadingIcon({ class: props.ui?.leadingIcon })" />
|
|
329
364
|
<UAvatar v-else-if="!!avatar" :size="((props.ui?.itemLeadingAvatarSize || ui.itemLeadingAvatarSize()) as AvatarProps['size'])" v-bind="avatar" :class="ui.itemLeadingAvatar({ class: props.ui?.itemLeadingAvatar })" />
|
|
330
365
|
</slot>
|
|
331
366
|
</span>
|
|
332
367
|
|
|
333
|
-
<slot :model-value="(modelValue as
|
|
334
|
-
<template v-for="displayedModelValue in [displayValue(modelValue as
|
|
368
|
+
<slot :model-value="(modelValue as GetModelValue<T, VK, M>)" :open="open">
|
|
369
|
+
<template v-for="displayedModelValue in [displayValue(modelValue as GetModelValue<T, VK, M>)]" :key="displayedModelValue">
|
|
335
370
|
<span v-if="displayedModelValue" :class="ui.value({ class: props.ui?.value })">
|
|
336
371
|
{{ displayedModelValue }}
|
|
337
372
|
</span>
|
|
@@ -342,7 +377,7 @@ function onUpdateOpen(value: boolean) {
|
|
|
342
377
|
</slot>
|
|
343
378
|
|
|
344
379
|
<span v-if="isTrailing || !!slots.trailing" :class="ui.trailing({ class: props.ui?.trailing })">
|
|
345
|
-
<slot name="trailing" :model-value="(modelValue as
|
|
380
|
+
<slot name="trailing" :model-value="(modelValue as GetModelValue<T, VK, M>)" :open="open" :ui="ui">
|
|
346
381
|
<UIcon v-if="trailingIconName" :name="trailingIconName" :class="ui.trailingIcon({ class: props.ui?.trailingIcon })" />
|
|
347
382
|
</slot>
|
|
348
383
|
</span>
|
|
@@ -367,25 +402,25 @@ function onUpdateOpen(value: boolean) {
|
|
|
367
402
|
|
|
368
403
|
<ComboboxGroup v-for="(group, groupIndex) in filteredGroups" :key="`group-${groupIndex}`" :class="ui.group({ class: props.ui?.group })">
|
|
369
404
|
<template v-for="(item, index) in group" :key="`group-${groupIndex}-${index}`">
|
|
370
|
-
<ComboboxLabel v-if="item
|
|
405
|
+
<ComboboxLabel v-if="isSelectItem(item) && item.type === 'label'" :class="ui.label({ class: props.ui?.label })">
|
|
371
406
|
{{ get(item, props.labelKey as string) }}
|
|
372
407
|
</ComboboxLabel>
|
|
373
408
|
|
|
374
|
-
<ComboboxSeparator v-else-if="item
|
|
409
|
+
<ComboboxSeparator v-else-if="isSelectItem(item) && item.type === 'separator'" :class="ui.separator({ class: props.ui?.separator })" />
|
|
375
410
|
|
|
376
411
|
<ComboboxItem
|
|
377
412
|
v-else
|
|
378
413
|
:class="ui.item({ class: props.ui?.item })"
|
|
379
|
-
:disabled="item.disabled"
|
|
380
|
-
:value="valueKey &&
|
|
381
|
-
@select="item.onSelect"
|
|
414
|
+
:disabled="isSelectItem(item) && item.disabled"
|
|
415
|
+
:value="props.valueKey && isSelectItem(item) ? get(item, props.valueKey as string) : item"
|
|
416
|
+
@select="isSelectItem(item) && item.onSelect"
|
|
382
417
|
>
|
|
383
|
-
<slot name="item" :item="(item as T)" :index="index">
|
|
384
|
-
<slot name="item-leading" :item="(item as T)" :index="index">
|
|
385
|
-
<UIcon v-if="item.icon" :name="item.icon" :class="ui.itemLeadingIcon({ class: props.ui?.itemLeadingIcon })" />
|
|
386
|
-
<UAvatar v-else-if="item.avatar" :size="((props.ui?.itemLeadingAvatarSize || ui.itemLeadingAvatarSize()) as AvatarProps['size'])" v-bind="item.avatar" :class="ui.itemLeadingAvatar({ class: props.ui?.itemLeadingAvatar })" />
|
|
418
|
+
<slot name="item" :item="(item as NestedItem<T>)" :index="index">
|
|
419
|
+
<slot name="item-leading" :item="(item as NestedItem<T>)" :index="index">
|
|
420
|
+
<UIcon v-if="isSelectItem(item) && item.icon" :name="item.icon" :class="ui.itemLeadingIcon({ class: props.ui?.itemLeadingIcon })" />
|
|
421
|
+
<UAvatar v-else-if="isSelectItem(item) && item.avatar" :size="((props.ui?.itemLeadingAvatarSize || ui.itemLeadingAvatarSize()) as AvatarProps['size'])" v-bind="item.avatar" :class="ui.itemLeadingAvatar({ class: props.ui?.itemLeadingAvatar })" />
|
|
387
422
|
<UChip
|
|
388
|
-
v-else-if="item.chip"
|
|
423
|
+
v-else-if="isSelectItem(item) && item.chip"
|
|
389
424
|
:size="((props.ui?.itemLeadingChipSize || ui.itemLeadingChipSize()) as ChipProps['size'])"
|
|
390
425
|
inset
|
|
391
426
|
standalone
|
|
@@ -395,13 +430,13 @@ function onUpdateOpen(value: boolean) {
|
|
|
395
430
|
</slot>
|
|
396
431
|
|
|
397
432
|
<span :class="ui.itemLabel({ class: props.ui?.itemLabel })">
|
|
398
|
-
<slot name="item-label" :item="(item as T)" :index="index">
|
|
399
|
-
{{
|
|
433
|
+
<slot name="item-label" :item="(item as NestedItem<T>)" :index="index">
|
|
434
|
+
{{ isSelectItem(item) ? get(item, props.labelKey as string) : item }}
|
|
400
435
|
</slot>
|
|
401
436
|
</span>
|
|
402
437
|
|
|
403
438
|
<span :class="ui.itemTrailing({ class: props.ui?.itemTrailing })">
|
|
404
|
-
<slot name="item-trailing" :item="(item as T)" :index="index" />
|
|
439
|
+
<slot name="item-trailing" :item="(item as NestedItem<T>)" :index="index" />
|
|
405
440
|
|
|
406
441
|
<ComboboxItemIndicator as-child>
|
|
407
442
|
<UIcon :name="selectedIcon || appConfig.ui.icons.check" :class="ui.itemTrailingIcon({ class: props.ui?.itemTrailingIcon })" />
|
|
@@ -70,7 +70,7 @@ export interface SlideoverSlots {
|
|
|
70
70
|
header(props?: {}): any
|
|
71
71
|
title(props?: {}): any
|
|
72
72
|
description(props?: {}): any
|
|
73
|
-
close(props: { ui:
|
|
73
|
+
close(props: { ui: ReturnType<typeof slideover> }): any
|
|
74
74
|
body(props?: {}): any
|
|
75
75
|
footer(props?: {}): any
|
|
76
76
|
}
|
|
@@ -25,9 +25,10 @@ export interface StepperItem {
|
|
|
25
25
|
icon?: string
|
|
26
26
|
content?: string
|
|
27
27
|
disabled?: boolean
|
|
28
|
+
[key: string]: any
|
|
28
29
|
}
|
|
29
30
|
|
|
30
|
-
export interface StepperProps<T extends StepperItem> extends Pick<StepperRootProps, 'linear'> {
|
|
31
|
+
export interface StepperProps<T extends StepperItem = StepperItem> extends Pick<StepperRootProps, 'linear'> {
|
|
31
32
|
/**
|
|
32
33
|
* The element or component this component should render as.
|
|
33
34
|
* @defaultValue 'div'
|
|
@@ -56,19 +57,19 @@ export interface StepperProps<T extends StepperItem> extends Pick<StepperRootPro
|
|
|
56
57
|
class?: any
|
|
57
58
|
}
|
|
58
59
|
|
|
59
|
-
export type StepperEmits<T> = Omit<StepperRootEmits, 'update:modelValue'> & {
|
|
60
|
+
export type StepperEmits<T extends StepperItem = StepperItem> = Omit<StepperRootEmits, 'update:modelValue'> & {
|
|
60
61
|
next: [payload: T]
|
|
61
62
|
prev: [payload: T]
|
|
62
63
|
}
|
|
63
64
|
|
|
64
65
|
type SlotProps<T extends StepperItem> = (props: { item: T }) => any
|
|
65
66
|
|
|
66
|
-
export type StepperSlots<T extends StepperItem> = {
|
|
67
|
+
export type StepperSlots<T extends StepperItem = StepperItem> = {
|
|
67
68
|
indicator: SlotProps<T>
|
|
68
69
|
title: SlotProps<T>
|
|
69
70
|
description: SlotProps<T>
|
|
70
71
|
content: SlotProps<T>
|
|
71
|
-
} & DynamicSlots<T
|
|
72
|
+
} & DynamicSlots<T>
|
|
72
73
|
|
|
73
74
|
</script>
|
|
74
75
|
|
|
@@ -108,7 +109,7 @@ const currentStepIndex = computed({
|
|
|
108
109
|
}
|
|
109
110
|
})
|
|
110
111
|
|
|
111
|
-
const currentStep = computed(() => props.items?.[currentStepIndex.value]
|
|
112
|
+
const currentStep = computed(() => props.items?.[currentStepIndex.value])
|
|
112
113
|
const hasNext = computed(() => currentStepIndex.value < props.items?.length - 1)
|
|
113
114
|
const hasPrev = computed(() => currentStepIndex.value > 0)
|
|
114
115
|
|
|
@@ -116,13 +117,13 @@ defineExpose({
|
|
|
116
117
|
next() {
|
|
117
118
|
if (hasNext.value) {
|
|
118
119
|
currentStepIndex.value += 1
|
|
119
|
-
emits('next', currentStep.value)
|
|
120
|
+
emits('next', currentStep.value as T)
|
|
120
121
|
}
|
|
121
122
|
},
|
|
122
123
|
prev() {
|
|
123
124
|
if (hasPrev.value) {
|
|
124
125
|
currentStepIndex.value -= 1
|
|
125
|
-
emits('prev', currentStep.value)
|
|
126
|
+
emits('prev', currentStep.value as T)
|
|
126
127
|
}
|
|
127
128
|
},
|
|
128
129
|
hasNext,
|
|
@@ -173,10 +174,10 @@ defineExpose({
|
|
|
173
174
|
</StepperItem>
|
|
174
175
|
</div>
|
|
175
176
|
|
|
176
|
-
<div v-if="currentStep?.content || !!slots.content ||
|
|
177
|
+
<div v-if="currentStep?.content || !!slots.content || currentStep?.slot" :class="ui.content({ class: props.ui?.description })">
|
|
177
178
|
<slot
|
|
178
|
-
:name="
|
|
179
|
-
:item="currentStep"
|
|
179
|
+
:name="((currentStep?.slot || 'content') as keyof StepperSlots<T>)"
|
|
180
|
+
:item="(currentStep as Extract<T, { slot: string }>)"
|
|
180
181
|
>
|
|
181
182
|
{{ currentStep?.content }}
|
|
182
183
|
</slot>
|
|
@@ -75,6 +75,11 @@ export interface TableProps<T extends TableData> extends TableOptions<T> {
|
|
|
75
75
|
data?: T[]
|
|
76
76
|
columns?: TableColumn<T>[]
|
|
77
77
|
caption?: string
|
|
78
|
+
/**
|
|
79
|
+
* The text to display when the table is empty.
|
|
80
|
+
* @defaultValue t('table.noData')
|
|
81
|
+
*/
|
|
82
|
+
empty?: string
|
|
78
83
|
/**
|
|
79
84
|
* Whether the table should have a sticky header.
|
|
80
85
|
* @defaultValue false
|
|
@@ -308,7 +313,7 @@ defineExpose({
|
|
|
308
313
|
<template>
|
|
309
314
|
<Primitive :as="as" :class="ui.root({ class: [props.class, props.ui?.root] })">
|
|
310
315
|
<table :class="ui.base({ class: [props.ui?.base] })">
|
|
311
|
-
<caption v-if="caption" :class="ui.caption({ class: [props.ui?.caption] })">
|
|
316
|
+
<caption v-if="caption || !!slots.caption" :class="ui.caption({ class: [props.ui?.caption] })">
|
|
312
317
|
<slot name="caption">
|
|
313
318
|
{{ caption }}
|
|
314
319
|
</slot>
|
|
@@ -369,7 +374,7 @@ defineExpose({
|
|
|
369
374
|
<tr v-else>
|
|
370
375
|
<td :colspan="columns?.length" :class="ui.empty({ class: props.ui?.empty })">
|
|
371
376
|
<slot name="empty">
|
|
372
|
-
{{ t('table.noData') }}
|
|
377
|
+
{{ empty || t('table.noData') }}
|
|
373
378
|
</slot>
|
|
374
379
|
</td>
|
|
375
380
|
</tr>
|
|
@@ -25,11 +25,12 @@ export interface TabsItem {
|
|
|
25
25
|
/** A unique value for the tab item. Defaults to the index. */
|
|
26
26
|
value?: string | number
|
|
27
27
|
disabled?: boolean
|
|
28
|
+
[key: string]: any
|
|
28
29
|
}
|
|
29
30
|
|
|
30
31
|
type TabsVariants = VariantProps<typeof tabs>
|
|
31
32
|
|
|
32
|
-
export interface TabsProps<T> extends Pick<TabsRootProps<string | number>, 'defaultValue' | 'modelValue' | 'activationMode' | 'unmountOnHide'> {
|
|
33
|
+
export interface TabsProps<T extends TabsItem = TabsItem> extends Pick<TabsRootProps<string | number>, 'defaultValue' | 'modelValue' | 'activationMode' | 'unmountOnHide'> {
|
|
33
34
|
/**
|
|
34
35
|
* The element or component this component should render as.
|
|
35
36
|
* @defaultValue 'div'
|
|
@@ -69,14 +70,14 @@ export interface TabsProps<T> extends Pick<TabsRootProps<string | number>, 'defa
|
|
|
69
70
|
|
|
70
71
|
export interface TabsEmits extends TabsRootEmits<string | number> {}
|
|
71
72
|
|
|
72
|
-
type SlotProps<T> = (props: { item: T, index: number }) => any
|
|
73
|
+
type SlotProps<T extends TabsItem> = (props: { item: T, index: number }) => any
|
|
73
74
|
|
|
74
|
-
export type TabsSlots<T extends
|
|
75
|
+
export type TabsSlots<T extends TabsItem = TabsItem> = {
|
|
75
76
|
leading: SlotProps<T>
|
|
76
77
|
default: SlotProps<T>
|
|
77
78
|
trailing: SlotProps<T>
|
|
78
79
|
content: SlotProps<T>
|
|
79
|
-
} & DynamicSlots<T,
|
|
80
|
+
} & DynamicSlots<T, undefined, { index: number }>
|
|
80
81
|
|
|
81
82
|
</script>
|
|
82
83
|
|
|
@@ -129,7 +130,7 @@ const ui = computed(() => tabs({
|
|
|
129
130
|
|
|
130
131
|
<template v-if="!!content">
|
|
131
132
|
<TabsContent v-for="(item, index) of items" :key="index" :value="item.value || String(index)" :class="ui.content({ class: props.ui?.content })">
|
|
132
|
-
<slot :name="item.slot || 'content'" :item="item" :index="index">
|
|
133
|
+
<slot :name="((item.slot || 'content') as keyof TabsSlots<T>)" :item="(item as Extract<T, { slot: string; }>)" :index="index">
|
|
133
134
|
{{ item.content }}
|
|
134
135
|
</slot>
|
|
135
136
|
</TabsContent>
|