@nuxt/ui 3.0.2 → 3.1.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/.nuxt/ui/accordion.ts +25 -4
- package/.nuxt/ui/alert.ts +52 -31
- package/.nuxt/ui/avatar-group.ts +24 -3
- package/.nuxt/ui/avatar.ts +26 -5
- package/.nuxt/ui/badge.ts +56 -35
- package/.nuxt/ui/breadcrumb.ts +28 -7
- package/.nuxt/ui/button-group.ts +23 -2
- package/.nuxt/ui/button.ts +66 -45
- package/.nuxt/ui/calendar.ts +39 -18
- package/.nuxt/ui/card.ts +28 -7
- package/.nuxt/ui/carousel.ts +29 -8
- package/.nuxt/ui/checkbox-group.ts +82 -0
- package/.nuxt/ui/checkbox.ts +163 -29
- package/.nuxt/ui/chip.ts +31 -10
- package/.nuxt/ui/collapsible.ts +23 -2
- package/.nuxt/ui/color-picker.ts +26 -5
- package/.nuxt/ui/command-palette.ts +37 -16
- package/.nuxt/ui/container.ts +23 -2
- package/.nuxt/ui/context-menu.ts +56 -35
- package/.nuxt/ui/drawer.ts +33 -12
- package/.nuxt/ui/dropdown-menu.ts +57 -36
- package/.nuxt/ui/form-field.ts +29 -8
- package/.nuxt/ui/form.ts +23 -2
- package/.nuxt/ui/index.ts +1 -0
- package/.nuxt/ui/input-menu.ts +65 -44
- package/.nuxt/ui/input-number.ts +43 -22
- package/.nuxt/ui/input.ts +46 -25
- package/.nuxt/ui/kbd.ts +27 -6
- package/.nuxt/ui/link.ts +26 -5
- package/.nuxt/ui/modal.ts +28 -7
- package/.nuxt/ui/navigation-menu.ts +102 -83
- package/.nuxt/ui/pagination.ts +23 -2
- package/.nuxt/ui/pin-input.ts +43 -22
- package/.nuxt/ui/popover.ts +25 -4
- package/.nuxt/ui/progress.ts +40 -19
- package/.nuxt/ui/radio-group.ts +273 -37
- package/.nuxt/ui/select-menu.ts +59 -35
- package/.nuxt/ui/select.ts +55 -34
- package/.nuxt/ui/separator.ts +31 -10
- package/.nuxt/ui/skeleton.ts +24 -3
- package/.nuxt/ui/slideover.ts +27 -6
- package/.nuxt/ui/slider.ts +39 -18
- package/.nuxt/ui/stepper.ts +41 -20
- package/.nuxt/ui/switch.ts +43 -22
- package/.nuxt/ui/table.ts +38 -17
- package/.nuxt/ui/tabs.ts +55 -34
- package/.nuxt/ui/textarea.ts +63 -37
- package/.nuxt/ui/toast.ts +47 -26
- package/.nuxt/ui/toaster.ts +23 -2
- package/.nuxt/ui/tooltip.ts +25 -4
- package/.nuxt/ui/tree.ts +41 -20
- package/.nuxt/ui.css +56 -12
- package/README.md +11 -0
- package/cli/templates.mjs +18 -17
- package/dist/module.json +5 -5
- package/dist/module.mjs +11 -7
- package/dist/runtime/components/Accordion.vue +36 -93
- package/dist/runtime/components/Accordion.vue.d.ts +91 -0
- package/dist/runtime/components/Alert.vue +37 -100
- package/dist/runtime/components/Alert.vue.d.ts +96 -0
- package/dist/runtime/components/App.vue +28 -34
- package/dist/runtime/components/App.vue.d.ts +24 -0
- package/dist/runtime/components/Avatar.vue +42 -75
- package/dist/runtime/components/Avatar.vue.d.ts +60 -0
- package/dist/runtime/components/AvatarGroup.vue +40 -77
- package/dist/runtime/components/AvatarGroup.vue.d.ts +40 -0
- package/dist/runtime/components/Badge.vue +33 -62
- package/dist/runtime/components/Badge.vue.d.ts +62 -0
- package/dist/runtime/components/Breadcrumb.vue +37 -90
- package/dist/runtime/components/Breadcrumb.vue.d.ts +82 -0
- package/dist/runtime/components/Button.vue +95 -104
- package/dist/runtime/components/Button.vue.d.ts +73 -0
- package/dist/runtime/components/ButtonGroup.vue +20 -46
- package/dist/runtime/components/ButtonGroup.vue.d.ts +55 -0
- package/dist/runtime/components/Calendar.vue +67 -150
- package/dist/runtime/components/Calendar.vue.d.ts +107 -0
- package/dist/runtime/components/Card.vue +18 -40
- package/dist/runtime/components/Card.vue.d.ts +38 -0
- package/dist/runtime/components/Carousel.vue +112 -234
- package/dist/runtime/components/Carousel.vue.d.ts +120 -0
- package/dist/runtime/components/Checkbox.vue +52 -93
- package/dist/runtime/components/Checkbox.vue.d.ts +76 -0
- package/dist/runtime/components/CheckboxGroup.vue +121 -0
- package/dist/runtime/components/CheckboxGroup.vue.d.ts +75 -0
- package/dist/runtime/components/Chip.vue +26 -69
- package/dist/runtime/components/Chip.vue.d.ts +71 -0
- package/dist/runtime/components/Collapsible.vue +22 -41
- package/dist/runtime/components/Collapsible.vue.d.ts +50 -0
- package/dist/runtime/components/ColorPicker.vue +111 -197
- package/dist/runtime/components/ColorPicker.vue.d.ts +63 -0
- package/dist/runtime/components/CommandPalette.vue +96 -237
- package/dist/runtime/components/CommandPalette.vue.d.ts +173 -0
- package/dist/runtime/components/Container.vue +15 -28
- package/dist/runtime/components/Container.vue.d.ts +27 -0
- package/dist/runtime/components/ContextMenu.vue +34 -133
- package/dist/runtime/components/ContextMenu.vue.d.ts +127 -0
- package/dist/runtime/components/ContextMenuContent.vue +73 -81
- package/dist/runtime/components/ContextMenuContent.vue.d.ts +105 -0
- package/dist/runtime/components/Drawer.vue +49 -83
- package/dist/runtime/components/Drawer.vue.d.ts +88 -0
- package/dist/runtime/components/DropdownMenu.vue +39 -142
- package/dist/runtime/components/DropdownMenu.vue.d.ts +141 -0
- package/dist/runtime/components/DropdownMenuContent.vue +78 -88
- package/dist/runtime/components/DropdownMenuContent.vue.d.ts +55 -0
- package/dist/runtime/components/Form.vue +135 -220
- package/dist/runtime/components/Form.vue.d.ts +66 -0
- package/dist/runtime/components/FormField.vue +35 -77
- package/dist/runtime/components/FormField.vue.d.ts +70 -0
- package/dist/runtime/components/Icon.vue +12 -19
- package/dist/runtime/components/Icon.vue.d.ts +17 -0
- package/dist/runtime/components/Input.vue +82 -140
- package/dist/runtime/components/Input.vue.d.ts +91 -0
- package/dist/runtime/components/InputMenu.vue +185 -332
- package/dist/runtime/components/InputMenu.vue.d.ts +312 -0
- package/dist/runtime/components/InputNumber.vue +71 -133
- package/dist/runtime/components/InputNumber.vue.d.ts +193 -0
- package/dist/runtime/components/Kbd.vue +20 -46
- package/dist/runtime/components/Kbd.vue.d.ts +55 -0
- package/dist/runtime/components/Link.vue +98 -176
- package/dist/runtime/components/Link.vue.d.ts +124 -0
- package/dist/runtime/components/LinkBase.vue +33 -42
- package/dist/runtime/components/LinkBase.vue.d.ts +48 -0
- package/dist/runtime/components/Modal.vue +53 -116
- package/dist/runtime/components/Modal.vue.d.ts +109 -0
- package/dist/runtime/components/NavigationMenu.vue +77 -209
- package/dist/runtime/components/NavigationMenu.vue.d.ts +159 -0
- package/dist/runtime/components/OverlayProvider.vue +14 -18
- package/dist/runtime/components/OverlayProvider.vue.d.ts +2 -0
- package/dist/runtime/components/Pagination.vue +46 -140
- package/dist/runtime/components/Pagination.vue.d.ts +143 -0
- package/dist/runtime/components/PinInput.vue +61 -78
- package/dist/runtime/components/PinInput.vue.d.ts +68 -0
- package/dist/runtime/components/Popover.vue +47 -84
- package/dist/runtime/components/Popover.vue.d.ts +80 -0
- package/dist/runtime/components/Progress.vue +70 -131
- package/dist/runtime/components/Progress.vue.d.ts +97 -0
- package/dist/runtime/components/RadioGroup.vue +70 -132
- package/dist/runtime/components/RadioGroup.vue.d.ts +88 -0
- package/dist/runtime/components/Select.vue +110 -224
- package/dist/runtime/components/Select.vue.d.ts +139 -0
- package/dist/runtime/components/SelectMenu.vue +161 -310
- package/dist/runtime/components/SelectMenu.vue.d.ts +184 -0
- package/dist/runtime/components/Separator.vue +29 -71
- package/dist/runtime/components/Separator.vue.d.ts +75 -0
- package/dist/runtime/components/Skeleton.vue +21 -23
- package/dist/runtime/components/Skeleton.vue.d.ts +26 -0
- package/dist/runtime/components/Slideover.vue +53 -120
- package/dist/runtime/components/Slideover.vue.d.ts +111 -0
- package/dist/runtime/components/Slider.vue +46 -84
- package/dist/runtime/components/Slider.vue.d.ts +71 -0
- package/dist/runtime/components/Stepper.vue +45 -115
- package/dist/runtime/components/Stepper.vue.d.ts +89 -0
- package/dist/runtime/components/Switch.vue +45 -93
- package/dist/runtime/components/Switch.vue.d.ts +73 -0
- package/dist/runtime/components/Table.vue +163 -267
- package/dist/runtime/components/Table.vue.d.ts +183 -0
- package/dist/runtime/components/Tabs.vue +41 -107
- package/dist/runtime/components/Tabs.vue.d.ts +104 -0
- package/dist/runtime/components/Textarea.vue +113 -158
- package/dist/runtime/components/Textarea.vue.d.ts +95 -0
- package/dist/runtime/components/Toast.vue +49 -110
- package/dist/runtime/components/Toast.vue.d.ts +95 -0
- package/dist/runtime/components/Toaster.vue +70 -107
- package/dist/runtime/components/Toaster.vue.d.ts +63 -0
- package/dist/runtime/components/Tooltip.vue +38 -65
- package/dist/runtime/components/Tooltip.vue.d.ts +65 -0
- package/dist/runtime/components/Tree.vue +59 -166
- package/dist/runtime/components/Tree.vue.d.ts +128 -0
- package/dist/runtime/composables/defineShortcuts.d.ts +1 -1
- package/dist/runtime/composables/useAvatarGroup.d.ts +1 -1
- package/dist/runtime/composables/useButtonGroup.d.ts +2 -2
- package/dist/runtime/composables/useFormField.d.ts +2 -2
- package/dist/runtime/composables/useOverlay.d.ts +14 -7
- package/dist/runtime/composables/useOverlay.js +14 -6
- package/dist/runtime/composables/usePortal.d.ts +6 -0
- package/dist/runtime/composables/usePortal.js +17 -0
- package/dist/runtime/index.css +1 -1
- package/dist/runtime/inertia/components/Link.vue +146 -0
- package/dist/runtime/inertia/components/Link.vue.d.ts +92 -0
- package/dist/runtime/inertia/stubs.d.ts +43 -0
- package/dist/runtime/inertia/stubs.js +82 -0
- package/dist/runtime/locale/bg.d.ts +3 -0
- package/dist/runtime/locale/bg.js +54 -0
- package/dist/runtime/locale/index.d.ts +5 -1
- package/dist/runtime/locale/index.js +5 -1
- package/dist/runtime/locale/kk.d.ts +3 -0
- package/dist/runtime/locale/kk.js +54 -0
- package/dist/runtime/locale/tj.d.ts +3 -0
- package/dist/runtime/locale/tj.js +54 -0
- package/dist/runtime/locale/ug_cn.d.ts +3 -0
- package/dist/runtime/locale/ug_cn.js +55 -0
- package/dist/runtime/types/form.d.ts +4 -1
- package/dist/runtime/types/index.d.ts +1 -0
- package/dist/runtime/types/index.js +1 -0
- package/dist/runtime/types/utils.d.ts +47 -7
- package/dist/runtime/utils/link.d.ts +3 -3
- package/dist/runtime/utils/link.js +1 -0
- package/dist/runtime/utils/tv.js +2 -2
- package/dist/runtime/vue/components/Icon.vue +7 -8
- package/dist/runtime/vue/components/Icon.vue.d.ts +14 -0
- package/dist/runtime/vue/components/Link.vue +118 -202
- package/dist/runtime/vue/components/Link.vue.d.ts +124 -0
- package/dist/runtime/vue/stubs.d.ts +2 -2
- package/dist/shared/{ui.BkNUP964.mjs → ui.D7lOOabO.mjs} +621 -362
- package/dist/types.d.mts +3 -5
- package/dist/unplugin.d.mts +4 -0
- package/dist/unplugin.mjs +25 -4
- package/dist/vite.mjs +1 -1
- package/package.json +94 -53
- package/dist/module.cjs +0 -62
- package/dist/module.d.cts +0 -45
- package/dist/module.d.ts +0 -45
- package/dist/shared/ui.BL-XB3u1.cjs +0 -3555
- package/dist/types.d.ts +0 -7
- package/dist/unplugin.cjs +0 -232
- package/dist/unplugin.d.cts +0 -62
- package/dist/unplugin.d.ts +0 -62
- package/dist/vite.cjs +0 -23
- package/dist/vite.d.cts +0 -15
- package/dist/vite.d.ts +0 -15
|
@@ -1,175 +1,69 @@
|
|
|
1
|
-
<script
|
|
2
|
-
import
|
|
3
|
-
import type { SelectRootProps, SelectRootEmits, SelectContentProps, SelectContentEmits, SelectArrowProps } from 'reka-ui'
|
|
4
|
-
import type { AppConfig } from '@nuxt/schema'
|
|
5
|
-
import _appConfig from '#build/app.config'
|
|
6
|
-
import theme from '#build/ui/select'
|
|
7
|
-
import type { UseComponentIconsProps } from '../composables/useComponentIcons'
|
|
8
|
-
import { tv } from '../utils/tv'
|
|
9
|
-
import type { AvatarProps, ChipProps, InputProps } from '../types'
|
|
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'
|
|
21
|
-
|
|
22
|
-
const appConfigSelect = _appConfig as AppConfig & { ui: { select: Partial<typeof theme> } }
|
|
23
|
-
|
|
24
|
-
const select = tv({ extend: tv(theme), ...(appConfigSelect.ui?.select || {}) })
|
|
25
|
-
|
|
26
|
-
interface SelectItemBase {
|
|
27
|
-
label?: string
|
|
28
|
-
/**
|
|
29
|
-
* @IconifyIcon
|
|
30
|
-
*/
|
|
31
|
-
icon?: string
|
|
32
|
-
avatar?: AvatarProps
|
|
33
|
-
chip?: ChipProps
|
|
34
|
-
/**
|
|
35
|
-
* The item type.
|
|
36
|
-
* @defaultValue 'item'
|
|
37
|
-
*/
|
|
38
|
-
type?: 'label' | 'separator' | 'item'
|
|
39
|
-
value?: string | number
|
|
40
|
-
disabled?: boolean
|
|
41
|
-
[key: string]: any
|
|
42
|
-
}
|
|
43
|
-
export type SelectItem = SelectItemBase | AcceptableValue | boolean
|
|
44
|
-
|
|
45
|
-
type SelectVariants = VariantProps<typeof select>
|
|
46
|
-
|
|
47
|
-
export interface SelectProps<T extends ArrayOrNested<SelectItem> = ArrayOrNested<SelectItem>, VK extends GetItemKeys<T> = 'value', M extends boolean = false> extends Omit<SelectRootProps<T>, 'dir' | 'multiple' | 'modelValue' | 'defaultValue' | 'by'>, UseComponentIconsProps {
|
|
48
|
-
id?: string
|
|
49
|
-
/** The placeholder text when the select is empty. */
|
|
50
|
-
placeholder?: string
|
|
51
|
-
/**
|
|
52
|
-
* @defaultValue 'primary'
|
|
53
|
-
*/
|
|
54
|
-
color?: SelectVariants['color']
|
|
55
|
-
/**
|
|
56
|
-
* @defaultValue 'outline'
|
|
57
|
-
*/
|
|
58
|
-
variant?: SelectVariants['variant']
|
|
59
|
-
/**
|
|
60
|
-
* @defaultValue 'md'
|
|
61
|
-
*/
|
|
62
|
-
size?: SelectVariants['size']
|
|
63
|
-
/**
|
|
64
|
-
* The icon displayed to open the menu.
|
|
65
|
-
* @defaultValue appConfig.ui.icons.chevronDown
|
|
66
|
-
* @IconifyIcon
|
|
67
|
-
*/
|
|
68
|
-
trailingIcon?: string
|
|
69
|
-
/**
|
|
70
|
-
* The icon displayed when an item is selected.
|
|
71
|
-
* @defaultValue appConfig.ui.icons.check
|
|
72
|
-
* @IconifyIcon
|
|
73
|
-
*/
|
|
74
|
-
selectedIcon?: string
|
|
75
|
-
/**
|
|
76
|
-
* The content of the menu.
|
|
77
|
-
* @defaultValue { side: 'bottom', sideOffset: 8, collisionPadding: 8, position: 'popper' }
|
|
78
|
-
*/
|
|
79
|
-
content?: Omit<SelectContentProps, 'as' | 'asChild' | 'forceMount'> & Partial<EmitsToProps<SelectContentEmits>>
|
|
80
|
-
/**
|
|
81
|
-
* Display an arrow alongside the menu.
|
|
82
|
-
* @defaultValue false
|
|
83
|
-
*/
|
|
84
|
-
arrow?: boolean | Omit<SelectArrowProps, 'as' | 'asChild'>
|
|
85
|
-
/**
|
|
86
|
-
* Render the menu in a portal.
|
|
87
|
-
* @defaultValue true
|
|
88
|
-
*/
|
|
89
|
-
portal?: boolean
|
|
90
|
-
/**
|
|
91
|
-
* When `items` is an array of objects, select the field to use as the value.
|
|
92
|
-
* @defaultValue 'value'
|
|
93
|
-
*/
|
|
94
|
-
valueKey?: VK
|
|
95
|
-
/**
|
|
96
|
-
* When `items` is an array of objects, select the field to use as the label.
|
|
97
|
-
* @defaultValue 'label'
|
|
98
|
-
*/
|
|
99
|
-
labelKey?: keyof NestedItem<T>
|
|
100
|
-
items?: T
|
|
101
|
-
/** The value of the Select when initially rendered. Use when you do not need to control the state of the Select. */
|
|
102
|
-
defaultValue?: GetModelValue<T, VK, M>
|
|
103
|
-
/** The controlled value of the Select. Can be bind as `v-model`. */
|
|
104
|
-
modelValue?: GetModelValue<T, VK, M>
|
|
105
|
-
/** Whether multiple options can be selected or not. */
|
|
106
|
-
multiple?: M & boolean
|
|
107
|
-
/** Highlight the ring color like a focus state. */
|
|
108
|
-
highlight?: boolean
|
|
109
|
-
class?: any
|
|
110
|
-
ui?: PartialString<typeof select.slots>
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
export type SelectEmits<A extends ArrayOrNested<SelectItem>, VK extends GetItemKeys<A> | undefined, M extends boolean> = Omit<SelectRootEmits, 'update:modelValue'> & {
|
|
114
|
-
change: [payload: Event]
|
|
115
|
-
blur: [payload: FocusEvent]
|
|
116
|
-
focus: [payload: FocusEvent]
|
|
117
|
-
} & GetModelValueEmits<A, VK, M>
|
|
118
|
-
|
|
119
|
-
type SlotProps<T extends SelectItem> = (props: { item: T, index: number }) => any
|
|
120
|
-
|
|
121
|
-
export interface SelectSlots<
|
|
122
|
-
A extends ArrayOrNested<SelectItem> = ArrayOrNested<SelectItem>,
|
|
123
|
-
VK extends GetItemKeys<A> | undefined = undefined,
|
|
124
|
-
M extends boolean = false,
|
|
125
|
-
T extends NestedItem<A> = NestedItem<A>
|
|
126
|
-
> {
|
|
127
|
-
'leading'(props: { modelValue?: GetModelValue<A, VK, M>, open: boolean, ui: ReturnType<typeof select> }): any
|
|
128
|
-
'default'(props: { modelValue?: GetModelValue<A, VK, M>, open: boolean }): any
|
|
129
|
-
'trailing'(props: { modelValue?: GetModelValue<A, VK, M>, open: boolean, ui: ReturnType<typeof select> }): any
|
|
130
|
-
'item': SlotProps<T>
|
|
131
|
-
'item-leading': SlotProps<T>
|
|
132
|
-
'item-label': SlotProps<T>
|
|
133
|
-
'item-trailing': SlotProps<T>
|
|
134
|
-
}
|
|
1
|
+
<script>
|
|
2
|
+
import theme from "#build/ui/select";
|
|
135
3
|
</script>
|
|
136
4
|
|
|
137
|
-
<script setup
|
|
138
|
-
import { computed, toRef } from
|
|
139
|
-
import { SelectRoot, SelectArrow, SelectTrigger, SelectPortal, SelectContent, SelectViewport, SelectLabel, SelectGroup, SelectItem, SelectItemIndicator, SelectItemText, SelectSeparator, useForwardPropsEmits } from
|
|
140
|
-
import { defu } from
|
|
141
|
-
import { reactivePick } from
|
|
142
|
-
import { useAppConfig } from
|
|
143
|
-
import { useButtonGroup } from
|
|
144
|
-
import { useComponentIcons } from
|
|
145
|
-
import { useFormField } from
|
|
146
|
-
import {
|
|
147
|
-
import
|
|
148
|
-
import
|
|
149
|
-
import
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
const props =
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
5
|
+
<script setup>
|
|
6
|
+
import { computed, toRef } from "vue";
|
|
7
|
+
import { SelectRoot, SelectArrow, SelectTrigger, SelectPortal, SelectContent, SelectViewport, SelectLabel, SelectGroup, SelectItem, SelectItemIndicator, SelectItemText, SelectSeparator, useForwardPropsEmits } from "reka-ui";
|
|
8
|
+
import { defu } from "defu";
|
|
9
|
+
import { reactivePick } from "@vueuse/core";
|
|
10
|
+
import { useAppConfig } from "#imports";
|
|
11
|
+
import { useButtonGroup } from "../composables/useButtonGroup";
|
|
12
|
+
import { useComponentIcons } from "../composables/useComponentIcons";
|
|
13
|
+
import { useFormField } from "../composables/useFormField";
|
|
14
|
+
import { usePortal } from "../composables/usePortal";
|
|
15
|
+
import { compare, get, isArrayOfArray } from "../utils";
|
|
16
|
+
import { tv } from "../utils/tv";
|
|
17
|
+
import UIcon from "./Icon.vue";
|
|
18
|
+
import UAvatar from "./Avatar.vue";
|
|
19
|
+
import UChip from "./Chip.vue";
|
|
20
|
+
defineOptions({ inheritAttrs: false });
|
|
21
|
+
const props = defineProps({
|
|
22
|
+
id: { type: String, required: false },
|
|
23
|
+
placeholder: { type: String, required: false },
|
|
24
|
+
color: { type: null, required: false },
|
|
25
|
+
variant: { type: null, required: false },
|
|
26
|
+
size: { type: null, required: false },
|
|
27
|
+
trailingIcon: { type: String, required: false },
|
|
28
|
+
selectedIcon: { type: String, required: false },
|
|
29
|
+
content: { type: Object, required: false },
|
|
30
|
+
arrow: { type: [Boolean, Object], required: false },
|
|
31
|
+
portal: { type: [Boolean, String], required: false, skipCheck: true, default: true },
|
|
32
|
+
valueKey: { type: null, required: false, default: "value" },
|
|
33
|
+
labelKey: { type: null, required: false, default: "label" },
|
|
34
|
+
items: { type: null, required: false },
|
|
35
|
+
defaultValue: { type: null, required: false },
|
|
36
|
+
modelValue: { type: null, required: false },
|
|
37
|
+
multiple: { type: Boolean, required: false },
|
|
38
|
+
highlight: { type: Boolean, required: false },
|
|
39
|
+
class: { type: null, required: false },
|
|
40
|
+
ui: { type: null, required: false },
|
|
41
|
+
open: { type: Boolean, required: false },
|
|
42
|
+
defaultOpen: { type: Boolean, required: false },
|
|
43
|
+
autocomplete: { type: String, required: false },
|
|
44
|
+
disabled: { type: Boolean, required: false },
|
|
45
|
+
name: { type: String, required: false },
|
|
46
|
+
required: { type: Boolean, required: false },
|
|
47
|
+
icon: { type: String, required: false },
|
|
48
|
+
avatar: { type: Object, required: false },
|
|
49
|
+
leading: { type: Boolean, required: false },
|
|
50
|
+
leadingIcon: { type: String, required: false },
|
|
51
|
+
trailing: { type: Boolean, required: false },
|
|
52
|
+
loading: { type: Boolean, required: false },
|
|
53
|
+
loadingIcon: { type: String, required: false }
|
|
54
|
+
});
|
|
55
|
+
const emits = defineEmits(["update:open", "change", "blur", "focus", "update:modelValue"]);
|
|
56
|
+
const slots = defineSlots();
|
|
57
|
+
const appConfig = useAppConfig();
|
|
58
|
+
const rootProps = useForwardPropsEmits(reactivePick(props, "open", "defaultOpen", "disabled", "autocomplete", "required", "multiple"), emits);
|
|
59
|
+
const portalProps = usePortal(toRef(() => props.portal));
|
|
60
|
+
const contentProps = toRef(() => defu(props.content, { side: "bottom", sideOffset: 8, collisionPadding: 8, position: "popper" }));
|
|
61
|
+
const arrowProps = toRef(() => props.arrow);
|
|
62
|
+
const { emitFormChange, emitFormInput, emitFormBlur, emitFormFocus, size: formGroupSize, color, id, name, highlight, disabled, ariaAttrs } = useFormField(props);
|
|
63
|
+
const { orientation, size: buttonGroupSize } = useButtonGroup(props);
|
|
64
|
+
const { isLeading, isTrailing, leadingIconName, trailingIconName } = useComponentIcons(toRef(() => defu(props, { trailingIcon: appConfig.ui.icons.chevronDown })));
|
|
65
|
+
const selectSize = computed(() => buttonGroupSize.value || formGroupSize.value);
|
|
66
|
+
const ui = computed(() => tv({ extend: tv(theme), ...appConfig.ui?.select || {} })({
|
|
173
67
|
color: color.value,
|
|
174
68
|
variant: props.variant,
|
|
175
69
|
size: selectSize?.value,
|
|
@@ -178,53 +72,40 @@ const ui = computed(() => select({
|
|
|
178
72
|
leading: isLeading.value || !!props.avatar || !!slots.leading,
|
|
179
73
|
trailing: isTrailing.value || !!slots.trailing,
|
|
180
74
|
buttonGroup: orientation.value
|
|
181
|
-
}))
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
: [props.items]
|
|
188
|
-
: []
|
|
189
|
-
)
|
|
190
|
-
// eslint-disable-next-line vue/no-dupe-keys
|
|
191
|
-
const items = computed(() => groups.value.flatMap(group => group) as T[])
|
|
192
|
-
|
|
193
|
-
function displayValue(value?: GetItemValue<T, VK> | GetItemValue<T, VK>[]): string {
|
|
75
|
+
}));
|
|
76
|
+
const groups = computed(
|
|
77
|
+
() => props.items?.length ? isArrayOfArray(props.items) ? props.items : [props.items] : []
|
|
78
|
+
);
|
|
79
|
+
const items = computed(() => groups.value.flatMap((group) => group));
|
|
80
|
+
function displayValue(value) {
|
|
194
81
|
if (props.multiple && Array.isArray(value)) {
|
|
195
|
-
return value.map(v => displayValue(v)).filter(Boolean).join(
|
|
82
|
+
return value.map((v) => displayValue(v)).filter(Boolean).join(", ");
|
|
196
83
|
}
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
return item && (typeof item === 'object' ? get(item, props.labelKey as string) : item)
|
|
84
|
+
const item = items.value.find((item2) => compare(typeof item2 === "object" ? get(item2, props.valueKey) : item2, value));
|
|
85
|
+
return item && (typeof item === "object" ? get(item, props.labelKey) : item);
|
|
200
86
|
}
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
emitFormChange()
|
|
208
|
-
emitFormInput()
|
|
87
|
+
function onUpdate(value) {
|
|
88
|
+
const event = new Event("change", { target: { value } });
|
|
89
|
+
emits("change", event);
|
|
90
|
+
emitFormChange();
|
|
91
|
+
emitFormInput();
|
|
209
92
|
}
|
|
210
|
-
function onUpdateOpen(value
|
|
93
|
+
function onUpdateOpen(value) {
|
|
211
94
|
if (!value) {
|
|
212
|
-
const event = new FocusEvent(
|
|
213
|
-
emits(
|
|
214
|
-
emitFormBlur()
|
|
95
|
+
const event = new FocusEvent("blur");
|
|
96
|
+
emits("blur", event);
|
|
97
|
+
emitFormBlur();
|
|
215
98
|
} else {
|
|
216
|
-
const event = new FocusEvent(
|
|
217
|
-
emits(
|
|
218
|
-
emitFormFocus()
|
|
99
|
+
const event = new FocusEvent("focus");
|
|
100
|
+
emits("focus", event);
|
|
101
|
+
emitFormFocus();
|
|
219
102
|
}
|
|
220
103
|
}
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
return typeof item === 'object' && item !== null
|
|
104
|
+
function isSelectItem(item) {
|
|
105
|
+
return typeof item === "object" && item !== null;
|
|
224
106
|
}
|
|
225
107
|
</script>
|
|
226
108
|
|
|
227
|
-
<!-- eslint-disable vue/no-template-shadow -->
|
|
228
109
|
<template>
|
|
229
110
|
<SelectRoot
|
|
230
111
|
v-slot="{ modelValue, open }"
|
|
@@ -232,44 +113,46 @@ function isSelectItem(item: SelectItem): item is SelectItemBase {
|
|
|
232
113
|
v-bind="rootProps"
|
|
233
114
|
:autocomplete="autocomplete"
|
|
234
115
|
:disabled="disabled"
|
|
235
|
-
:default-value="
|
|
236
|
-
:model-value="
|
|
116
|
+
:default-value="defaultValue"
|
|
117
|
+
:model-value="modelValue"
|
|
237
118
|
@update:model-value="onUpdate"
|
|
238
119
|
@update:open="onUpdateOpen"
|
|
239
120
|
>
|
|
240
121
|
<SelectTrigger :id="id" :class="ui.base({ class: [props.class, props.ui?.base] })" v-bind="{ ...$attrs, ...ariaAttrs }">
|
|
241
122
|
<span v-if="isLeading || !!avatar || !!slots.leading" :class="ui.leading({ class: props.ui?.leading })">
|
|
242
|
-
<slot name="leading" :model-value="
|
|
123
|
+
<slot name="leading" :model-value="modelValue" :open="open" :ui="ui">
|
|
243
124
|
<UIcon v-if="isLeading && leadingIconName" :name="leadingIconName" :class="ui.leadingIcon({ class: props.ui?.leadingIcon })" />
|
|
244
|
-
<UAvatar v-else-if="!!avatar" :size="
|
|
125
|
+
<UAvatar v-else-if="!!avatar" :size="props.ui?.itemLeadingAvatarSize || ui.itemLeadingAvatarSize()" v-bind="avatar" :class="ui.itemLeadingAvatar({ class: props.ui?.itemLeadingAvatar })" />
|
|
245
126
|
</slot>
|
|
246
127
|
</span>
|
|
247
128
|
|
|
248
|
-
<slot :model-value="
|
|
249
|
-
<template v-for="displayedModelValue in [displayValue(modelValue
|
|
129
|
+
<slot :model-value="modelValue" :open="open">
|
|
130
|
+
<template v-for="displayedModelValue in [displayValue(modelValue)]" :key="displayedModelValue">
|
|
250
131
|
<span v-if="displayedModelValue" :class="ui.value({ class: props.ui?.value })">
|
|
251
132
|
{{ displayedModelValue }}
|
|
252
133
|
</span>
|
|
253
134
|
<span v-else :class="ui.placeholder({ class: props.ui?.placeholder })">
|
|
254
|
-
{{ placeholder ?? '
|
|
135
|
+
{{ placeholder ?? '\xA0' }}
|
|
255
136
|
</span>
|
|
256
137
|
</template>
|
|
257
138
|
</slot>
|
|
258
139
|
|
|
259
140
|
<span v-if="isTrailing || !!slots.trailing" :class="ui.trailing({ class: props.ui?.trailing })">
|
|
260
|
-
<slot name="trailing" :model-value="
|
|
141
|
+
<slot name="trailing" :model-value="modelValue" :open="open" :ui="ui">
|
|
261
142
|
<UIcon v-if="trailingIconName" :name="trailingIconName" :class="ui.trailingIcon({ class: props.ui?.trailingIcon })" />
|
|
262
143
|
</slot>
|
|
263
144
|
</span>
|
|
264
145
|
</SelectTrigger>
|
|
265
146
|
|
|
266
|
-
<SelectPortal
|
|
147
|
+
<SelectPortal v-bind="portalProps">
|
|
267
148
|
<SelectContent :class="ui.content({ class: props.ui?.content })" v-bind="contentProps">
|
|
149
|
+
<slot name="content-top" />
|
|
150
|
+
|
|
268
151
|
<SelectViewport :class="ui.viewport({ class: props.ui?.viewport })">
|
|
269
152
|
<SelectGroup v-for="(group, groupIndex) in groups" :key="`group-${groupIndex}`" :class="ui.group({ class: props.ui?.group })">
|
|
270
153
|
<template v-for="(item, index) in group" :key="`group-${groupIndex}-${index}`">
|
|
271
154
|
<SelectLabel v-if="isSelectItem(item) && item.type === 'label'" :class="ui.label({ class: props.ui?.label })">
|
|
272
|
-
{{ get(item, props.labelKey
|
|
155
|
+
{{ get(item, props.labelKey) }}
|
|
273
156
|
</SelectLabel>
|
|
274
157
|
|
|
275
158
|
<SelectSeparator v-else-if="isSelectItem(item) && item.type === 'separator'" :class="ui.separator({ class: props.ui?.separator })" />
|
|
@@ -278,15 +161,16 @@ function isSelectItem(item: SelectItem): item is SelectItemBase {
|
|
|
278
161
|
v-else
|
|
279
162
|
:class="ui.item({ class: props.ui?.item })"
|
|
280
163
|
:disabled="isSelectItem(item) && item.disabled"
|
|
281
|
-
:value="isSelectItem(item) ? get(item, props.valueKey
|
|
164
|
+
:value="isSelectItem(item) ? get(item, props.valueKey) : item"
|
|
165
|
+
@select="isSelectItem(item) && item.onSelect?.($event)"
|
|
282
166
|
>
|
|
283
|
-
<slot name="item" :item="
|
|
284
|
-
<slot name="item-leading" :item="
|
|
167
|
+
<slot name="item" :item="item" :index="index">
|
|
168
|
+
<slot name="item-leading" :item="item" :index="index">
|
|
285
169
|
<UIcon v-if="isSelectItem(item) && item.icon" :name="item.icon" :class="ui.itemLeadingIcon({ class: props.ui?.itemLeadingIcon })" />
|
|
286
|
-
<UAvatar v-else-if="isSelectItem(item) && item.avatar" :size="
|
|
170
|
+
<UAvatar v-else-if="isSelectItem(item) && item.avatar" :size="props.ui?.itemLeadingAvatarSize || ui.itemLeadingAvatarSize()" v-bind="item.avatar" :class="ui.itemLeadingAvatar({ class: props.ui?.itemLeadingAvatar })" />
|
|
287
171
|
<UChip
|
|
288
172
|
v-else-if="isSelectItem(item) && item.chip"
|
|
289
|
-
:size="
|
|
173
|
+
:size="props.ui?.itemLeadingChipSize || ui.itemLeadingChipSize()"
|
|
290
174
|
inset
|
|
291
175
|
standalone
|
|
292
176
|
v-bind="item.chip"
|
|
@@ -295,13 +179,13 @@ function isSelectItem(item: SelectItem): item is SelectItemBase {
|
|
|
295
179
|
</slot>
|
|
296
180
|
|
|
297
181
|
<SelectItemText :class="ui.itemLabel({ class: props.ui?.itemLabel })">
|
|
298
|
-
<slot name="item-label" :item="
|
|
299
|
-
{{ isSelectItem(item) ? get(item, props.labelKey
|
|
182
|
+
<slot name="item-label" :item="item" :index="index">
|
|
183
|
+
{{ isSelectItem(item) ? get(item, props.labelKey) : item }}
|
|
300
184
|
</slot>
|
|
301
185
|
</SelectItemText>
|
|
302
186
|
|
|
303
187
|
<span :class="ui.itemTrailing({ class: props.ui?.itemTrailing })">
|
|
304
|
-
<slot name="item-trailing" :item="
|
|
188
|
+
<slot name="item-trailing" :item="item" :index="index" />
|
|
305
189
|
|
|
306
190
|
<SelectItemIndicator as-child>
|
|
307
191
|
<UIcon :name="selectedIcon || appConfig.ui.icons.check" :class="ui.itemTrailingIcon({ class: props.ui?.itemTrailingIcon })" />
|
|
@@ -313,6 +197,8 @@ function isSelectItem(item: SelectItem): item is SelectItemBase {
|
|
|
313
197
|
</SelectGroup>
|
|
314
198
|
</SelectViewport>
|
|
315
199
|
|
|
200
|
+
<slot name="content-bottom" />
|
|
201
|
+
|
|
316
202
|
<SelectArrow v-if="!!arrow" v-bind="arrowProps" :class="ui.arrow({ class: props.ui?.arrow })" />
|
|
317
203
|
</SelectContent>
|
|
318
204
|
</SelectPortal>
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import type { SelectRootProps, SelectRootEmits, SelectContentProps, SelectContentEmits, SelectArrowProps } from 'reka-ui';
|
|
2
|
+
import type { AppConfig } from '@nuxt/schema';
|
|
3
|
+
import theme from '#build/ui/select';
|
|
4
|
+
import type { UseComponentIconsProps } from '../composables/useComponentIcons';
|
|
5
|
+
import type { AvatarProps, ChipProps } from '../types';
|
|
6
|
+
import type { AcceptableValue, ArrayOrNested, GetItemKeys, GetModelValue, GetModelValueEmits, NestedItem, EmitsToProps, ComponentConfig } from '../types/utils';
|
|
7
|
+
type Select = ComponentConfig<typeof theme, AppConfig, 'select'>;
|
|
8
|
+
interface SelectItemBase {
|
|
9
|
+
label?: string;
|
|
10
|
+
/**
|
|
11
|
+
* @IconifyIcon
|
|
12
|
+
*/
|
|
13
|
+
icon?: string;
|
|
14
|
+
avatar?: AvatarProps;
|
|
15
|
+
chip?: ChipProps;
|
|
16
|
+
/**
|
|
17
|
+
* The item type.
|
|
18
|
+
* @defaultValue 'item'
|
|
19
|
+
*/
|
|
20
|
+
type?: 'label' | 'separator' | 'item';
|
|
21
|
+
value?: string | number;
|
|
22
|
+
disabled?: boolean;
|
|
23
|
+
onSelect?(e?: Event): void;
|
|
24
|
+
[key: string]: any;
|
|
25
|
+
}
|
|
26
|
+
export type SelectItem = SelectItemBase | AcceptableValue | boolean;
|
|
27
|
+
export interface SelectProps<T extends ArrayOrNested<SelectItem> = ArrayOrNested<SelectItem>, VK extends GetItemKeys<T> = 'value', M extends boolean = false> extends Omit<SelectRootProps<T>, 'dir' | 'multiple' | 'modelValue' | 'defaultValue' | 'by'>, UseComponentIconsProps {
|
|
28
|
+
id?: string;
|
|
29
|
+
/** The placeholder text when the select is empty. */
|
|
30
|
+
placeholder?: string;
|
|
31
|
+
/**
|
|
32
|
+
* @defaultValue 'primary'
|
|
33
|
+
*/
|
|
34
|
+
color?: Select['variants']['color'];
|
|
35
|
+
/**
|
|
36
|
+
* @defaultValue 'outline'
|
|
37
|
+
*/
|
|
38
|
+
variant?: Select['variants']['variant'];
|
|
39
|
+
/**
|
|
40
|
+
* @defaultValue 'md'
|
|
41
|
+
*/
|
|
42
|
+
size?: Select['variants']['size'];
|
|
43
|
+
/**
|
|
44
|
+
* The icon displayed to open the menu.
|
|
45
|
+
* @defaultValue appConfig.ui.icons.chevronDown
|
|
46
|
+
* @IconifyIcon
|
|
47
|
+
*/
|
|
48
|
+
trailingIcon?: string;
|
|
49
|
+
/**
|
|
50
|
+
* The icon displayed when an item is selected.
|
|
51
|
+
* @defaultValue appConfig.ui.icons.check
|
|
52
|
+
* @IconifyIcon
|
|
53
|
+
*/
|
|
54
|
+
selectedIcon?: string;
|
|
55
|
+
/**
|
|
56
|
+
* The content of the menu.
|
|
57
|
+
* @defaultValue { side: 'bottom', sideOffset: 8, collisionPadding: 8, position: 'popper' }
|
|
58
|
+
*/
|
|
59
|
+
content?: Omit<SelectContentProps, 'as' | 'asChild' | 'forceMount'> & Partial<EmitsToProps<SelectContentEmits>>;
|
|
60
|
+
/**
|
|
61
|
+
* Display an arrow alongside the menu.
|
|
62
|
+
* @defaultValue false
|
|
63
|
+
*/
|
|
64
|
+
arrow?: boolean | Omit<SelectArrowProps, 'as' | 'asChild'>;
|
|
65
|
+
/**
|
|
66
|
+
* Render the menu in a portal.
|
|
67
|
+
* @defaultValue true
|
|
68
|
+
*/
|
|
69
|
+
portal?: boolean | string | HTMLElement;
|
|
70
|
+
/**
|
|
71
|
+
* When `items` is an array of objects, select the field to use as the value.
|
|
72
|
+
* @defaultValue 'value'
|
|
73
|
+
*/
|
|
74
|
+
valueKey?: VK;
|
|
75
|
+
/**
|
|
76
|
+
* When `items` is an array of objects, select the field to use as the label.
|
|
77
|
+
* @defaultValue 'label'
|
|
78
|
+
*/
|
|
79
|
+
labelKey?: keyof NestedItem<T>;
|
|
80
|
+
items?: T;
|
|
81
|
+
/** The value of the Select when initially rendered. Use when you do not need to control the state of the Select. */
|
|
82
|
+
defaultValue?: GetModelValue<T, VK, M>;
|
|
83
|
+
/** The controlled value of the Select. Can be bind as `v-model`. */
|
|
84
|
+
modelValue?: GetModelValue<T, VK, M>;
|
|
85
|
+
/** Whether multiple options can be selected or not. */
|
|
86
|
+
multiple?: M & boolean;
|
|
87
|
+
/** Highlight the ring color like a focus state. */
|
|
88
|
+
highlight?: boolean;
|
|
89
|
+
class?: any;
|
|
90
|
+
ui?: Select['slots'];
|
|
91
|
+
}
|
|
92
|
+
export type SelectEmits<A extends ArrayOrNested<SelectItem>, VK extends GetItemKeys<A> | undefined, M extends boolean> = Omit<SelectRootEmits, 'update:modelValue'> & {
|
|
93
|
+
change: [payload: Event];
|
|
94
|
+
blur: [payload: FocusEvent];
|
|
95
|
+
focus: [payload: FocusEvent];
|
|
96
|
+
} & GetModelValueEmits<A, VK, M>;
|
|
97
|
+
type SlotProps<T extends SelectItem> = (props: {
|
|
98
|
+
item: T;
|
|
99
|
+
index: number;
|
|
100
|
+
}) => any;
|
|
101
|
+
export interface SelectSlots<A extends ArrayOrNested<SelectItem> = ArrayOrNested<SelectItem>, VK extends GetItemKeys<A> | undefined = undefined, M extends boolean = false, T extends NestedItem<A> = NestedItem<A>> {
|
|
102
|
+
'leading'(props: {
|
|
103
|
+
modelValue?: GetModelValue<A, VK, M>;
|
|
104
|
+
open: boolean;
|
|
105
|
+
ui: {
|
|
106
|
+
[K in keyof Required<Select['slots']>]: (props?: Record<string, any>) => string;
|
|
107
|
+
};
|
|
108
|
+
}): any;
|
|
109
|
+
'default'(props: {
|
|
110
|
+
modelValue?: GetModelValue<A, VK, M>;
|
|
111
|
+
open: boolean;
|
|
112
|
+
}): any;
|
|
113
|
+
'trailing'(props: {
|
|
114
|
+
modelValue?: GetModelValue<A, VK, M>;
|
|
115
|
+
open: boolean;
|
|
116
|
+
ui: {
|
|
117
|
+
[K in keyof Required<Select['slots']>]: (props?: Record<string, any>) => string;
|
|
118
|
+
};
|
|
119
|
+
}): any;
|
|
120
|
+
'item': SlotProps<T>;
|
|
121
|
+
'item-leading': SlotProps<T>;
|
|
122
|
+
'item-label': SlotProps<T>;
|
|
123
|
+
'item-trailing': SlotProps<T>;
|
|
124
|
+
'content-top': (props?: {}) => any;
|
|
125
|
+
'content-bottom': (props?: {}) => any;
|
|
126
|
+
}
|
|
127
|
+
declare const _default: <T extends ArrayOrNested<SelectItem>, VK extends GetItemKeys<T> = "value", M extends boolean = false>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_expose?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
|
|
128
|
+
props: __VLS_PrettifyLocal<any & SelectProps<T, VK, M> & Partial<{}>> & (import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps);
|
|
129
|
+
expose(exposed: import("vue").ShallowUnwrapRef<{}>): void;
|
|
130
|
+
attrs: any;
|
|
131
|
+
slots: Readonly<SelectSlots<T, VK, M, NestedItem<T>>> & SelectSlots<T, VK, M, NestedItem<T>>;
|
|
132
|
+
emit: ((evt: "blur", payload: FocusEvent) => void) & ((evt: "change", payload: Event) => void) & ((evt: "focus", payload: FocusEvent) => void) & ((evt: "update:open", value: boolean) => void) & ((evt: "update:modelValue", payload: GetModelValue<T, VK, M>) => void);
|
|
133
|
+
}>) => import("vue").VNode & {
|
|
134
|
+
__ctx?: Awaited<typeof __VLS_setup>;
|
|
135
|
+
};
|
|
136
|
+
export default _default;
|
|
137
|
+
type __VLS_PrettifyLocal<T> = {
|
|
138
|
+
[K in keyof T]: T[K];
|
|
139
|
+
} & {};
|