@nuxt/ui 2.9.0 → 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/dist/module.d.mts +270 -2
- package/dist/module.d.ts +270 -2
- package/dist/module.json +1 -1
- package/dist/module.mjs +21 -2
- package/dist/runtime/components/data/Table.vue +8 -6
- package/dist/runtime/components/data/Table.vue.d.ts +2 -1
- package/dist/runtime/components/elements/Accordion.vue +15 -13
- package/dist/runtime/components/elements/Accordion.vue.d.ts +5 -2
- package/dist/runtime/components/elements/Button.vue.d.ts +2 -2
- package/dist/runtime/components/elements/Dropdown.vue +31 -25
- package/dist/runtime/components/elements/Dropdown.vue.d.ts +2 -0
- 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.d.ts +2 -2
- package/dist/runtime/components/forms/Form.vue +32 -7
- package/dist/runtime/components/forms/Form.vue.d.ts +2 -1
- package/dist/runtime/components/forms/Input.vue +5 -1
- package/dist/runtime/components/forms/Input.vue.d.ts +12 -3
- package/dist/runtime/components/forms/Radio.vue +10 -9
- package/dist/runtime/components/forms/Radio.vue.d.ts +3 -3
- 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.d.ts +3 -3
- package/dist/runtime/components/forms/Select.vue.d.ts +2 -2
- package/dist/runtime/components/forms/SelectMenu.vue +62 -57
- package/dist/runtime/components/forms/SelectMenu.vue.d.ts +6 -5
- package/dist/runtime/components/forms/Textarea.vue +5 -1
- package/dist/runtime/components/forms/Textarea.vue.d.ts +11 -2
- package/dist/runtime/components/forms/Toggle.vue.d.ts +2 -2
- package/dist/runtime/components/layout/Divider.vue +107 -0
- package/dist/runtime/components/layout/Divider.vue.d.ts +82 -0
- package/dist/runtime/components/navigation/CommandPalette.vue +10 -3
- package/dist/runtime/components/navigation/CommandPalette.vue.d.ts +1 -1
- package/dist/runtime/components/navigation/Pagination.vue +65 -9
- package/dist/runtime/components/navigation/Pagination.vue.d.ts +41 -3
- package/dist/runtime/components/navigation/Tabs.vue +1 -1
- package/dist/runtime/components/overlays/ContextMenu.vue +7 -2
- package/dist/runtime/components/overlays/ContextMenu.vue.d.ts +2 -1
- package/dist/runtime/components/overlays/Modal.vue +1 -1
- package/dist/runtime/components/overlays/Modal.vue.d.ts +1 -1
- package/dist/runtime/components/overlays/Notification.vue +7 -1
- package/dist/runtime/components/overlays/Notifications.vue +1 -1
- package/dist/runtime/components/overlays/Popover.vue +22 -7
- package/dist/runtime/components/overlays/Popover.vue.d.ts +14 -0
- package/dist/runtime/components/overlays/Slideover.vue.d.ts +1 -1
- package/dist/runtime/components/overlays/Tooltip.vue +16 -10
- package/dist/runtime/components/overlays/Tooltip.vue.d.ts +1 -0
- package/dist/runtime/composables/useFormGroup.d.ts +3 -3
- package/dist/runtime/composables/useFormGroup.mjs +17 -6
- package/dist/runtime/composables/usePopper.d.ts +3 -3
- package/dist/runtime/composables/usePopper.mjs +7 -1
- package/dist/runtime/composables/useUI.d.ts +2 -2
- package/dist/runtime/composables/useUI.mjs +2 -2
- package/dist/runtime/types/command-palette.d.ts +1 -0
- package/dist/runtime/types/form.d.ts +13 -6
- package/dist/runtime/types/index.d.ts +2 -0
- package/dist/runtime/types/meter.d.ts +5 -0
- package/dist/runtime/types/popper.d.ts +1 -0
- package/dist/runtime/types/progress.d.ts +4 -0
- package/dist/runtime/types/utils.d.ts +1 -1
- package/dist/runtime/ui.config.d.ts +263 -0
- package/dist/runtime/ui.config.mjs +263 -19
- package/dist/types.d.mts +1 -1
- package/dist/types.d.ts +1 -1
- package/package.json +19 -19
- package/dist/runtime/utils/StateEmitter.d.ts +0 -17
- package/dist/runtime/utils/StateEmitter.mjs +0 -21
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div :class="ui.wrapper" v-bind="attrs">
|
|
3
|
+
<slot v-if="indicator || $slots.indicator" name="indicator" v-bind="{ percent }">
|
|
4
|
+
<div v-if="!isSteps" :class="indicatorContainerClass" :style="{ width: `${percent}%` }">
|
|
5
|
+
<div :class="indicatorClass">
|
|
6
|
+
{{ Math.round(percent) }}%
|
|
7
|
+
</div>
|
|
8
|
+
</div>
|
|
9
|
+
</slot>
|
|
10
|
+
|
|
11
|
+
<progress :class="progressClass" v-bind="{ value, max: realMax }">
|
|
12
|
+
{{ Math.round(percent) }}%
|
|
13
|
+
</progress>
|
|
14
|
+
|
|
15
|
+
<div v-if="isSteps" :class="stepsClass">
|
|
16
|
+
<div v-for="(step, index) in max" :key="index" :class="stepClasses(index)">
|
|
17
|
+
<slot :name="`step-${index}`" v-bind="{ step }">
|
|
18
|
+
{{ step }}
|
|
19
|
+
</slot>
|
|
20
|
+
</div>
|
|
21
|
+
</div>
|
|
22
|
+
</div>
|
|
23
|
+
</template>
|
|
24
|
+
|
|
25
|
+
<script>
|
|
26
|
+
import { computed, defineComponent, toRef } from "vue";
|
|
27
|
+
import { twJoin } from "tailwind-merge";
|
|
28
|
+
import { useUI } from "../../composables/useUI";
|
|
29
|
+
import { mergeConfig } from "../../utils";
|
|
30
|
+
import appConfig from "#build/app.config";
|
|
31
|
+
import { progress } from "#ui/ui.config";
|
|
32
|
+
const config = mergeConfig(appConfig.ui.strategy, appConfig.ui.progress, progress);
|
|
33
|
+
export default defineComponent({
|
|
34
|
+
inheritAttrs: false,
|
|
35
|
+
props: {
|
|
36
|
+
value: {
|
|
37
|
+
type: [Number, null, void 0],
|
|
38
|
+
default: null
|
|
39
|
+
},
|
|
40
|
+
max: {
|
|
41
|
+
type: [Number, Array],
|
|
42
|
+
default: 100
|
|
43
|
+
},
|
|
44
|
+
indicator: {
|
|
45
|
+
type: Boolean,
|
|
46
|
+
default: false
|
|
47
|
+
},
|
|
48
|
+
animation: {
|
|
49
|
+
type: String,
|
|
50
|
+
default: () => config.default.animation,
|
|
51
|
+
validator(value) {
|
|
52
|
+
return Object.keys(config.animation).includes(value);
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
size: {
|
|
56
|
+
type: String,
|
|
57
|
+
default: () => config.default.size,
|
|
58
|
+
validator(value) {
|
|
59
|
+
return Object.keys(config.progress.size).includes(value);
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
color: {
|
|
63
|
+
type: String,
|
|
64
|
+
default: () => config.default.color,
|
|
65
|
+
validator(value) {
|
|
66
|
+
return appConfig.ui.colors.includes(value);
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
class: {
|
|
70
|
+
type: [String, Object, Array],
|
|
71
|
+
default: void 0
|
|
72
|
+
},
|
|
73
|
+
ui: {
|
|
74
|
+
type: Object,
|
|
75
|
+
default: void 0
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
setup(props) {
|
|
79
|
+
const { ui, attrs } = useUI("progress", toRef(props, "ui"), config, toRef(props, "class"));
|
|
80
|
+
const indicatorContainerClass = computed(() => {
|
|
81
|
+
return twJoin(
|
|
82
|
+
ui.value.indicator.container.base,
|
|
83
|
+
ui.value.indicator.container.width,
|
|
84
|
+
ui.value.indicator.container.transition
|
|
85
|
+
);
|
|
86
|
+
});
|
|
87
|
+
const indicatorClass = computed(() => {
|
|
88
|
+
return twJoin(
|
|
89
|
+
ui.value.indicator.align,
|
|
90
|
+
ui.value.indicator.width,
|
|
91
|
+
ui.value.indicator.color,
|
|
92
|
+
ui.value.indicator.size[props.size]
|
|
93
|
+
);
|
|
94
|
+
});
|
|
95
|
+
const progressClass = computed(() => {
|
|
96
|
+
const classes = [
|
|
97
|
+
ui.value.progress.base,
|
|
98
|
+
ui.value.progress.width,
|
|
99
|
+
ui.value.progress.size[props.size],
|
|
100
|
+
ui.value.progress.rounded,
|
|
101
|
+
ui.value.progress.track,
|
|
102
|
+
ui.value.progress.bar,
|
|
103
|
+
// Intermediate class to allow thumb ring or background color (set to `current`) as it's impossible to safelist with arbitrary values
|
|
104
|
+
ui.value.progress.color?.replaceAll("{color}", props.color),
|
|
105
|
+
ui.value.progress.background,
|
|
106
|
+
ui.value.progress.indeterminate.base,
|
|
107
|
+
ui.value.progress.indeterminate.rounded
|
|
108
|
+
];
|
|
109
|
+
if (isIndeterminate.value) {
|
|
110
|
+
classes.push(ui.value.animation[props.animation]);
|
|
111
|
+
}
|
|
112
|
+
return twJoin(...classes);
|
|
113
|
+
});
|
|
114
|
+
const stepsClass = computed(() => {
|
|
115
|
+
return twJoin(
|
|
116
|
+
ui.value.steps.base,
|
|
117
|
+
ui.value.steps.color?.replaceAll("{color}", props.color),
|
|
118
|
+
ui.value.steps.size[props.size]
|
|
119
|
+
);
|
|
120
|
+
});
|
|
121
|
+
const stepClass = computed(() => {
|
|
122
|
+
return twJoin(
|
|
123
|
+
ui.value.step.base,
|
|
124
|
+
ui.value.step.align
|
|
125
|
+
);
|
|
126
|
+
});
|
|
127
|
+
const stepActiveClass = computed(() => {
|
|
128
|
+
return twJoin(
|
|
129
|
+
ui.value.step.active
|
|
130
|
+
);
|
|
131
|
+
});
|
|
132
|
+
const stepFirstClass = computed(() => {
|
|
133
|
+
return twJoin(
|
|
134
|
+
ui.value.step.first
|
|
135
|
+
);
|
|
136
|
+
});
|
|
137
|
+
function isActive(index) {
|
|
138
|
+
return index === Number(props.value);
|
|
139
|
+
}
|
|
140
|
+
function isFirst(index) {
|
|
141
|
+
return index === 0;
|
|
142
|
+
}
|
|
143
|
+
function stepClasses(index) {
|
|
144
|
+
index = Number(index);
|
|
145
|
+
const classes = [stepClass.value];
|
|
146
|
+
if (isFirst(index)) {
|
|
147
|
+
classes.push(stepFirstClass.value);
|
|
148
|
+
}
|
|
149
|
+
if (isActive(index)) {
|
|
150
|
+
classes.push(stepActiveClass.value);
|
|
151
|
+
}
|
|
152
|
+
return classes.join(" ");
|
|
153
|
+
}
|
|
154
|
+
const isIndeterminate = computed(() => [void 0, null].includes(props.value));
|
|
155
|
+
const isSteps = computed(() => Array.isArray(props.max));
|
|
156
|
+
const realMax = computed(() => {
|
|
157
|
+
if (isIndeterminate.value) {
|
|
158
|
+
return null;
|
|
159
|
+
}
|
|
160
|
+
if (Array.isArray(props.max)) {
|
|
161
|
+
return props.max.length - 1;
|
|
162
|
+
}
|
|
163
|
+
return Number(props.max);
|
|
164
|
+
});
|
|
165
|
+
const percent = computed(() => {
|
|
166
|
+
switch (true) {
|
|
167
|
+
case props.value < 0:
|
|
168
|
+
return 0;
|
|
169
|
+
case props.value > 100:
|
|
170
|
+
return 100;
|
|
171
|
+
default:
|
|
172
|
+
return props.value / realMax.value * 100;
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
return {
|
|
176
|
+
// eslint-disable-next-line vue/no-dupe-keys
|
|
177
|
+
ui,
|
|
178
|
+
attrs,
|
|
179
|
+
indicatorContainerClass,
|
|
180
|
+
indicatorClass,
|
|
181
|
+
progressClass,
|
|
182
|
+
stepsClass,
|
|
183
|
+
stepClasses,
|
|
184
|
+
isIndeterminate,
|
|
185
|
+
isSteps,
|
|
186
|
+
realMax,
|
|
187
|
+
percent
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
</script>
|
|
192
|
+
|
|
193
|
+
<style scoped>
|
|
194
|
+
/** These styles are required to animate the bar */
|
|
195
|
+
progress:indeterminate {
|
|
196
|
+
@apply relative;
|
|
197
|
+
|
|
198
|
+
&:after {
|
|
199
|
+
@apply content-[''];
|
|
200
|
+
@apply absolute inset-0;
|
|
201
|
+
@apply bg-current;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
&::-webkit-progress-value {
|
|
205
|
+
@apply bg-current;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
&::-moz-progress-bar {
|
|
209
|
+
@apply bg-current;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
&.bar-animation-carousel {
|
|
213
|
+
&:after {
|
|
214
|
+
animation: carousel 2s ease-in-out infinite;
|
|
215
|
+
}
|
|
216
|
+
&::-webkit-progress-value {
|
|
217
|
+
animation: carousel 2s ease-in-out infinite;
|
|
218
|
+
}
|
|
219
|
+
&::-moz-progress-bar {
|
|
220
|
+
animation: carousel 2s ease-in-out infinite;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
&.bar-animation-carousel-inverse {
|
|
225
|
+
&:after {
|
|
226
|
+
animation: carousel-inverse 2s ease-in-out infinite;
|
|
227
|
+
}
|
|
228
|
+
&::-webkit-progress-value {
|
|
229
|
+
animation: carousel-inverse 2s ease-in-out infinite;
|
|
230
|
+
}
|
|
231
|
+
&::-moz-progress-bar {
|
|
232
|
+
animation: carousel-inverse 2s ease-in-out infinite;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
&.bar-animation-swing {
|
|
237
|
+
&:after {
|
|
238
|
+
animation: swing 3s ease-in-out infinite;
|
|
239
|
+
}
|
|
240
|
+
&::-webkit-progress-value {
|
|
241
|
+
animation: swing 3s ease-in-out infinite;
|
|
242
|
+
}
|
|
243
|
+
&::-moz-progress-bar {
|
|
244
|
+
animation: swing 3s ease-in-out infinite;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
&.bar-animation-elastic {
|
|
249
|
+
&::after {
|
|
250
|
+
animation: elastic 3s ease-in-out infinite;
|
|
251
|
+
}
|
|
252
|
+
&::-webkit-progress-value {
|
|
253
|
+
animation: elastic 3s ease-in-out infinite;
|
|
254
|
+
}
|
|
255
|
+
&::-moz-progress-bar {
|
|
256
|
+
animation: elastic 3s ease-in-out infinite;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
@keyframes carousel {
|
|
262
|
+
0%, 100% { width: 50% }
|
|
263
|
+
0% { transform: translateX(-100%) }
|
|
264
|
+
100% { transform: translateX(200%) }
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
@keyframes carousel-inverse {
|
|
268
|
+
0%, 100% { width: 50% }
|
|
269
|
+
0% { transform: translateX(200%) }
|
|
270
|
+
100% { transform: translateX(-100%) }
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
@keyframes swing {
|
|
274
|
+
0%, 100% { width: 50% }
|
|
275
|
+
0%, 100% { transform: translateX(-25%) }
|
|
276
|
+
50% { transform: translateX(125%) }
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
@keyframes elastic {
|
|
280
|
+
/* Firefox doesn't do "margin: 0 auto", we have to play with margin-left */
|
|
281
|
+
0%, 100% { width: 50%; margin-left: 25%; }
|
|
282
|
+
50% { width: 90%; margin-left: 5% }
|
|
283
|
+
}
|
|
284
|
+
</style>
|
|
@@ -63,8 +63,8 @@ declare const _default: import("vue").DefineComponent<{
|
|
|
63
63
|
[x: string]: unknown;
|
|
64
64
|
}, string>>;
|
|
65
65
|
toggle: import("vue").WritableComputedRef<boolean | unknown[]>;
|
|
66
|
-
inputId: import("vue").
|
|
67
|
-
name: import("vue").ComputedRef<
|
|
66
|
+
inputId: import("vue").Ref<string | undefined>;
|
|
67
|
+
name: import("vue").ComputedRef<string | undefined>;
|
|
68
68
|
inputClass: import("vue").ComputedRef<string>;
|
|
69
69
|
onChange: (event: Event) => void;
|
|
70
70
|
}, 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<{
|
|
@@ -8,6 +8,13 @@
|
|
|
8
8
|
import { provide, ref, defineComponent } from "vue";
|
|
9
9
|
import { useEventBus } from "@vueuse/core";
|
|
10
10
|
import { uid } from "../../utils/uid";
|
|
11
|
+
class FormException extends Error {
|
|
12
|
+
constructor(message) {
|
|
13
|
+
super(message);
|
|
14
|
+
this.message = message;
|
|
15
|
+
Object.setPrototypeOf(this, FormException.prototype);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
11
18
|
export default defineComponent({
|
|
12
19
|
props: {
|
|
13
20
|
schema: {
|
|
@@ -27,7 +34,7 @@ export default defineComponent({
|
|
|
27
34
|
default: () => ["blur", "input", "change", "submit"]
|
|
28
35
|
}
|
|
29
36
|
},
|
|
30
|
-
emits: ["submit"],
|
|
37
|
+
emits: ["submit", "error"],
|
|
31
38
|
setup(props, { expose, emit }) {
|
|
32
39
|
const bus = useEventBus(`form-${uid()}`);
|
|
33
40
|
bus.on(async (event) => {
|
|
@@ -38,6 +45,8 @@ export default defineComponent({
|
|
|
38
45
|
const errors = ref([]);
|
|
39
46
|
provide("form-errors", errors);
|
|
40
47
|
provide("form-events", bus);
|
|
48
|
+
const inputs = ref({});
|
|
49
|
+
provide("form-inputs", inputs);
|
|
41
50
|
async function getErrors() {
|
|
42
51
|
let errs = await props.validate(props.state);
|
|
43
52
|
if (props.schema) {
|
|
@@ -68,19 +77,35 @@ export default defineComponent({
|
|
|
68
77
|
errors.value = await getErrors();
|
|
69
78
|
}
|
|
70
79
|
if (!opts.silent && errors.value.length > 0) {
|
|
71
|
-
throw new
|
|
80
|
+
throw new FormException(
|
|
72
81
|
`Form validation failed: ${JSON.stringify(errors.value, null, 2)}`
|
|
73
82
|
);
|
|
74
83
|
}
|
|
75
84
|
return props.state;
|
|
76
85
|
}
|
|
77
86
|
async function onSubmit(event) {
|
|
78
|
-
|
|
79
|
-
|
|
87
|
+
try {
|
|
88
|
+
if (props.validateOn?.includes("submit")) {
|
|
89
|
+
await validate();
|
|
90
|
+
}
|
|
91
|
+
const submitEvent = {
|
|
92
|
+
...event,
|
|
93
|
+
data: props.state
|
|
94
|
+
};
|
|
95
|
+
emit("submit", submitEvent);
|
|
96
|
+
} catch (error) {
|
|
97
|
+
if (!(error instanceof FormException)) {
|
|
98
|
+
throw error;
|
|
99
|
+
}
|
|
100
|
+
const errorEvent = {
|
|
101
|
+
...event,
|
|
102
|
+
errors: errors.value.map((err) => ({
|
|
103
|
+
...err,
|
|
104
|
+
id: inputs.value[err.path]
|
|
105
|
+
}))
|
|
106
|
+
};
|
|
107
|
+
emit("error", errorEvent);
|
|
80
108
|
}
|
|
81
|
-
const submitEvent = event;
|
|
82
|
-
submitEvent.data = props.state;
|
|
83
|
-
emit("submit", event);
|
|
84
109
|
}
|
|
85
110
|
expose({
|
|
86
111
|
validate,
|
|
@@ -23,7 +23,7 @@ declare const _default: import("vue").DefineComponent<{
|
|
|
23
23
|
};
|
|
24
24
|
}, {
|
|
25
25
|
onSubmit: (event: SubmitEvent) => Promise<void>;
|
|
26
|
-
}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, "submit"[], "submit", import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{
|
|
26
|
+
}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, ("error" | "submit")[], "error" | "submit", import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{
|
|
27
27
|
schema: {
|
|
28
28
|
type: PropType<ZodSchema<any, import("zod").ZodTypeDef, any>> | PropType<YupObjectSchema<any, import("yup").AnyObject, any, "">> | PropType<JoiSchema> | PropType<ValibotObjectSchema<any>>;
|
|
29
29
|
default: undefined;
|
|
@@ -41,6 +41,7 @@ declare const _default: import("vue").DefineComponent<{
|
|
|
41
41
|
default: () => string[];
|
|
42
42
|
};
|
|
43
43
|
}>> & {
|
|
44
|
+
onError?: ((...args: any[]) => any) | undefined;
|
|
44
45
|
onSubmit?: ((...args: any[]) => any) | undefined;
|
|
45
46
|
}, {
|
|
46
47
|
schema: ZodSchema<any, import("zod").ZodTypeDef, any> | YupObjectSchema<any, import("yup").AnyObject, any, ""> | import("joi").AnySchema<any> | ValibotObjectSchema<any>;
|
|
@@ -79,6 +79,10 @@ export default defineComponent({
|
|
|
79
79
|
type: Boolean,
|
|
80
80
|
default: false
|
|
81
81
|
},
|
|
82
|
+
autofocusDelay: {
|
|
83
|
+
type: Number,
|
|
84
|
+
default: 100
|
|
85
|
+
},
|
|
82
86
|
icon: {
|
|
83
87
|
type: String,
|
|
84
88
|
default: null
|
|
@@ -169,7 +173,7 @@ export default defineComponent({
|
|
|
169
173
|
onMounted(() => {
|
|
170
174
|
setTimeout(() => {
|
|
171
175
|
autoFocus();
|
|
172
|
-
},
|
|
176
|
+
}, props.autofocusDelay);
|
|
173
177
|
});
|
|
174
178
|
const inputClass = computed(() => {
|
|
175
179
|
const variant = ui.value.color?.[color.value]?.[props.variant] || ui.value.variant[props.variant];
|
|
@@ -32,6 +32,10 @@ declare const _default: import("vue").DefineComponent<{
|
|
|
32
32
|
type: BooleanConstructor;
|
|
33
33
|
default: boolean;
|
|
34
34
|
};
|
|
35
|
+
autofocusDelay: {
|
|
36
|
+
type: NumberConstructor;
|
|
37
|
+
default: number;
|
|
38
|
+
};
|
|
35
39
|
icon: {
|
|
36
40
|
type: StringConstructor;
|
|
37
41
|
default: null;
|
|
@@ -96,8 +100,8 @@ declare const _default: import("vue").DefineComponent<{
|
|
|
96
100
|
attrs: import("vue").ComputedRef<Pick<{
|
|
97
101
|
[x: string]: unknown;
|
|
98
102
|
}, string>>;
|
|
99
|
-
name: import("vue").ComputedRef<
|
|
100
|
-
inputId: import("vue").
|
|
103
|
+
name: import("vue").ComputedRef<string | undefined>;
|
|
104
|
+
inputId: import("vue").Ref<string | undefined>;
|
|
101
105
|
input: import("vue").Ref<HTMLInputElement | null>;
|
|
102
106
|
isLeading: import("vue").ComputedRef<string | true>;
|
|
103
107
|
isTrailing: import("vue").ComputedRef<string | true>;
|
|
@@ -143,6 +147,10 @@ declare const _default: import("vue").DefineComponent<{
|
|
|
143
147
|
type: BooleanConstructor;
|
|
144
148
|
default: boolean;
|
|
145
149
|
};
|
|
150
|
+
autofocusDelay: {
|
|
151
|
+
type: NumberConstructor;
|
|
152
|
+
default: number;
|
|
153
|
+
};
|
|
146
154
|
icon: {
|
|
147
155
|
type: StringConstructor;
|
|
148
156
|
default: null;
|
|
@@ -212,9 +220,9 @@ declare const _default: import("vue").DefineComponent<{
|
|
|
212
220
|
ui: Partial<any>;
|
|
213
221
|
name: string;
|
|
214
222
|
class: any;
|
|
215
|
-
type: string;
|
|
216
223
|
modelValue: string | number;
|
|
217
224
|
loading: boolean;
|
|
225
|
+
type: string;
|
|
218
226
|
disabled: boolean;
|
|
219
227
|
variant: any;
|
|
220
228
|
required: boolean;
|
|
@@ -228,5 +236,6 @@ declare const _default: import("vue").DefineComponent<{
|
|
|
228
236
|
leading: boolean;
|
|
229
237
|
autofocus: boolean;
|
|
230
238
|
inputClass: string;
|
|
239
|
+
autofocusDelay: number;
|
|
231
240
|
}, {}>;
|
|
232
241
|
export default _default;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<div :class="ui.wrapper">
|
|
3
3
|
<div class="flex items-center h-5">
|
|
4
4
|
<input
|
|
5
|
-
:id="
|
|
5
|
+
:id="id"
|
|
6
6
|
v-model="pick"
|
|
7
7
|
:name="name"
|
|
8
8
|
:required="required"
|
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
v-bind="attrs"
|
|
15
15
|
>
|
|
16
16
|
</div>
|
|
17
|
-
<div v-if="label || $slots.label" class="ms-3
|
|
18
|
-
<label :for="
|
|
17
|
+
<div v-if="label || $slots.label" class="ms-3 inline-flex items-center">
|
|
18
|
+
<label :for="id" :class="ui.label">
|
|
19
19
|
<slot name="label">{{ label }}</slot>
|
|
20
20
|
<span v-if="required" :class="ui.required">*</span>
|
|
21
21
|
</label>
|
|
@@ -27,14 +27,14 @@
|
|
|
27
27
|
</template>
|
|
28
28
|
|
|
29
29
|
<script>
|
|
30
|
-
import { computed,
|
|
30
|
+
import { computed, defineComponent, inject, toRef } from "vue";
|
|
31
31
|
import { twMerge, twJoin } from "tailwind-merge";
|
|
32
32
|
import { useUI } from "../../composables/useUI";
|
|
33
|
-
import { useFormGroup } from "../../composables/useFormGroup";
|
|
34
33
|
import { mergeConfig } from "../../utils";
|
|
35
34
|
import appConfig from "#build/app.config";
|
|
36
35
|
import { radio } from "#ui/ui.config";
|
|
37
36
|
import { uid } from "../../utils/uid";
|
|
37
|
+
import { useFormGroup } from "../../composables/useFormGroup";
|
|
38
38
|
const config = mergeConfig(appConfig.ui.strategy, appConfig.ui.radio, radio);
|
|
39
39
|
export default defineComponent({
|
|
40
40
|
inheritAttrs: false,
|
|
@@ -92,17 +92,19 @@ export default defineComponent({
|
|
|
92
92
|
default: void 0
|
|
93
93
|
}
|
|
94
94
|
},
|
|
95
|
-
emits: ["update:modelValue"],
|
|
95
|
+
emits: ["update:modelValue", "change"],
|
|
96
96
|
setup(props, { emit }) {
|
|
97
97
|
const { ui, attrs } = useUI("radio", toRef(props, "ui"), config, toRef(props, "class"));
|
|
98
|
-
const
|
|
98
|
+
const radioGroup = inject("radio-group", null);
|
|
99
|
+
const { emitFormChange, color, name } = radioGroup ?? useFormGroup(props, config);
|
|
99
100
|
const pick = computed({
|
|
100
101
|
get() {
|
|
101
102
|
return props.modelValue;
|
|
102
103
|
},
|
|
103
104
|
set(value) {
|
|
104
105
|
emit("update:modelValue", value);
|
|
105
|
-
|
|
106
|
+
emit("change", value);
|
|
107
|
+
if (!radioGroup) {
|
|
106
108
|
emitFormChange();
|
|
107
109
|
}
|
|
108
110
|
}
|
|
@@ -119,7 +121,6 @@ export default defineComponent({
|
|
|
119
121
|
return {
|
|
120
122
|
// eslint-disable-next-line vue/no-dupe-keys
|
|
121
123
|
ui,
|
|
122
|
-
inputId,
|
|
123
124
|
attrs,
|
|
124
125
|
pick,
|
|
125
126
|
// eslint-disable-next-line vue/no-dupe-keys
|
|
@@ -51,14 +51,13 @@ declare const _default: import("vue").DefineComponent<{
|
|
|
51
51
|
};
|
|
52
52
|
}, {
|
|
53
53
|
ui: import("vue").ComputedRef<any>;
|
|
54
|
-
inputId: import("vue").ComputedRef<any>;
|
|
55
54
|
attrs: import("vue").ComputedRef<Pick<{
|
|
56
55
|
[x: string]: unknown;
|
|
57
56
|
}, string>>;
|
|
58
57
|
pick: import("vue").WritableComputedRef<string | number | boolean | Record<string, any>>;
|
|
59
|
-
name: import("vue").ComputedRef<
|
|
58
|
+
name: import("vue").ComputedRef<string | undefined>;
|
|
60
59
|
inputClass: import("vue").ComputedRef<string>;
|
|
61
|
-
}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, "update:modelValue"[], "update:modelValue", import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{
|
|
60
|
+
}, 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<{
|
|
62
61
|
id: {
|
|
63
62
|
type: StringConstructor;
|
|
64
63
|
default: () => string;
|
|
@@ -110,6 +109,7 @@ declare const _default: import("vue").DefineComponent<{
|
|
|
110
109
|
};
|
|
111
110
|
}>> & {
|
|
112
111
|
"onUpdate:modelValue"?: ((...args: any[]) => any) | undefined;
|
|
112
|
+
onChange?: ((...args: any[]) => any) | undefined;
|
|
113
113
|
}, {
|
|
114
114
|
id: string;
|
|
115
115
|
color: any;
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div :class="ui.wrapper">
|
|
3
|
+
<fieldset v-bind="attrs">
|
|
4
|
+
<legend v-if="legend || $slots.legend" :class="ui.legend">
|
|
5
|
+
<slot name="legend">
|
|
6
|
+
{{ legend }}
|
|
7
|
+
</slot>
|
|
8
|
+
</legend>
|
|
9
|
+
<URadio
|
|
10
|
+
v-for="option in normalizedOptions"
|
|
11
|
+
:key="option.value"
|
|
12
|
+
:label="option.label"
|
|
13
|
+
:model-value="modelValue"
|
|
14
|
+
:value="option.value"
|
|
15
|
+
:disabled="disabled"
|
|
16
|
+
:ui="uiRadio"
|
|
17
|
+
@change="onUpdate(option.value)"
|
|
18
|
+
>
|
|
19
|
+
<template #label>
|
|
20
|
+
<slot name="label" v-bind="{ option }" />
|
|
21
|
+
</template>
|
|
22
|
+
</URadio>
|
|
23
|
+
</fieldset>
|
|
24
|
+
</div>
|
|
25
|
+
</template>
|
|
26
|
+
|
|
27
|
+
<script>
|
|
28
|
+
import URadio from "./Radio.vue";
|
|
29
|
+
import { computed, defineComponent, provide, toRef } from "vue";
|
|
30
|
+
import { useUI } from "../../composables/useUI";
|
|
31
|
+
import { useFormGroup } from "../../composables/useFormGroup";
|
|
32
|
+
import { mergeConfig, get } from "../../utils";
|
|
33
|
+
import appConfig from "#build/app.config";
|
|
34
|
+
import { radioGroup, radio } from "#ui/ui.config";
|
|
35
|
+
const config = mergeConfig(appConfig.ui.strategy, appConfig.ui.radioGroup, radioGroup);
|
|
36
|
+
const configRadio = mergeConfig(appConfig.ui.strategy, appConfig.ui.radio, radio);
|
|
37
|
+
export default defineComponent({
|
|
38
|
+
components: {
|
|
39
|
+
URadio
|
|
40
|
+
},
|
|
41
|
+
inheritAttrs: false,
|
|
42
|
+
props: {
|
|
43
|
+
modelValue: {
|
|
44
|
+
type: [String, Number, Object],
|
|
45
|
+
default: ""
|
|
46
|
+
},
|
|
47
|
+
name: {
|
|
48
|
+
type: String,
|
|
49
|
+
default: null
|
|
50
|
+
},
|
|
51
|
+
legend: {
|
|
52
|
+
type: String,
|
|
53
|
+
default: null
|
|
54
|
+
},
|
|
55
|
+
options: {
|
|
56
|
+
type: Array,
|
|
57
|
+
default: () => []
|
|
58
|
+
},
|
|
59
|
+
optionAttribute: {
|
|
60
|
+
type: String,
|
|
61
|
+
default: "label"
|
|
62
|
+
},
|
|
63
|
+
valueAttribute: {
|
|
64
|
+
type: String,
|
|
65
|
+
default: "value"
|
|
66
|
+
},
|
|
67
|
+
disabled: {
|
|
68
|
+
type: Boolean,
|
|
69
|
+
default: false
|
|
70
|
+
},
|
|
71
|
+
color: {
|
|
72
|
+
type: String,
|
|
73
|
+
default: () => config.default.color,
|
|
74
|
+
validator(value) {
|
|
75
|
+
return appConfig.ui.colors.includes(value);
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
class: {
|
|
79
|
+
type: [String, Object, Array],
|
|
80
|
+
default: void 0
|
|
81
|
+
},
|
|
82
|
+
ui: {
|
|
83
|
+
type: Object,
|
|
84
|
+
default: void 0
|
|
85
|
+
},
|
|
86
|
+
uiRadio: {
|
|
87
|
+
type: Object,
|
|
88
|
+
default: void 0
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
emits: ["update:modelValue", "change"],
|
|
92
|
+
setup(props, { emit }) {
|
|
93
|
+
const { ui, attrs } = useUI("radioGroup", toRef(props, "ui"), config, toRef(props, "class"));
|
|
94
|
+
const { ui: uiRadio } = useUI("radio", toRef(props, "uiRadio"), configRadio);
|
|
95
|
+
const { emitFormChange, color, name } = useFormGroup(props, config);
|
|
96
|
+
provide("radio-group", { color, name });
|
|
97
|
+
const onUpdate = (value) => {
|
|
98
|
+
emit("update:modelValue", value);
|
|
99
|
+
emit("change", value);
|
|
100
|
+
emitFormChange();
|
|
101
|
+
};
|
|
102
|
+
const guessOptionValue = (option) => {
|
|
103
|
+
return get(option, props.valueAttribute, get(option, props.optionAttribute));
|
|
104
|
+
};
|
|
105
|
+
const guessOptionText = (option) => {
|
|
106
|
+
return get(option, props.optionAttribute, get(option, props.valueAttribute));
|
|
107
|
+
};
|
|
108
|
+
const normalizeOption = (option) => {
|
|
109
|
+
if (["string", "number", "boolean"].includes(typeof option)) {
|
|
110
|
+
return {
|
|
111
|
+
value: option,
|
|
112
|
+
label: option
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
return {
|
|
116
|
+
...option,
|
|
117
|
+
value: guessOptionValue(option),
|
|
118
|
+
label: guessOptionText(option)
|
|
119
|
+
};
|
|
120
|
+
};
|
|
121
|
+
const normalizedOptions = computed(() => {
|
|
122
|
+
return props.options.map((option) => normalizeOption(option));
|
|
123
|
+
});
|
|
124
|
+
return {
|
|
125
|
+
// eslint-disable-next-line vue/no-dupe-keys
|
|
126
|
+
ui,
|
|
127
|
+
// eslint-disable-next-line vue/no-dupe-keys
|
|
128
|
+
uiRadio,
|
|
129
|
+
attrs,
|
|
130
|
+
normalizedOptions,
|
|
131
|
+
// eslint-disable-next-line vue/no-dupe-keys
|
|
132
|
+
onUpdate
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
</script>
|