nuxt-ui-tools 1.3.0 → 1.4.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.json +1 -1
- package/dist/module.mjs +8 -1
- package/dist/runtime/form/components/actions/form-actions.vue +13 -127
- package/dist/runtime/form/components/page/form-page-actions.d.vue.ts +3 -0
- package/dist/runtime/form/components/page/form-page-actions.vue +40 -0
- package/dist/runtime/form/components/page/form-page-actions.vue.d.ts +3 -0
- package/dist/runtime/form/components/page/form-page-header.d.vue.ts +24 -0
- package/dist/runtime/form/components/page/form-page-header.vue +99 -0
- package/dist/runtime/form/components/page/form-page-header.vue.d.ts +24 -0
- package/dist/runtime/form/components/page/form-page-navigation.d.vue.ts +34 -0
- package/dist/runtime/form/components/page/form-page-navigation.vue +229 -0
- package/dist/runtime/form/components/page/form-page-navigation.vue.d.ts +34 -0
- package/dist/runtime/form/components/page/form-page-section.d.vue.ts +19 -0
- package/dist/runtime/form/components/page/form-page-section.vue +114 -0
- package/dist/runtime/form/components/page/form-page-section.vue.d.ts +19 -0
- package/dist/runtime/form/components/page/form-page-sections.d.vue.ts +21 -0
- package/dist/runtime/form/components/page/form-page-sections.vue +75 -0
- package/dist/runtime/form/components/page/form-page-sections.vue.d.ts +21 -0
- package/dist/runtime/form/components/page/form-page.d.vue.ts +80 -0
- package/dist/runtime/form/components/page/form-page.vue +91 -0
- package/dist/runtime/form/components/page/form-page.vue.d.ts +80 -0
- package/dist/runtime/form/components/renderer/form-field-shell.vue +7 -11
- package/dist/runtime/form/components/root/form.vue +25 -194
- package/dist/runtime/form/composables/use-form-action-buttons.d.ts +32 -0
- package/dist/runtime/form/composables/use-form-action-buttons.js +89 -0
- package/dist/runtime/form/composables/use-form-actions.d.ts +8 -5
- package/dist/runtime/form/composables/use-form-actions.js +1 -1
- package/dist/runtime/form/composables/use-form-page-scroll.d.ts +22 -0
- package/dist/runtime/form/composables/use-form-page-scroll.js +178 -0
- package/dist/runtime/form/composables/use-form-page.d.ts +114 -0
- package/dist/runtime/form/composables/use-form-page.js +83 -0
- package/dist/runtime/form/composables/use-form-root.d.ts +34 -0
- package/dist/runtime/form/composables/use-form-root.js +171 -0
- package/dist/runtime/form/composables/use-form-runtime.js +13 -4
- package/dist/runtime/form/composables/use-form.js +2 -22
- package/dist/runtime/form/fields/checkbox-card/component.vue +28 -19
- package/dist/runtime/form/fields/checkbox-card/types.d.ts +2 -5
- package/dist/runtime/form/fields/choice-card/choice-card-label.d.vue.ts +17 -0
- package/dist/runtime/form/fields/choice-card/choice-card-label.vue +50 -0
- package/dist/runtime/form/fields/choice-card/choice-card-label.vue.d.ts +17 -0
- package/dist/runtime/form/fields/choice-card/types.d.ts +31 -0
- package/dist/runtime/form/fields/choice-card/types.js +0 -0
- package/dist/runtime/form/fields/choice-card/use-choice-card.d.ts +22 -0
- package/dist/runtime/form/fields/choice-card/use-choice-card.js +52 -0
- package/dist/runtime/form/fields/radio-card/component.vue +17 -18
- package/dist/runtime/form/fields/radio-card/types.d.ts +2 -4
- package/dist/runtime/form/index.d.ts +1 -1
- package/dist/runtime/form/index.js +7 -1
- package/dist/runtime/form/schema/index.d.ts +1 -1
- package/dist/runtime/form/schema/index.js +1 -0
- package/dist/runtime/form/schema/page.d.ts +50 -0
- package/dist/runtime/form/schema/page.js +25 -0
- package/dist/runtime/form/types/index.d.ts +1 -0
- package/dist/runtime/form/types/page.d.ts +172 -0
- package/dist/runtime/form/types/page.js +0 -0
- package/dist/runtime/form/types/ui.d.ts +60 -0
- package/dist/runtime/form/utils/controls.d.ts +15 -0
- package/dist/runtime/form/utils/controls.js +38 -0
- package/dist/runtime/form/utils/layout.js +3 -1
- package/dist/runtime/form/utils/page.d.ts +20 -0
- package/dist/runtime/form/utils/page.js +107 -0
- package/dist/runtime/form/utils/state.d.ts +2 -0
- package/dist/runtime/form/utils/state.js +1 -1
- package/dist/runtime/form/utils/ui.js +1 -0
- package/dist/runtime/i18n/locales/en.js +18 -0
- package/dist/runtime/i18n/locales/fr.js +18 -0
- package/dist/runtime/i18n/types.d.ts +29 -0
- package/package.json +1 -1
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { createFormFieldInstance } from "./field-instance.js";
|
|
2
|
+
import { getPathValue, isRecord } from "./path.js";
|
|
3
|
+
import { isBoolean, isFunction, isNumber, isString } from "./predicate.js";
|
|
4
|
+
import {
|
|
5
|
+
fieldPath,
|
|
6
|
+
getChildFields,
|
|
7
|
+
getSchemaFields,
|
|
8
|
+
isEmptyValue,
|
|
9
|
+
isFlatPassthroughField,
|
|
10
|
+
isObjectContainerField,
|
|
11
|
+
resolveRequired
|
|
12
|
+
} from "./state.js";
|
|
13
|
+
import { resolveFormText } from "./text.js";
|
|
14
|
+
export function getFormPageSections(schema) {
|
|
15
|
+
if (!isRecord(schema) || !Array.isArray(schema.sections)) {
|
|
16
|
+
return [];
|
|
17
|
+
}
|
|
18
|
+
const cards = getSchemaFields(schema);
|
|
19
|
+
return schema.sections.filter(isFormPageSection).flatMap((section) => {
|
|
20
|
+
const card = cards.find((field) => field.key === section.key);
|
|
21
|
+
return card ? [{ card, section }] : [];
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
export function getFormPageNavigationTitle(schema) {
|
|
25
|
+
if (!isRecord(schema) || !isRecord(schema.navigation)) {
|
|
26
|
+
return void 0;
|
|
27
|
+
}
|
|
28
|
+
const { title } = schema.navigation;
|
|
29
|
+
return isFormText(title) ? resolveFormText(title) : void 0;
|
|
30
|
+
}
|
|
31
|
+
export function isFormPageSectionVisible(entry, runtime) {
|
|
32
|
+
return !hasCondition(entry.card) || runtime.shouldRender(entry.card, [entry.card.key]);
|
|
33
|
+
}
|
|
34
|
+
export function resolveFormPageSectionState(params) {
|
|
35
|
+
const { entry, runtime } = params;
|
|
36
|
+
const leaves = collectVisibleLeaves(entry.section.fields, [], runtime);
|
|
37
|
+
const paths = leaves.map((leaf) => leaf.path.join("."));
|
|
38
|
+
const contains = (candidate) => paths.some((path) => isPathWithin(candidate, path));
|
|
39
|
+
const dirtyPaths = runtime.dirtyPaths.value.filter(contains);
|
|
40
|
+
const invalid = runtime.errors.value.some((error) => contains(error.path));
|
|
41
|
+
const required = params.requiredEnforced ? leaves.filter((leaf) => isRequiredLeaf(leaf, runtime)) : [];
|
|
42
|
+
const missing = required.filter((leaf) => isEmptyValue(runtime.getValue(leaf.path))).length;
|
|
43
|
+
const optional = entry.section.optional === true || required.length === 0;
|
|
44
|
+
const filled = !optional || leaves.some((leaf) => isProvided(leaf, runtime, dirtyPaths, params.input));
|
|
45
|
+
return {
|
|
46
|
+
description: resolveFormText(entry.section.description),
|
|
47
|
+
dirty: dirtyPaths.length > 0,
|
|
48
|
+
dirtyPaths,
|
|
49
|
+
index: params.index,
|
|
50
|
+
key: entry.section.key,
|
|
51
|
+
label: resolveFormText(entry.section.label) ?? entry.section.key,
|
|
52
|
+
missing,
|
|
53
|
+
optional,
|
|
54
|
+
status: invalid ? "invalid" : missing === 0 && filled ? "complete" : "pending"
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
function collectVisibleLeaves(fields, parentPath, runtime) {
|
|
58
|
+
return fields.flatMap((field) => {
|
|
59
|
+
if (field.ignore === true) {
|
|
60
|
+
return [];
|
|
61
|
+
}
|
|
62
|
+
const path = fieldPath(parentPath, field);
|
|
63
|
+
if (hasCondition(field) && !runtime.shouldRender(field, path)) {
|
|
64
|
+
return [];
|
|
65
|
+
}
|
|
66
|
+
if (createFormFieldInstance(field).state.is("stateless")) {
|
|
67
|
+
return [];
|
|
68
|
+
}
|
|
69
|
+
if (isFlatPassthroughField(field)) {
|
|
70
|
+
return collectVisibleLeaves(getChildFields(field), parentPath, runtime);
|
|
71
|
+
}
|
|
72
|
+
if (isObjectContainerField(field)) {
|
|
73
|
+
return collectVisibleLeaves(getChildFields(field), path, runtime);
|
|
74
|
+
}
|
|
75
|
+
return [{ field, path }];
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
function isRequiredLeaf(leaf, runtime) {
|
|
79
|
+
const required = Object.getOwnPropertyDescriptor(leaf.field, "required")?.value;
|
|
80
|
+
if (isBoolean(required)) {
|
|
81
|
+
return required;
|
|
82
|
+
}
|
|
83
|
+
const validation = Object.getOwnPropertyDescriptor(leaf.field, "validation")?.value;
|
|
84
|
+
if (!isFunction(required) && !isRecord(validation)) {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
return resolveRequired(leaf.field, runtime.getFieldCallbackParams(leaf.path, leaf.field)) === true;
|
|
88
|
+
}
|
|
89
|
+
function isProvided(leaf, runtime, dirtyPaths, input) {
|
|
90
|
+
if (isEmptyValue(runtime.getValue(leaf.path))) {
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
const path = leaf.path.join(".");
|
|
94
|
+
return dirtyPaths.some((dirtyPath) => isPathWithin(dirtyPath, path)) || !isEmptyValue(getPathValue(input ?? {}, leaf.path));
|
|
95
|
+
}
|
|
96
|
+
function hasCondition(field) {
|
|
97
|
+
return isFunction(Object.getOwnPropertyDescriptor(field, "condition")?.value);
|
|
98
|
+
}
|
|
99
|
+
function isPathWithin(path, scope) {
|
|
100
|
+
return path === scope || path.startsWith(`${scope}.`);
|
|
101
|
+
}
|
|
102
|
+
function isFormPageSection(value) {
|
|
103
|
+
return isRecord(value) && isString(value.key) && isFormText(value.label) && Array.isArray(value.fields);
|
|
104
|
+
}
|
|
105
|
+
function isFormText(value) {
|
|
106
|
+
return isString(value) || isNumber(value) || isFunction(value);
|
|
107
|
+
}
|
|
@@ -30,4 +30,6 @@ export declare function getMatrixRows(field: FormField): any[];
|
|
|
30
30
|
export declare function resolveRequired(field: FormField, params: FormFieldCallbackParams): any;
|
|
31
31
|
export declare function resolveRequiredMessage(field: FormField, fallback?: string): string;
|
|
32
32
|
export declare function isEmptyValue(value: FormValue): boolean;
|
|
33
|
+
/** Child fields of a container, with the fields of every tab for tabs. */
|
|
34
|
+
export declare function getChildFields(field: FormField): FormField[];
|
|
33
35
|
export declare function getArrayItemFields(field: FormField, item: FormObject): FormField[];
|
|
@@ -588,7 +588,7 @@ function isFormField(value) {
|
|
|
588
588
|
const type = Object.getOwnPropertyDescriptor(value, "type")?.value;
|
|
589
589
|
return isString(value.key) && isString(type) && isRegisteredFormFieldType(type);
|
|
590
590
|
}
|
|
591
|
-
function getChildFields(field) {
|
|
591
|
+
export function getChildFields(field) {
|
|
592
592
|
const tabs = Object.getOwnPropertyDescriptor(field, "tabs")?.value;
|
|
593
593
|
if (Array.isArray(tabs)) {
|
|
594
594
|
return tabs.flatMap((tab) => {
|
|
@@ -39,6 +39,7 @@ function mergeFormUiPair(current, next) {
|
|
|
39
39
|
group: mergePart(current.group, next.group),
|
|
40
40
|
matrix: mergePart(current.matrix, next.matrix),
|
|
41
41
|
modal: mergePart(current.modal, next.modal),
|
|
42
|
+
page: mergePart(current.page, next.page),
|
|
42
43
|
root: mergePart(current.root, next.root),
|
|
43
44
|
tree: mergePart(current.tree, next.tree),
|
|
44
45
|
treeSelect: mergePart(current.treeSelect, next.treeSelect)
|
|
@@ -101,6 +101,24 @@ export default defineUiToolsLocale({
|
|
|
101
101
|
resetButton: "Reset",
|
|
102
102
|
submitButton: "Submit"
|
|
103
103
|
},
|
|
104
|
+
page: {
|
|
105
|
+
complete: "Everything is ready.",
|
|
106
|
+
modifiedOne: "{count} modified.",
|
|
107
|
+
modifiedOther: "{count} modified.",
|
|
108
|
+
navigation: "Form sections",
|
|
109
|
+
optional: "optional",
|
|
110
|
+
remaining: "{count} left to complete.",
|
|
111
|
+
resetSection: "Reset",
|
|
112
|
+
sectionsOne: "{count} section",
|
|
113
|
+
sectionsOther: "{count} sections",
|
|
114
|
+
status: {
|
|
115
|
+
complete: "Complete",
|
|
116
|
+
invalid: "Has errors",
|
|
117
|
+
pending: "To complete"
|
|
118
|
+
},
|
|
119
|
+
unmodified: "No unsaved changes.",
|
|
120
|
+
unsavedChanges: "Unsaved changes"
|
|
121
|
+
},
|
|
104
122
|
fields: {
|
|
105
123
|
array: {
|
|
106
124
|
addItem: "Add item",
|
|
@@ -101,6 +101,24 @@ export default defineUiToolsLocale({
|
|
|
101
101
|
resetButton: "R\xE9initialiser",
|
|
102
102
|
submitButton: "Soumettre"
|
|
103
103
|
},
|
|
104
|
+
page: {
|
|
105
|
+
complete: "Tout est pr\xEAt.",
|
|
106
|
+
modifiedOne: "{count} modifi\xE9e.",
|
|
107
|
+
modifiedOther: "{count} modifi\xE9es.",
|
|
108
|
+
navigation: "Sections du formulaire",
|
|
109
|
+
optional: "optionnel",
|
|
110
|
+
remaining: "{count} \xE0 compl\xE9ter.",
|
|
111
|
+
resetSection: "R\xE9initialiser",
|
|
112
|
+
sectionsOne: "{count} section",
|
|
113
|
+
sectionsOther: "{count} sections",
|
|
114
|
+
status: {
|
|
115
|
+
complete: "Compl\xE8te",
|
|
116
|
+
invalid: "Contient des erreurs",
|
|
117
|
+
pending: "\xC0 compl\xE9ter"
|
|
118
|
+
},
|
|
119
|
+
unmodified: "Aucune modification en cours.",
|
|
120
|
+
unsavedChanges: "Modifications non enregistr\xE9es"
|
|
121
|
+
},
|
|
104
122
|
fields: {
|
|
105
123
|
array: {
|
|
106
124
|
addItem: "Ajouter un \xE9l\xE9ment",
|
|
@@ -275,6 +275,35 @@ export interface UiToolsFormMessages {
|
|
|
275
275
|
cancelButton: string;
|
|
276
276
|
resetButton: string;
|
|
277
277
|
};
|
|
278
|
+
/** Form page chrome. Counts use `Intl.PluralRules`: `One` for "one", `Other` otherwise. */
|
|
279
|
+
page: {
|
|
280
|
+
/** Accessible name of the section navigation when the schema gives it no title. */
|
|
281
|
+
navigation: string;
|
|
282
|
+
/** Marks an optional section, in the navigation and on its card. */
|
|
283
|
+
optional: string;
|
|
284
|
+
/** Badge under the page title and name of a section's dirty marker. */
|
|
285
|
+
unsavedChanges: string;
|
|
286
|
+
/** Button of a modified section that puts its values back. */
|
|
287
|
+
resetSection: string;
|
|
288
|
+
/** Bold count inserted in `remaining` and `modified`: "{count} sections". */
|
|
289
|
+
sectionsOne: string;
|
|
290
|
+
sectionsOther: string;
|
|
291
|
+
/** Navigation summary while required sections are incomplete: "{count} to complete." */
|
|
292
|
+
remaining: string;
|
|
293
|
+
/** Navigation summary once every required section is complete. */
|
|
294
|
+
complete: string;
|
|
295
|
+
/** Navigation summary of a form with dirty checking: "{count} modified." */
|
|
296
|
+
modifiedOne: string;
|
|
297
|
+
modifiedOther: string;
|
|
298
|
+
/** Navigation summary of a form with dirty checking and no change. */
|
|
299
|
+
unmodified: string;
|
|
300
|
+
/** Accessible status of a navigation entry. */
|
|
301
|
+
status: {
|
|
302
|
+
complete: string;
|
|
303
|
+
pending: string;
|
|
304
|
+
invalid: string;
|
|
305
|
+
};
|
|
306
|
+
};
|
|
278
307
|
states: {
|
|
279
308
|
contextError: {
|
|
280
309
|
title: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nuxt-ui-tools",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
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",
|