@nuxt/ui 2.8.1 → 2.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/module.d.mts +1411 -1092
- package/dist/module.d.ts +1411 -1092
- package/dist/module.json +1 -1
- package/dist/module.mjs +55 -11
- package/dist/runtime/components/data/Table.vue +47 -32
- package/dist/runtime/components/data/Table.vue.d.ts +22 -14
- package/dist/runtime/components/elements/Accordion.vue +33 -28
- package/dist/runtime/components/elements/Accordion.vue.d.ts +25 -18
- package/dist/runtime/components/elements/Alert.vue +22 -18
- package/dist/runtime/components/elements/Alert.vue.d.ts +26 -19
- package/dist/runtime/components/elements/Avatar.vue +22 -16
- package/dist/runtime/components/elements/Avatar.vue.d.ts +28 -19
- package/dist/runtime/components/elements/AvatarGroup.d.ts +17 -8
- package/dist/runtime/components/elements/AvatarGroup.mjs +18 -13
- package/dist/runtime/components/elements/Badge.vue +21 -17
- package/dist/runtime/components/elements/Badge.vue.d.ts +28 -19
- package/dist/runtime/components/elements/Button.vue +22 -18
- package/dist/runtime/components/elements/Button.vue.d.ts +28 -19
- package/dist/runtime/components/elements/ButtonGroup.d.ts +17 -8
- package/dist/runtime/components/elements/ButtonGroup.mjs +22 -15
- package/dist/runtime/components/elements/Dropdown.vue +45 -37
- package/dist/runtime/components/elements/Dropdown.vue.d.ts +22 -17
- package/dist/runtime/components/elements/Kbd.vue +16 -12
- package/dist/runtime/components/elements/Kbd.vue.d.ts +20 -12
- package/dist/runtime/components/elements/Link.vue +18 -5
- package/dist/runtime/components/elements/Meter.vue +166 -0
- package/dist/runtime/components/elements/Meter.vue.d.ts +123 -0
- package/dist/runtime/components/elements/MeterGroup.d.ts +78 -0
- package/dist/runtime/components/elements/MeterGroup.mjs +172 -0
- package/dist/runtime/components/elements/Progress.vue +284 -0
- package/dist/runtime/components/elements/Progress.vue.d.ts +2 -0
- package/dist/runtime/components/forms/Checkbox.vue +27 -17
- package/dist/runtime/components/forms/Checkbox.vue.d.ts +33 -15
- package/dist/runtime/components/forms/Form.vue +34 -9
- package/dist/runtime/components/forms/Form.vue.d.ts +2 -1
- package/dist/runtime/components/forms/FormGroup.vue +51 -27
- package/dist/runtime/components/forms/FormGroup.vue.d.ts +23 -15
- package/dist/runtime/components/forms/Input.vue +41 -29
- package/dist/runtime/components/forms/Input.vue.d.ts +51 -24
- package/dist/runtime/components/forms/Radio.vue +32 -21
- package/dist/runtime/components/forms/Radio.vue.d.ts +36 -18
- package/dist/runtime/components/forms/RadioGroup.vue +136 -0
- package/dist/runtime/components/forms/RadioGroup.vue.d.ts +118 -0
- package/dist/runtime/components/forms/Range.vue +26 -16
- package/dist/runtime/components/forms/Range.vue.d.ts +37 -18
- package/dist/runtime/components/forms/Select.vue +34 -26
- package/dist/runtime/components/forms/Select.vue.d.ts +42 -24
- package/dist/runtime/components/forms/SelectMenu.vue +104 -89
- package/dist/runtime/components/forms/SelectMenu.vue.d.ts +53 -33
- package/dist/runtime/components/forms/Textarea.vue +43 -31
- package/dist/runtime/components/forms/Textarea.vue.d.ts +50 -23
- package/dist/runtime/components/forms/Toggle.vue +26 -15
- package/dist/runtime/components/forms/Toggle.vue.d.ts +31 -12
- package/dist/runtime/components/layout/Card.vue +15 -10
- package/dist/runtime/components/layout/Card.vue.d.ts +17 -9
- package/dist/runtime/components/layout/Container.vue +15 -10
- package/dist/runtime/components/layout/Container.vue.d.ts +17 -9
- package/dist/runtime/components/layout/Divider.vue +107 -0
- package/dist/runtime/components/layout/Divider.vue.d.ts +82 -0
- package/dist/runtime/components/layout/Skeleton.vue +15 -10
- package/dist/runtime/components/layout/Skeleton.vue.d.ts +17 -9
- package/dist/runtime/components/navigation/CommandPalette.vue +57 -38
- package/dist/runtime/components/navigation/CommandPalette.vue.d.ts +24 -23
- package/dist/runtime/components/navigation/CommandPaletteGroup.vue +1 -1
- package/dist/runtime/components/navigation/CommandPaletteGroup.vue.d.ts +3 -4
- package/dist/runtime/components/navigation/Pagination.vue +129 -64
- package/dist/runtime/components/navigation/Pagination.vue.d.ts +70 -25
- package/dist/runtime/components/navigation/Tabs.vue +17 -14
- package/dist/runtime/components/navigation/Tabs.vue.d.ts +18 -11
- package/dist/runtime/components/navigation/VerticalNavigation.vue +15 -13
- package/dist/runtime/components/navigation/VerticalNavigation.vue.d.ts +20 -16
- package/dist/runtime/components/overlays/ContextMenu.vue +21 -11
- package/dist/runtime/components/overlays/ContextMenu.vue.d.ts +20 -11
- package/dist/runtime/components/overlays/Modal.vue +16 -14
- package/dist/runtime/components/overlays/Modal.vue.d.ts +18 -11
- package/dist/runtime/components/overlays/Notification.vue +25 -15
- package/dist/runtime/components/overlays/Notification.vue.d.ts +25 -19
- package/dist/runtime/components/overlays/Notifications.vue +19 -13
- package/dist/runtime/components/overlays/Notifications.vue.d.ts +22 -14
- package/dist/runtime/components/overlays/Popover.vue +39 -22
- package/dist/runtime/components/overlays/Popover.vue.d.ts +32 -11
- package/dist/runtime/components/overlays/Slideover.vue +15 -13
- package/dist/runtime/components/overlays/Slideover.vue.d.ts +18 -11
- package/dist/runtime/components/overlays/Tooltip.vue +31 -23
- package/dist/runtime/components/overlays/Tooltip.vue.d.ts +19 -11
- package/dist/runtime/composables/useFormGroup.d.ts +12 -2
- package/dist/runtime/composables/useFormGroup.mjs +21 -4
- package/dist/runtime/composables/usePopper.d.ts +3 -3
- package/dist/runtime/composables/usePopper.mjs +47 -31
- package/dist/runtime/composables/useToast.d.ts +3 -3
- package/dist/runtime/composables/useUI.d.ts +10 -0
- package/dist/runtime/composables/useUI.mjs +24 -0
- package/dist/runtime/types/avatar.d.ts +10 -4
- package/dist/runtime/types/badge.d.ts +14 -0
- package/dist/runtime/types/button.d.ts +10 -3
- package/dist/runtime/types/command-palette.d.ts +3 -1
- package/dist/runtime/types/form.d.ts +18 -4
- package/dist/runtime/types/index.d.ts +4 -0
- package/dist/runtime/types/link.d.ts +1 -0
- package/dist/runtime/types/meter.d.ts +5 -0
- package/dist/runtime/types/notification.d.ts +5 -3
- package/dist/runtime/types/popper.d.ts +1 -0
- package/dist/runtime/types/progress.d.ts +4 -0
- package/dist/runtime/types/tabs.d.ts +1 -0
- package/dist/runtime/types/utils.d.ts +11 -0
- package/dist/runtime/ui.config.d.ts +1470 -0
- package/dist/runtime/{app.config.mjs → ui.config.mjs} +313 -97
- package/dist/runtime/utils/index.d.ts +5 -11
- package/dist/runtime/utils/index.mjs +21 -9
- package/dist/runtime/utils/lodash.d.ts +2 -0
- package/dist/runtime/utils/lodash.mjs +23 -0
- package/dist/runtime/utils/uid.d.ts +1 -0
- package/dist/runtime/utils/uid.mjs +4 -0
- package/dist/types.d.mts +1 -1
- package/dist/types.d.ts +1 -1
- package/package.json +27 -29
- package/dist/runtime/app.config.d.ts +0 -1203
- package/dist/runtime/utils/StateEmitter.d.ts +0 -17
- package/dist/runtime/utils/StateEmitter.mjs +0 -21
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div :class="
|
|
2
|
+
<div :class="ui.wrapper">
|
|
3
3
|
<select
|
|
4
|
+
:id="inputId"
|
|
4
5
|
:name="name"
|
|
5
6
|
:value="modelValue"
|
|
6
7
|
:required="required"
|
|
@@ -53,14 +54,15 @@
|
|
|
53
54
|
</template>
|
|
54
55
|
|
|
55
56
|
<script>
|
|
56
|
-
import { computed, defineComponent } from "vue";
|
|
57
|
-
import { get, omit } from "lodash-es";
|
|
57
|
+
import { computed, toRef, defineComponent } from "vue";
|
|
58
58
|
import { twMerge, twJoin } from "tailwind-merge";
|
|
59
59
|
import UIcon from "../elements/Icon.vue";
|
|
60
|
-
import {
|
|
60
|
+
import { useUI } from "../../composables/useUI";
|
|
61
61
|
import { useFormGroup } from "../../composables/useFormGroup";
|
|
62
|
-
import {
|
|
62
|
+
import { mergeConfig, get } from "../../utils";
|
|
63
63
|
import appConfig from "#build/app.config";
|
|
64
|
+
import { select } from "#ui/ui.config";
|
|
65
|
+
const config = mergeConfig(appConfig.ui.strategy, appConfig.ui.select, select);
|
|
64
66
|
export default defineComponent({
|
|
65
67
|
components: {
|
|
66
68
|
UIcon
|
|
@@ -71,6 +73,10 @@ export default defineComponent({
|
|
|
71
73
|
type: [String, Number, Object],
|
|
72
74
|
default: ""
|
|
73
75
|
},
|
|
76
|
+
id: {
|
|
77
|
+
type: String,
|
|
78
|
+
default: null
|
|
79
|
+
},
|
|
74
80
|
name: {
|
|
75
81
|
type: String,
|
|
76
82
|
default: null
|
|
@@ -93,7 +99,7 @@ export default defineComponent({
|
|
|
93
99
|
},
|
|
94
100
|
loadingIcon: {
|
|
95
101
|
type: String,
|
|
96
|
-
default: () =>
|
|
102
|
+
default: () => config.default.loadingIcon
|
|
97
103
|
},
|
|
98
104
|
leadingIcon: {
|
|
99
105
|
type: String,
|
|
@@ -101,7 +107,7 @@ export default defineComponent({
|
|
|
101
107
|
},
|
|
102
108
|
trailingIcon: {
|
|
103
109
|
type: String,
|
|
104
|
-
default: () =>
|
|
110
|
+
default: () => config.default.trailingIcon
|
|
105
111
|
},
|
|
106
112
|
trailing: {
|
|
107
113
|
type: Boolean,
|
|
@@ -125,25 +131,25 @@ export default defineComponent({
|
|
|
125
131
|
},
|
|
126
132
|
size: {
|
|
127
133
|
type: String,
|
|
128
|
-
default:
|
|
134
|
+
default: null,
|
|
129
135
|
validator(value) {
|
|
130
|
-
return Object.keys(
|
|
136
|
+
return Object.keys(config.size).includes(value);
|
|
131
137
|
}
|
|
132
138
|
},
|
|
133
139
|
color: {
|
|
134
140
|
type: String,
|
|
135
|
-
default: () =>
|
|
141
|
+
default: () => config.default.color,
|
|
136
142
|
validator(value) {
|
|
137
|
-
return [...appConfig.ui.colors, ...Object.keys(
|
|
143
|
+
return [...appConfig.ui.colors, ...Object.keys(config.color)].includes(value);
|
|
138
144
|
}
|
|
139
145
|
},
|
|
140
146
|
variant: {
|
|
141
147
|
type: String,
|
|
142
|
-
default: () =>
|
|
148
|
+
default: () => config.default.variant,
|
|
143
149
|
validator(value) {
|
|
144
150
|
return [
|
|
145
|
-
...Object.keys(
|
|
146
|
-
...Object.values(
|
|
151
|
+
...Object.keys(config.variant),
|
|
152
|
+
...Object.values(config.color).flatMap((value2) => Object.keys(value2))
|
|
147
153
|
].includes(value);
|
|
148
154
|
}
|
|
149
155
|
},
|
|
@@ -159,18 +165,19 @@ export default defineComponent({
|
|
|
159
165
|
type: String,
|
|
160
166
|
default: null
|
|
161
167
|
},
|
|
168
|
+
class: {
|
|
169
|
+
type: [String, Object, Array],
|
|
170
|
+
default: void 0
|
|
171
|
+
},
|
|
162
172
|
ui: {
|
|
163
173
|
type: Object,
|
|
164
|
-
default:
|
|
174
|
+
default: void 0
|
|
165
175
|
}
|
|
166
176
|
},
|
|
167
177
|
emits: ["update:modelValue", "change"],
|
|
168
|
-
setup(props, { emit,
|
|
169
|
-
const
|
|
170
|
-
const
|
|
171
|
-
const { emitFormChange, formGroup } = useFormGroup();
|
|
172
|
-
const color = computed(() => formGroup?.error?.value ? "red" : props.color);
|
|
173
|
-
const size = computed(() => formGroup?.size?.value ?? props.size);
|
|
178
|
+
setup(props, { emit, slots }) {
|
|
179
|
+
const { ui, attrs } = useUI("select", toRef(props, "ui"), config, toRef(props, "class"));
|
|
180
|
+
const { emitFormChange, inputId, color, size, name } = useFormGroup(props, config);
|
|
174
181
|
const onInput = (event) => {
|
|
175
182
|
emit("update:modelValue", event.target.value);
|
|
176
183
|
};
|
|
@@ -221,7 +228,6 @@ export default defineComponent({
|
|
|
221
228
|
}
|
|
222
229
|
return foundOption[props.valueAttribute];
|
|
223
230
|
});
|
|
224
|
-
const wrapperClass = computed(() => twMerge(ui.value.wrapper, attrs.class));
|
|
225
231
|
const selectClass = computed(() => {
|
|
226
232
|
const variant = ui.value.color?.[color.value]?.[props.variant] || ui.value.variant[props.variant];
|
|
227
233
|
return twMerge(twJoin(
|
|
@@ -262,7 +268,7 @@ export default defineComponent({
|
|
|
262
268
|
const leadingIconClass = computed(() => {
|
|
263
269
|
return twJoin(
|
|
264
270
|
ui.value.icon.base,
|
|
265
|
-
|
|
271
|
+
appConfig.ui.colors.includes(color.value) && ui.value.icon.color.replaceAll("{color}", color.value),
|
|
266
272
|
ui.value.icon.size[size.value],
|
|
267
273
|
props.loading && "animate-spin"
|
|
268
274
|
);
|
|
@@ -277,20 +283,22 @@ export default defineComponent({
|
|
|
277
283
|
const trailingIconClass = computed(() => {
|
|
278
284
|
return twJoin(
|
|
279
285
|
ui.value.icon.base,
|
|
280
|
-
|
|
286
|
+
appConfig.ui.colors.includes(color.value) && ui.value.icon.color.replaceAll("{color}", color.value),
|
|
281
287
|
ui.value.icon.size[size.value],
|
|
282
288
|
props.loading && !isLeading.value && "animate-spin"
|
|
283
289
|
);
|
|
284
290
|
});
|
|
285
291
|
return {
|
|
286
|
-
attrs: omit(attrs, ["class"]),
|
|
287
292
|
// eslint-disable-next-line vue/no-dupe-keys
|
|
288
293
|
ui,
|
|
294
|
+
attrs,
|
|
295
|
+
// eslint-disable-next-line vue/no-dupe-keys
|
|
296
|
+
name,
|
|
297
|
+
inputId,
|
|
289
298
|
normalizedOptionsWithPlaceholder,
|
|
290
299
|
normalizedValue,
|
|
291
300
|
isLeading,
|
|
292
301
|
isTrailing,
|
|
293
|
-
wrapperClass,
|
|
294
302
|
// eslint-disable-next-line vue/no-dupe-keys
|
|
295
303
|
selectClass,
|
|
296
304
|
leadingIconName,
|
|
@@ -1,10 +1,13 @@
|
|
|
1
|
-
/// <reference types="lodash" />
|
|
2
1
|
import type { PropType, ComputedRef } from 'vue';
|
|
3
2
|
declare const _default: import("vue").DefineComponent<{
|
|
4
3
|
modelValue: {
|
|
5
|
-
type: (ObjectConstructor |
|
|
4
|
+
type: (ObjectConstructor | NumberConstructor | StringConstructor)[];
|
|
6
5
|
default: string;
|
|
7
6
|
};
|
|
7
|
+
id: {
|
|
8
|
+
type: StringConstructor;
|
|
9
|
+
default: null;
|
|
10
|
+
};
|
|
8
11
|
name: {
|
|
9
12
|
type: StringConstructor;
|
|
10
13
|
default: null;
|
|
@@ -58,17 +61,17 @@ declare const _default: import("vue").DefineComponent<{
|
|
|
58
61
|
default: () => never[];
|
|
59
62
|
};
|
|
60
63
|
size: {
|
|
61
|
-
type:
|
|
62
|
-
default:
|
|
64
|
+
type: PropType<string | number | symbol>;
|
|
65
|
+
default: null;
|
|
63
66
|
validator(value: string): boolean;
|
|
64
67
|
};
|
|
65
68
|
color: {
|
|
66
|
-
type:
|
|
69
|
+
type: PropType<any>;
|
|
67
70
|
default: () => any;
|
|
68
71
|
validator(value: string): boolean;
|
|
69
72
|
};
|
|
70
73
|
variant: {
|
|
71
|
-
type:
|
|
74
|
+
type: PropType<any>;
|
|
72
75
|
default: () => any;
|
|
73
76
|
validator(value: string): boolean;
|
|
74
77
|
};
|
|
@@ -84,15 +87,21 @@ declare const _default: import("vue").DefineComponent<{
|
|
|
84
87
|
type: StringConstructor;
|
|
85
88
|
default: null;
|
|
86
89
|
};
|
|
87
|
-
|
|
90
|
+
class: {
|
|
88
91
|
type: PropType<any>;
|
|
89
|
-
default:
|
|
92
|
+
default: undefined;
|
|
93
|
+
};
|
|
94
|
+
ui: {
|
|
95
|
+
type: PropType<Partial<any>>;
|
|
96
|
+
default: undefined;
|
|
90
97
|
};
|
|
91
98
|
}, {
|
|
92
|
-
attrs: import("lodash").Omit<{
|
|
93
|
-
[x: string]: unknown;
|
|
94
|
-
}, "class">;
|
|
95
99
|
ui: ComputedRef<any>;
|
|
100
|
+
attrs: ComputedRef<Pick<{
|
|
101
|
+
[x: string]: unknown;
|
|
102
|
+
}, string>>;
|
|
103
|
+
name: ComputedRef<string | undefined>;
|
|
104
|
+
inputId: import("vue").Ref<string | undefined>;
|
|
96
105
|
normalizedOptionsWithPlaceholder: ComputedRef<{
|
|
97
106
|
disabled?: boolean | undefined;
|
|
98
107
|
children: {
|
|
@@ -102,7 +111,6 @@ declare const _default: import("vue").DefineComponent<{
|
|
|
102
111
|
normalizedValue: ComputedRef<any>;
|
|
103
112
|
isLeading: ComputedRef<string | true>;
|
|
104
113
|
isTrailing: ComputedRef<string | true | undefined>;
|
|
105
|
-
wrapperClass: ComputedRef<string>;
|
|
106
114
|
selectClass: ComputedRef<string>;
|
|
107
115
|
leadingIconName: ComputedRef<string | undefined>;
|
|
108
116
|
leadingIconClass: ComputedRef<string>;
|
|
@@ -114,9 +122,13 @@ declare const _default: import("vue").DefineComponent<{
|
|
|
114
122
|
onChange: (event: Event) => void;
|
|
115
123
|
}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, ("change" | "update:modelValue")[], "change" | "update:modelValue", import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{
|
|
116
124
|
modelValue: {
|
|
117
|
-
type: (ObjectConstructor |
|
|
125
|
+
type: (ObjectConstructor | NumberConstructor | StringConstructor)[];
|
|
118
126
|
default: string;
|
|
119
127
|
};
|
|
128
|
+
id: {
|
|
129
|
+
type: StringConstructor;
|
|
130
|
+
default: null;
|
|
131
|
+
};
|
|
120
132
|
name: {
|
|
121
133
|
type: StringConstructor;
|
|
122
134
|
default: null;
|
|
@@ -170,17 +182,17 @@ declare const _default: import("vue").DefineComponent<{
|
|
|
170
182
|
default: () => never[];
|
|
171
183
|
};
|
|
172
184
|
size: {
|
|
173
|
-
type:
|
|
174
|
-
default:
|
|
185
|
+
type: PropType<string | number | symbol>;
|
|
186
|
+
default: null;
|
|
175
187
|
validator(value: string): boolean;
|
|
176
188
|
};
|
|
177
189
|
color: {
|
|
178
|
-
type:
|
|
190
|
+
type: PropType<any>;
|
|
179
191
|
default: () => any;
|
|
180
192
|
validator(value: string): boolean;
|
|
181
193
|
};
|
|
182
194
|
variant: {
|
|
183
|
-
type:
|
|
195
|
+
type: PropType<any>;
|
|
184
196
|
default: () => any;
|
|
185
197
|
validator(value: string): boolean;
|
|
186
198
|
};
|
|
@@ -196,25 +208,31 @@ declare const _default: import("vue").DefineComponent<{
|
|
|
196
208
|
type: StringConstructor;
|
|
197
209
|
default: null;
|
|
198
210
|
};
|
|
199
|
-
|
|
211
|
+
class: {
|
|
200
212
|
type: PropType<any>;
|
|
201
|
-
default:
|
|
213
|
+
default: undefined;
|
|
214
|
+
};
|
|
215
|
+
ui: {
|
|
216
|
+
type: PropType<Partial<any>>;
|
|
217
|
+
default: undefined;
|
|
202
218
|
};
|
|
203
219
|
}>> & {
|
|
204
220
|
"onUpdate:modelValue"?: ((...args: any[]) => any) | undefined;
|
|
205
221
|
onChange?: ((...args: any[]) => any) | undefined;
|
|
206
222
|
}, {
|
|
223
|
+
id: string;
|
|
207
224
|
icon: string;
|
|
208
|
-
color:
|
|
209
|
-
ui: any
|
|
210
|
-
name: string;
|
|
225
|
+
color: any;
|
|
226
|
+
ui: Partial<any>;
|
|
211
227
|
options: unknown[];
|
|
228
|
+
name: string;
|
|
229
|
+
class: any;
|
|
212
230
|
modelValue: string | number | Record<string, any>;
|
|
213
231
|
loading: boolean;
|
|
214
232
|
disabled: boolean;
|
|
215
|
-
variant:
|
|
233
|
+
variant: any;
|
|
216
234
|
required: boolean;
|
|
217
|
-
size: string;
|
|
235
|
+
size: string | number | symbol;
|
|
218
236
|
placeholder: string;
|
|
219
237
|
padded: boolean;
|
|
220
238
|
loadingIcon: string;
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
:multiple="multiple"
|
|
9
9
|
:disabled="disabled || loading"
|
|
10
10
|
as="div"
|
|
11
|
-
:class="
|
|
11
|
+
:class="ui.wrapper"
|
|
12
12
|
@update:model-value="onUpdate"
|
|
13
13
|
>
|
|
14
14
|
<input
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
class="inline-flex w-full"
|
|
29
29
|
>
|
|
30
30
|
<slot :open="open" :disabled="disabled" :loading="loading">
|
|
31
|
-
<button :class="selectClass" :disabled="disabled || loading" type="button" v-bind="attrs">
|
|
31
|
+
<button :id="inputId" :class="selectClass" :disabled="disabled || loading" type="button" v-bind="attrs">
|
|
32
32
|
<span v-if="(isLeading && leadingIconName) || $slots.leading" :class="leadingWrapperIconClass">
|
|
33
33
|
<slot name="leading" :disabled="disabled" :loading="loading">
|
|
34
34
|
<UIcon :name="leadingIconName" :class="leadingIconClass" />
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
|
|
38
38
|
<slot name="label">
|
|
39
39
|
<span v-if="multiple && Array.isArray(modelValue) && modelValue.length" class="block truncate">{{ modelValue.length }} selected</span>
|
|
40
|
-
<span v-else-if="!multiple && modelValue" class="block truncate">{{ typeof modelValue
|
|
40
|
+
<span v-else-if="!multiple && modelValue" class="block truncate">{{ ['string', 'number'].includes(typeof modelValue) ? modelValue : modelValue[optionAttribute] }}</span>
|
|
41
41
|
<span v-else class="block truncate" :class="uiMenu.placeholder">{{ placeholder || ' ' }}</span>
|
|
42
42
|
</slot>
|
|
43
43
|
|
|
@@ -52,71 +52,74 @@
|
|
|
52
52
|
|
|
53
53
|
<div v-if="open" ref="container" :class="[uiMenu.container, uiMenu.width]">
|
|
54
54
|
<Transition appear v-bind="uiMenu.transition">
|
|
55
|
-
<
|
|
56
|
-
<
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
<
|
|
81
|
-
v-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
55
|
+
<div>
|
|
56
|
+
<div v-if="popper.arrow" data-popper-arrow :class="['invisible before:visible before:block before:rotate-45 before:z-[-1]', Object.values(uiMenu.arrow)]" />
|
|
57
|
+
<component :is="searchable ? 'HComboboxOptions' : 'HListboxOptions'" static :class="[uiMenu.base, uiMenu.divide, uiMenu.ring, uiMenu.rounded, uiMenu.shadow, uiMenu.background, uiMenu.padding, uiMenu.height]">
|
|
58
|
+
<HComboboxInput
|
|
59
|
+
v-if="searchable"
|
|
60
|
+
ref="searchInput"
|
|
61
|
+
:display-value="() => query"
|
|
62
|
+
name="q"
|
|
63
|
+
:placeholder="searchablePlaceholder"
|
|
64
|
+
autofocus
|
|
65
|
+
autocomplete="off"
|
|
66
|
+
:class="uiMenu.input"
|
|
67
|
+
@change="query = $event.target.value"
|
|
68
|
+
/>
|
|
69
|
+
<component
|
|
70
|
+
:is="searchable ? 'HComboboxOption' : 'HListboxOption'"
|
|
71
|
+
v-for="(option, index) in filteredOptions"
|
|
72
|
+
v-slot="{ active, selected, disabled: optionDisabled }"
|
|
73
|
+
:key="index"
|
|
74
|
+
as="template"
|
|
75
|
+
:value="valueAttribute ? option[valueAttribute] : option"
|
|
76
|
+
:disabled="option.disabled"
|
|
77
|
+
>
|
|
78
|
+
<li :class="[uiMenu.option.base, uiMenu.option.rounded, uiMenu.option.padding, uiMenu.option.size, uiMenu.option.color, active ? uiMenu.option.active : uiMenu.option.inactive, selected && uiMenu.option.selected, optionDisabled && uiMenu.option.disabled]">
|
|
79
|
+
<div :class="uiMenu.option.container">
|
|
80
|
+
<slot name="option" :option="option" :active="active" :selected="selected">
|
|
81
|
+
<UIcon v-if="option.icon" :name="option.icon" :class="[uiMenu.option.icon.base, active ? uiMenu.option.icon.active : uiMenu.option.icon.inactive, option.iconClass]" aria-hidden="true" />
|
|
82
|
+
<UAvatar
|
|
83
|
+
v-else-if="option.avatar"
|
|
84
|
+
v-bind="{ size: uiMenu.option.avatar.size, ...option.avatar }"
|
|
85
|
+
:class="uiMenu.option.avatar.base"
|
|
86
|
+
aria-hidden="true"
|
|
87
|
+
/>
|
|
88
|
+
<span v-else-if="option.chip" :class="uiMenu.option.chip.base" :style="{ background: `#${option.chip}` }" />
|
|
89
|
+
|
|
90
|
+
<span class="truncate">{{ ['string', 'number'].includes(typeof option) ? option : option[optionAttribute] }}</span>
|
|
91
|
+
</slot>
|
|
92
|
+
</div>
|
|
93
|
+
|
|
94
|
+
<span v-if="selected" :class="[uiMenu.option.selectedIcon.wrapper, uiMenu.option.selectedIcon.padding]">
|
|
95
|
+
<UIcon :name="selectedIcon" :class="uiMenu.option.selectedIcon.base" aria-hidden="true" />
|
|
96
|
+
</span>
|
|
97
|
+
</li>
|
|
98
|
+
</component>
|
|
99
|
+
|
|
100
|
+
<component :is="searchable ? 'HComboboxOption' : 'HListboxOption'" v-if="creatable && queryOption && !filteredOptions.length" v-slot="{ active, selected }" :value="queryOption" as="template">
|
|
101
|
+
<li :class="[uiMenu.option.base, uiMenu.option.rounded, uiMenu.option.padding, uiMenu.option.size, uiMenu.option.color, active ? uiMenu.option.active : uiMenu.option.inactive]">
|
|
102
|
+
<div :class="uiMenu.option.container">
|
|
103
|
+
<slot name="option-create" :option="queryOption" :active="active" :selected="selected">
|
|
104
|
+
<span class="block truncate">Create "{{ queryOption[optionAttribute] }}"</span>
|
|
105
|
+
</slot>
|
|
106
|
+
</div>
|
|
107
|
+
</li>
|
|
108
|
+
</component>
|
|
109
|
+
<p v-else-if="searchable && query && !filteredOptions.length" :class="uiMenu.option.empty">
|
|
110
|
+
<slot name="option-empty" :query="query">
|
|
111
|
+
No results for "{{ query }}".
|
|
112
|
+
</slot>
|
|
113
|
+
</p>
|
|
96
114
|
</component>
|
|
97
|
-
|
|
98
|
-
<component :is="searchable ? 'HComboboxOption' : 'HListboxOption'" v-if="creatable && queryOption && !filteredOptions.length" v-slot="{ active, selected }" :value="queryOption" as="template">
|
|
99
|
-
<li :class="[uiMenu.option.base, uiMenu.option.rounded, uiMenu.option.padding, uiMenu.option.size, uiMenu.option.color, active ? uiMenu.option.active : uiMenu.option.inactive]">
|
|
100
|
-
<div :class="uiMenu.option.container">
|
|
101
|
-
<slot name="option-create" :option="queryOption" :active="active" :selected="selected">
|
|
102
|
-
<span class="block truncate">Create "{{ queryOption[optionAttribute] }}"</span>
|
|
103
|
-
</slot>
|
|
104
|
-
</div>
|
|
105
|
-
</li>
|
|
106
|
-
</component>
|
|
107
|
-
<p v-else-if="searchable && query && !filteredOptions.length" :class="uiMenu.option.empty">
|
|
108
|
-
<slot name="option-empty" :query="query">
|
|
109
|
-
No results for "{{ query }}".
|
|
110
|
-
</slot>
|
|
111
|
-
</p>
|
|
112
|
-
</component>
|
|
115
|
+
</div>
|
|
113
116
|
</Transition>
|
|
114
117
|
</div>
|
|
115
118
|
</component>
|
|
116
119
|
</template>
|
|
117
120
|
|
|
118
121
|
<script>
|
|
119
|
-
import { ref, computed, watch, defineComponent } from "vue";
|
|
122
|
+
import { ref, computed, toRef, watch, defineComponent } from "vue";
|
|
120
123
|
import {
|
|
121
124
|
Combobox as HCombobox,
|
|
122
125
|
ComboboxButton as HComboboxButton,
|
|
@@ -130,15 +133,17 @@ import {
|
|
|
130
133
|
} from "@headlessui/vue";
|
|
131
134
|
import { computedAsync, useDebounceFn } from "@vueuse/core";
|
|
132
135
|
import { defu } from "defu";
|
|
133
|
-
import { omit } from "lodash-es";
|
|
134
136
|
import { twMerge, twJoin } from "tailwind-merge";
|
|
135
137
|
import UIcon from "../elements/Icon.vue";
|
|
136
138
|
import UAvatar from "../elements/Avatar.vue";
|
|
137
|
-
import {
|
|
139
|
+
import { useUI } from "../../composables/useUI";
|
|
138
140
|
import { usePopper } from "../../composables/usePopper";
|
|
139
141
|
import { useFormGroup } from "../../composables/useFormGroup";
|
|
140
|
-
import {
|
|
142
|
+
import { mergeConfig } from "../../utils";
|
|
141
143
|
import appConfig from "#build/app.config";
|
|
144
|
+
import { select, selectMenu } from "#ui/ui.config";
|
|
145
|
+
const config = mergeConfig(appConfig.ui.strategy, appConfig.ui.select, select);
|
|
146
|
+
const configMenu = mergeConfig(appConfig.ui.strategy, appConfig.ui.selectMenu, selectMenu);
|
|
142
147
|
export default defineComponent({
|
|
143
148
|
components: {
|
|
144
149
|
HCombobox,
|
|
@@ -167,6 +172,10 @@ export default defineComponent({
|
|
|
167
172
|
type: Array,
|
|
168
173
|
default: () => []
|
|
169
174
|
},
|
|
175
|
+
id: {
|
|
176
|
+
type: String,
|
|
177
|
+
default: null
|
|
178
|
+
},
|
|
170
179
|
name: {
|
|
171
180
|
type: String,
|
|
172
181
|
default: null
|
|
@@ -181,7 +190,7 @@ export default defineComponent({
|
|
|
181
190
|
},
|
|
182
191
|
loadingIcon: {
|
|
183
192
|
type: String,
|
|
184
|
-
default: () =>
|
|
193
|
+
default: () => config.default.loadingIcon
|
|
185
194
|
},
|
|
186
195
|
leadingIcon: {
|
|
187
196
|
type: String,
|
|
@@ -189,7 +198,7 @@ export default defineComponent({
|
|
|
189
198
|
},
|
|
190
199
|
trailingIcon: {
|
|
191
200
|
type: String,
|
|
192
|
-
default: () =>
|
|
201
|
+
default: () => config.default.trailingIcon
|
|
193
202
|
},
|
|
194
203
|
trailing: {
|
|
195
204
|
type: Boolean,
|
|
@@ -205,7 +214,7 @@ export default defineComponent({
|
|
|
205
214
|
},
|
|
206
215
|
selectedIcon: {
|
|
207
216
|
type: String,
|
|
208
|
-
default: () =>
|
|
217
|
+
default: () => configMenu.default.selectedIcon
|
|
209
218
|
},
|
|
210
219
|
disabled: {
|
|
211
220
|
type: Boolean,
|
|
@@ -241,25 +250,25 @@ export default defineComponent({
|
|
|
241
250
|
},
|
|
242
251
|
size: {
|
|
243
252
|
type: String,
|
|
244
|
-
default:
|
|
253
|
+
default: null,
|
|
245
254
|
validator(value) {
|
|
246
|
-
return Object.keys(
|
|
255
|
+
return Object.keys(config.size).includes(value);
|
|
247
256
|
}
|
|
248
257
|
},
|
|
249
258
|
color: {
|
|
250
259
|
type: String,
|
|
251
|
-
default: () =>
|
|
260
|
+
default: () => config.default.color,
|
|
252
261
|
validator(value) {
|
|
253
|
-
return [...appConfig.ui.colors, ...Object.keys(
|
|
262
|
+
return [...appConfig.ui.colors, ...Object.keys(config.color)].includes(value);
|
|
254
263
|
}
|
|
255
264
|
},
|
|
256
265
|
variant: {
|
|
257
266
|
type: String,
|
|
258
|
-
default: () =>
|
|
267
|
+
default: () => config.default.variant,
|
|
259
268
|
validator(value) {
|
|
260
269
|
return [
|
|
261
|
-
...Object.keys(
|
|
262
|
-
...Object.values(
|
|
270
|
+
...Object.keys(config.variant),
|
|
271
|
+
...Object.values(config.color).flatMap((value2) => Object.keys(value2))
|
|
263
272
|
].includes(value);
|
|
264
273
|
}
|
|
265
274
|
},
|
|
@@ -283,28 +292,28 @@ export default defineComponent({
|
|
|
283
292
|
type: String,
|
|
284
293
|
default: null
|
|
285
294
|
},
|
|
295
|
+
class: {
|
|
296
|
+
type: [String, Object, Array],
|
|
297
|
+
default: void 0
|
|
298
|
+
},
|
|
286
299
|
ui: {
|
|
287
300
|
type: Object,
|
|
288
|
-
default:
|
|
301
|
+
default: void 0
|
|
289
302
|
},
|
|
290
303
|
uiMenu: {
|
|
291
304
|
type: Object,
|
|
292
|
-
default:
|
|
305
|
+
default: void 0
|
|
293
306
|
}
|
|
294
307
|
},
|
|
295
308
|
emits: ["update:modelValue", "open", "close", "change"],
|
|
296
|
-
setup(props, { emit,
|
|
297
|
-
const
|
|
298
|
-
const ui
|
|
299
|
-
const uiMenu = computed(() => defuTwMerge({}, props.uiMenu, appConfig2.ui.selectMenu));
|
|
309
|
+
setup(props, { emit, slots }) {
|
|
310
|
+
const { ui, attrs } = useUI("select", toRef(props, "ui"), config, toRef(props, "class"));
|
|
311
|
+
const { ui: uiMenu } = useUI("selectMenu", toRef(props, "uiMenu"), configMenu);
|
|
300
312
|
const popper = computed(() => defu({}, props.popper, uiMenu.value.popper));
|
|
301
313
|
const [trigger, container] = usePopper(popper.value);
|
|
302
|
-
const { emitFormBlur, emitFormChange,
|
|
303
|
-
const color = computed(() => formGroup?.error?.value ? "red" : props.color);
|
|
304
|
-
const size = computed(() => formGroup?.size?.value ?? props.size);
|
|
314
|
+
const { emitFormBlur, emitFormChange, inputId, color, size, name } = useFormGroup(props, config);
|
|
305
315
|
const query = ref("");
|
|
306
316
|
const searchInput = ref();
|
|
307
|
-
const wrapperClass = computed(() => twMerge(ui.value.wrapper, attrs.class));
|
|
308
317
|
const selectClass = computed(() => {
|
|
309
318
|
const variant = ui.value.color?.[color.value]?.[props.variant] || ui.value.variant[props.variant];
|
|
310
319
|
return twMerge(twJoin(
|
|
@@ -348,7 +357,7 @@ export default defineComponent({
|
|
|
348
357
|
const leadingIconClass = computed(() => {
|
|
349
358
|
return twJoin(
|
|
350
359
|
ui.value.icon.base,
|
|
351
|
-
|
|
360
|
+
appConfig.ui.colors.includes(color.value) && ui.value.icon.color.replaceAll("{color}", color.value),
|
|
352
361
|
ui.value.icon.size[size.value],
|
|
353
362
|
props.loading && "animate-spin"
|
|
354
363
|
);
|
|
@@ -363,7 +372,7 @@ export default defineComponent({
|
|
|
363
372
|
const trailingIconClass = computed(() => {
|
|
364
373
|
return twJoin(
|
|
365
374
|
ui.value.icon.base,
|
|
366
|
-
|
|
375
|
+
appConfig.ui.colors.includes(color.value) && ui.value.icon.color.replaceAll("{color}", color.value),
|
|
367
376
|
ui.value.icon.size[size.value],
|
|
368
377
|
props.loading && !isLeading.value && "animate-spin"
|
|
369
378
|
);
|
|
@@ -378,7 +387,7 @@ export default defineComponent({
|
|
|
378
387
|
}
|
|
379
388
|
return props.options.filter((option) => {
|
|
380
389
|
return (props.searchAttributes?.length ? props.searchAttributes : [props.optionAttribute]).some((searchAttribute) => {
|
|
381
|
-
return typeof option
|
|
390
|
+
return ["string", "number"].includes(typeof option) ? option.toString().search(new RegExp(query.value, "i")) !== -1 : option[searchAttribute] && option[searchAttribute].search(new RegExp(query.value, "i")) !== -1;
|
|
382
391
|
});
|
|
383
392
|
});
|
|
384
393
|
});
|
|
@@ -403,14 +412,20 @@ export default defineComponent({
|
|
|
403
412
|
emitFormChange();
|
|
404
413
|
}
|
|
405
414
|
return {
|
|
406
|
-
|
|
415
|
+
// eslint-disable-next-line vue/no-dupe-keys
|
|
416
|
+
ui,
|
|
407
417
|
// eslint-disable-next-line vue/no-dupe-keys
|
|
408
418
|
uiMenu,
|
|
419
|
+
attrs,
|
|
420
|
+
// eslint-disable-next-line vue/no-dupe-keys
|
|
421
|
+
name,
|
|
422
|
+
inputId,
|
|
423
|
+
// eslint-disable-next-line vue/no-dupe-keys
|
|
424
|
+
popper,
|
|
409
425
|
trigger,
|
|
410
426
|
container,
|
|
411
427
|
isLeading,
|
|
412
428
|
isTrailing,
|
|
413
|
-
wrapperClass,
|
|
414
429
|
// eslint-disable-next-line vue/no-dupe-keys
|
|
415
430
|
selectClass,
|
|
416
431
|
leadingIconName,
|