nuxt-ui-tools 1.16.7 → 1.16.9
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.json +1 -1
- package/dist/runtime/form/components/renderer/form-field-renderer.vue +2 -1
- package/dist/runtime/form/components/root/form.vue +7 -1
- package/dist/runtime/form/composables/use-form-validation.js +7 -1
- package/dist/runtime/form/fields/checkbox-card/component.vue +2 -1
- package/dist/runtime/form/fields/choice-card/choice-card-label.d.vue.ts +9 -4
- package/dist/runtime/form/fields/choice-card/choice-card-label.vue +26 -2
- package/dist/runtime/form/fields/choice-card/choice-card-label.vue.d.ts +9 -4
- package/dist/runtime/form/fields/choice-card/types.d.ts +9 -4
- package/dist/runtime/form/fields/choice-card/use-choice-card.d.ts +3 -3
- package/dist/runtime/form/fields/choice-card/use-choice-card.js +9 -5
- package/dist/runtime/form/fields/radio-card/component.vue +2 -1
- package/package.json +1 -1
package/dist/module.json
CHANGED
|
@@ -86,6 +86,7 @@ const controlAttrs = computed(() => {
|
|
|
86
86
|
provideFormFieldBare(bare);
|
|
87
87
|
provideFormFieldControlAttrs(controlAttrs);
|
|
88
88
|
const field = computed(() => createFormFieldInstance(props.field));
|
|
89
|
+
const headless = computed(() => !field.value.capability.has("layout"));
|
|
89
90
|
const path = computed(() => fieldPath(props.parentPath, props.field));
|
|
90
91
|
const childPath = computed(() => childParentPath(props.parentPath, props.field));
|
|
91
92
|
const visible = computed(() => form.shouldRender(props.field, path.value));
|
|
@@ -200,7 +201,7 @@ function resolveControlLabel(controlField) {
|
|
|
200
201
|
</script>
|
|
201
202
|
|
|
202
203
|
<template>
|
|
203
|
-
<template v-if="visible && bare">
|
|
204
|
+
<template v-if="visible && (bare || headless)">
|
|
204
205
|
<component :is="renderer" v-if="renderer" v-bind="rendererProps" />
|
|
205
206
|
<UAlert
|
|
206
207
|
v-else
|
|
@@ -9,6 +9,7 @@ import { useUiToolsLocale } from "#ui-tools/i18n";
|
|
|
9
9
|
import { useFormActions } from "../../composables/use-form-actions";
|
|
10
10
|
import { useFormGridLayout } from "../../composables/use-form-layout";
|
|
11
11
|
import { useFormRoot } from "../../composables/use-form-root";
|
|
12
|
+
import { createFormFieldInstance } from "../../utils/field-instance";
|
|
12
13
|
import { getFormHeader } from "../../utils/overlay";
|
|
13
14
|
import { isRecord } from "../../utils/path";
|
|
14
15
|
import { isFunction, isNumber, isString } from "../../utils/predicate";
|
|
@@ -69,6 +70,11 @@ watch(
|
|
|
69
70
|
const displayedStep = computed(
|
|
70
71
|
() => isSteppedSchema(schemaRef.value) ? getSchemaSteps(schemaRef.value)[displayedStepIndex.value] : void 0
|
|
71
72
|
);
|
|
73
|
+
const skeletonFields = computed(
|
|
74
|
+
() => runtime.currentFields.value.filter(
|
|
75
|
+
(field) => createFormFieldInstance(field).capability.has("layout")
|
|
76
|
+
)
|
|
77
|
+
);
|
|
72
78
|
const displayedFields = computed(
|
|
73
79
|
() => isSteppedSchema(schemaRef.value) ? displayedStep.value?.fields ?? [] : getSchemaFields(schemaRef.value)
|
|
74
80
|
);
|
|
@@ -295,7 +301,7 @@ function getSchemaShowStepper(schema) {
|
|
|
295
301
|
:style="grid.style.value"
|
|
296
302
|
>
|
|
297
303
|
<div
|
|
298
|
-
v-for="field in
|
|
304
|
+
v-for="field in skeletonFields"
|
|
299
305
|
:key="field.key"
|
|
300
306
|
:class="mergeFormUiClass('grid gap-2', formUi.ui.value.root?.ui?.skeletonField)"
|
|
301
307
|
>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useRegle } from "@regle/core";
|
|
1
|
+
import { markStatic, useRegle } from "@regle/core";
|
|
2
2
|
import { withMessage } from "@regle/rules";
|
|
3
3
|
import { computed, nextTick, reactive, ref, unref, watch } from "vue";
|
|
4
4
|
import { calendarSeedFromValue, isDateFamilyRange } from "../fields/date-family/utils.js";
|
|
@@ -387,6 +387,12 @@ function buildFieldRules(params) {
|
|
|
387
387
|
continue;
|
|
388
388
|
}
|
|
389
389
|
const path = fieldPath(params.parentPath, field);
|
|
390
|
+
if (fieldInstance.type.is("custom-component")) {
|
|
391
|
+
const value = getPathValue(params.state, path);
|
|
392
|
+
if (isRecord(value)) {
|
|
393
|
+
markStatic(value);
|
|
394
|
+
}
|
|
395
|
+
}
|
|
390
396
|
const api = params.apiFactory(path, field);
|
|
391
397
|
const callbackParams = {
|
|
392
398
|
api,
|
|
@@ -65,8 +65,9 @@ function isOptionValue(value) {
|
|
|
65
65
|
<ChoiceCardLabel
|
|
66
66
|
:label="optionByKey.get(item.value)?.label ?? item.label"
|
|
67
67
|
:icon="optionByKey.get(item.value)?.icon"
|
|
68
|
+
:value="optionByKey.get(item.value)?.value"
|
|
68
69
|
:tile="cards.tile.value"
|
|
69
|
-
:
|
|
70
|
+
:mark="cards.mark.value"
|
|
70
71
|
:selected="model.includes(item.value)"
|
|
71
72
|
:ui="cards.ui.value"
|
|
72
73
|
/>
|
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
import type { FormControlUi } from '../../types/index.js';
|
|
2
|
+
import type { ChoiceCardMark } from './types.js';
|
|
2
3
|
/**
|
|
3
|
-
* Content of a card's label: the option icon, inline or in a tile above the label, and the
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Content of a card's label: the option icon, inline or in a tile above the label, and the
|
|
5
|
+
* selection mark the card draws itself: a check in the corner of a selected card, or a switch
|
|
6
|
+
* that follows the selection. Both marks are decorative; the group's own control keeps the
|
|
7
|
+
* semantics. Styled through `ui.tile`, `ui.tileIcon`, `ui.optionIcon`, `ui.check`,
|
|
8
|
+
* `ui.checkIcon`, `ui.switch`, and `ui.switchThumb`; the tile and the switch carry the option
|
|
9
|
+
* value as `data-value` for per-option styling.
|
|
6
10
|
*/
|
|
7
11
|
type __VLS_Props = {
|
|
8
12
|
label?: string;
|
|
9
13
|
icon?: string;
|
|
14
|
+
value?: string | number | boolean;
|
|
10
15
|
tile: boolean;
|
|
11
|
-
|
|
16
|
+
mark: ChoiceCardMark;
|
|
12
17
|
selected: boolean;
|
|
13
18
|
ui?: FormControlUi;
|
|
14
19
|
};
|
|
@@ -4,8 +4,9 @@ import { mergeFormUiClass } from "../../utils/ui";
|
|
|
4
4
|
defineProps({
|
|
5
5
|
label: { type: String, required: false },
|
|
6
6
|
icon: { type: String, required: false },
|
|
7
|
+
value: { type: [String, Number, Boolean], required: false },
|
|
7
8
|
tile: { type: Boolean, required: true },
|
|
8
|
-
|
|
9
|
+
mark: { type: String, required: true },
|
|
9
10
|
selected: { type: Boolean, required: true },
|
|
10
11
|
ui: { type: Object, required: false }
|
|
11
12
|
});
|
|
@@ -15,6 +16,7 @@ defineProps({
|
|
|
15
16
|
<span
|
|
16
17
|
v-if="tile && icon"
|
|
17
18
|
:data-selected="selected || void 0"
|
|
19
|
+
:data-value="value"
|
|
18
20
|
:class="
|
|
19
21
|
mergeFormUiClass(
|
|
20
22
|
'grid size-8 place-items-center rounded-lg bg-elevated text-muted transition-colors data-[selected]:bg-primary/10 data-[selected]:text-primary',
|
|
@@ -35,7 +37,7 @@ defineProps({
|
|
|
35
37
|
</span>
|
|
36
38
|
<span v-else class="block">{{ label }}</span>
|
|
37
39
|
<span
|
|
38
|
-
v-if="corner && selected"
|
|
40
|
+
v-if="mark === 'corner' && selected"
|
|
39
41
|
aria-hidden="true"
|
|
40
42
|
:class="
|
|
41
43
|
mergeFormUiClass(
|
|
@@ -47,4 +49,26 @@ defineProps({
|
|
|
47
49
|
>
|
|
48
50
|
<UIcon name="i-lucide-check" :class="mergeFormUiClass('size-2.5', ui?.checkIcon)" />
|
|
49
51
|
</span>
|
|
52
|
+
<span
|
|
53
|
+
v-if="mark === 'switch'"
|
|
54
|
+
aria-hidden="true"
|
|
55
|
+
:data-state="selected ? 'checked' : 'unchecked'"
|
|
56
|
+
:data-value="value"
|
|
57
|
+
:class="
|
|
58
|
+
mergeFormUiClass(
|
|
59
|
+
'group/switch absolute end-3 top-3.5 inline-flex h-[18px] w-8 shrink-0 items-center rounded-full bg-accented p-0.5 transition-colors duration-150 data-[state=checked]:bg-primary',
|
|
60
|
+
ui?.switch
|
|
61
|
+
)
|
|
62
|
+
"
|
|
63
|
+
data-choice-switch
|
|
64
|
+
>
|
|
65
|
+
<span
|
|
66
|
+
:class="
|
|
67
|
+
mergeFormUiClass(
|
|
68
|
+
'size-3.5 rounded-full bg-default shadow-xs transition-transform duration-150 group-data-[state=checked]/switch:translate-x-3.5 motion-reduce:transition-none rtl:group-data-[state=checked]/switch:-translate-x-3.5',
|
|
69
|
+
ui?.switchThumb
|
|
70
|
+
)
|
|
71
|
+
"
|
|
72
|
+
/>
|
|
73
|
+
</span>
|
|
50
74
|
</template>
|
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
import type { FormControlUi } from '../../types/index.js';
|
|
2
|
+
import type { ChoiceCardMark } from './types.js';
|
|
2
3
|
/**
|
|
3
|
-
* Content of a card's label: the option icon, inline or in a tile above the label, and the
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Content of a card's label: the option icon, inline or in a tile above the label, and the
|
|
5
|
+
* selection mark the card draws itself: a check in the corner of a selected card, or a switch
|
|
6
|
+
* that follows the selection. Both marks are decorative; the group's own control keeps the
|
|
7
|
+
* semantics. Styled through `ui.tile`, `ui.tileIcon`, `ui.optionIcon`, `ui.check`,
|
|
8
|
+
* `ui.checkIcon`, `ui.switch`, and `ui.switchThumb`; the tile and the switch carry the option
|
|
9
|
+
* value as `data-value` for per-option styling.
|
|
6
10
|
*/
|
|
7
11
|
type __VLS_Props = {
|
|
8
12
|
label?: string;
|
|
9
13
|
icon?: string;
|
|
14
|
+
value?: string | number | boolean;
|
|
10
15
|
tile: boolean;
|
|
11
|
-
|
|
16
|
+
mark: ChoiceCardMark;
|
|
12
17
|
selected: boolean;
|
|
13
18
|
ui?: FormControlUi;
|
|
14
19
|
};
|
|
@@ -18,14 +18,19 @@ export interface FormChoiceCardProps {
|
|
|
18
18
|
orientation?: 'horizontal' | 'vertical';
|
|
19
19
|
/**
|
|
20
20
|
* Selection mark: the radio or checkbox before the content (`start`, the default), after it
|
|
21
|
-
* (`end`), none (`hidden`),
|
|
21
|
+
* (`end`), none (`hidden`), a check in the top corner of the selected cards (`corner`), or a
|
|
22
|
+
* switch in the top corner of every card that turns on with the selection (`switch`), for cards
|
|
23
|
+
* that enable something.
|
|
22
24
|
*/
|
|
23
|
-
indicator?: 'start' | 'end' | 'hidden' | 'corner';
|
|
25
|
+
indicator?: 'start' | 'end' | 'hidden' | 'corner' | 'switch';
|
|
24
26
|
/**
|
|
25
27
|
* Where an option's `icon` shows: before its label (`inline`, the default), or in a tile above
|
|
26
28
|
* it (`tile`) that takes the selection color. Style the parts the engine renders with the
|
|
27
|
-
* `ui` slots `tile`, `tileIcon`, `optionIcon`, `check`,
|
|
28
|
-
* slots of the group.
|
|
29
|
+
* `ui` slots `tile`, `tileIcon`, `optionIcon`, `check`, `checkIcon`, `switch`, and
|
|
30
|
+
* `switchThumb`, next to the Nuxt UI slots of the group. The tile and the switch carry the
|
|
31
|
+
* option value as `data-value`, so one option can take its own colors.
|
|
29
32
|
*/
|
|
30
33
|
icon?: 'inline' | 'tile';
|
|
31
34
|
}
|
|
35
|
+
/** The mark a card draws itself, in place of the Nuxt UI indicator. */
|
|
36
|
+
export type ChoiceCardMark = 'corner' | 'switch' | 'none';
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import type { FormControlUi } from '../../types/index.js';
|
|
2
|
-
import type { FormChoiceCardProps } from './types.js';
|
|
2
|
+
import type { ChoiceCardMark, FormChoiceCardProps } from './types.js';
|
|
3
3
|
/** Props the card fields render themselves, kept away from the Nuxt UI group. */
|
|
4
4
|
export declare const CHOICE_CARD_PROPS: string[];
|
|
5
5
|
/**
|
|
6
6
|
* Presentation of a radio or checkbox card group: the flowing row or fixed grid of cards, the
|
|
7
7
|
* selection mark, and where option icons go. Returns the props and `ui` slots for the Nuxt UI
|
|
8
|
-
* group, and what the card content renders (`tile`, `
|
|
8
|
+
* group, and what the card content renders (`tile`, `mark`).
|
|
9
9
|
*/
|
|
10
10
|
export declare function useChoiceCard(params: {
|
|
11
11
|
props: () => FormChoiceCardProps;
|
|
12
12
|
ui: () => FormControlUi | undefined;
|
|
13
13
|
}): {
|
|
14
|
-
corner: import("vue").ComputedRef<boolean>;
|
|
15
14
|
indicator: import("vue").ComputedRef<"end" | "start" | "hidden" | undefined>;
|
|
15
|
+
mark: import("vue").ComputedRef<ChoiceCardMark>;
|
|
16
16
|
orientation: import("vue").ComputedRef<"horizontal" | "vertical" | undefined>;
|
|
17
17
|
style: import("vue").ComputedRef<{
|
|
18
18
|
'--nut-choice-columns': string;
|
|
@@ -9,11 +9,14 @@ export function useChoiceCard(params) {
|
|
|
9
9
|
const count = Math.trunc(Number(columnsValue.value));
|
|
10
10
|
return count > 0 ? count : void 0;
|
|
11
11
|
});
|
|
12
|
-
const
|
|
12
|
+
const mark = computed(() => {
|
|
13
|
+
const value = params.props().indicator;
|
|
14
|
+
return value === "corner" || value === "switch" ? value : "none";
|
|
15
|
+
});
|
|
13
16
|
const tile = computed(() => params.props().icon === "tile");
|
|
14
17
|
const indicator = computed(() => {
|
|
15
18
|
const value = params.props().indicator;
|
|
16
|
-
return value === "corner" ? "hidden" : value;
|
|
19
|
+
return value === "corner" || value === "switch" ? "hidden" : value;
|
|
17
20
|
});
|
|
18
21
|
const orientation = computed(() => params.props().orientation);
|
|
19
22
|
const style = computed(
|
|
@@ -29,7 +32,7 @@ export function useChoiceCard(params) {
|
|
|
29
32
|
),
|
|
30
33
|
item: mergeFormUiClass(
|
|
31
34
|
`border-default ${CARD_SELECTED_RING}`,
|
|
32
|
-
|
|
35
|
+
mark.value === "none" ? void 0 : "relative",
|
|
33
36
|
current?.item
|
|
34
37
|
),
|
|
35
38
|
// The card label renders the option icon itself (inline or as a tile): Nuxt UI's own copy
|
|
@@ -45,11 +48,12 @@ export function useChoiceCard(params) {
|
|
|
45
48
|
tile.value ? "flex flex-col items-start gap-1.5" : void 0,
|
|
46
49
|
[
|
|
47
50
|
indicator.value === "hidden" ? "ms-0 text-start" : "",
|
|
48
|
-
|
|
51
|
+
mark.value === "corner" && !tile.value ? "pe-7" : "",
|
|
52
|
+
mark.value === "switch" && !tile.value ? "pe-12" : ""
|
|
49
53
|
].join(" "),
|
|
50
54
|
current?.wrapper
|
|
51
55
|
)
|
|
52
56
|
};
|
|
53
57
|
});
|
|
54
|
-
return {
|
|
58
|
+
return { indicator, mark, orientation, style, tile, ui };
|
|
55
59
|
}
|
|
@@ -49,8 +49,9 @@ const items = computed(() => [...options.items.value]);
|
|
|
49
49
|
<ChoiceCardLabel
|
|
50
50
|
:label="item.label"
|
|
51
51
|
:icon="item.icon"
|
|
52
|
+
:value="item.value"
|
|
52
53
|
:tile="cards.tile.value"
|
|
53
|
-
:
|
|
54
|
+
:mark="cards.mark.value"
|
|
54
55
|
:selected="model === item.value"
|
|
55
56
|
:ui="cards.ui.value"
|
|
56
57
|
/>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nuxt-ui-tools",
|
|
3
|
-
"version": "1.16.
|
|
3
|
+
"version": "1.16.9",
|
|
4
4
|
"description": "Nuxt module and runtime toolkit for UI-heavy Nuxt applications",
|
|
5
5
|
"homepage": "https://github.com/ChronicStone/nuxt-ui-tools#readme",
|
|
6
6
|
"bugs": "https://github.com/ChronicStone/nuxt-ui-tools/issues",
|