nuxt-ui-tools 1.17.1 → 1.19.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 +1 -0
- package/dist/runtime/form/components/page/form-page-header.d.vue.ts +3 -1
- package/dist/runtime/form/components/page/form-page-header.vue +44 -34
- package/dist/runtime/form/components/page/form-page-header.vue.d.ts +3 -1
- package/dist/runtime/form/components/page/form-page-navigation.d.vue.ts +5 -3
- package/dist/runtime/form/components/page/form-page-navigation.vue +6 -3
- package/dist/runtime/form/components/page/form-page-navigation.vue.d.ts +5 -3
- package/dist/runtime/form/components/page/form-page-section.vue +6 -5
- package/dist/runtime/form/components/page/form-page-sections.d.vue.ts +4 -3
- package/dist/runtime/form/components/page/form-page-sections.vue +7 -2
- package/dist/runtime/form/components/page/form-page-sections.vue.d.ts +4 -3
- package/dist/runtime/form/components/page/form-page.d.vue.ts +2 -0
- package/dist/runtime/form/components/page/form-page.vue +11 -2
- package/dist/runtime/form/components/page/form-page.vue.d.ts +2 -0
- package/dist/runtime/form/components/renderer/form-field-renderer.vue +6 -4
- package/dist/runtime/form/components/renderer/form-field-shell.d.vue.ts +4 -4
- package/dist/runtime/form/components/renderer/form-field-shell.vue +28 -4
- package/dist/runtime/form/components/renderer/form-field-shell.vue.d.ts +4 -4
- package/dist/runtime/form/components/root/form.vue +2 -2
- package/dist/runtime/form/components/utils/form-option-choice-label.d.vue.ts +16 -0
- package/dist/runtime/form/components/utils/form-option-choice-label.vue +37 -0
- package/dist/runtime/form/components/utils/form-option-choice-label.vue.d.ts +16 -0
- package/dist/runtime/form/components/utils/form-option-display-value.d.vue.ts +14 -0
- package/dist/runtime/form/components/utils/form-option-display-value.vue +20 -0
- package/dist/runtime/form/components/utils/form-option-display-value.vue.d.ts +14 -0
- package/dist/runtime/form/components/utils/form-option-item-label.d.vue.ts +9 -2
- package/dist/runtime/form/components/utils/form-option-item-label.vue +20 -13
- package/dist/runtime/form/components/utils/form-option-item-label.vue.d.ts +9 -2
- package/dist/runtime/form/components/utils/form-option-leading.d.vue.ts +23 -0
- package/dist/runtime/form/components/utils/form-option-leading.vue +41 -0
- package/dist/runtime/form/components/utils/form-option-leading.vue.d.ts +23 -0
- package/dist/runtime/form/components/utils/form-option-render.d.ts +11 -0
- package/dist/runtime/form/components/utils/form-option-render.js +5 -0
- package/dist/runtime/form/components/utils/form-option-suffix.d.vue.ts +8 -0
- package/dist/runtime/form/components/utils/form-option-suffix.vue +15 -0
- package/dist/runtime/form/components/utils/form-option-suffix.vue.d.ts +8 -0
- package/dist/runtime/form/components/utils/form-option-value-overlay.d.vue.ts +30 -0
- package/dist/runtime/form/components/utils/form-option-value-overlay.vue +44 -0
- package/dist/runtime/form/components/utils/form-option-value-overlay.vue.d.ts +30 -0
- package/dist/runtime/form/composables/use-choice-group-items.d.ts +27 -0
- package/dist/runtime/form/composables/use-choice-group-items.js +24 -0
- package/dist/runtime/form/composables/use-field-control.d.ts +6 -6
- package/dist/runtime/form/composables/use-field-control.js +9 -21
- package/dist/runtime/form/composables/use-field-options.js +8 -4
- package/dist/runtime/form/composables/use-form-layout.js +4 -3
- package/dist/runtime/form/composables/use-form-page.d.ts +11 -1
- package/dist/runtime/form/composables/use-form-page.js +12 -6
- package/dist/runtime/form/composables/use-form-runtime.js +1 -1
- package/dist/runtime/form/composables/use-option-menu.d.ts +20 -0
- package/dist/runtime/form/composables/use-option-menu.js +41 -0
- package/dist/runtime/form/fields/array-primitive/types.d.ts +1 -1
- package/dist/runtime/form/fields/auto-complete/component.vue +92 -51
- package/dist/runtime/form/fields/auto-complete/config.d.ts +1 -0
- package/dist/runtime/form/fields/auto-complete/config.js +1 -1
- package/dist/runtime/form/fields/auto-complete/types.d.ts +2 -2
- package/dist/runtime/form/fields/checkbox-card/component.vue +55 -29
- package/dist/runtime/form/fields/checkbox-card/config.d.ts +1 -0
- package/dist/runtime/form/fields/checkbox-card/config.js +1 -1
- package/dist/runtime/form/fields/checkbox-card/types.d.ts +3 -3
- package/dist/runtime/form/fields/checkbox-group/component.vue +18 -4
- package/dist/runtime/form/fields/checkbox-group/types.d.ts +2 -2
- package/dist/runtime/form/fields/choice-card/choice-card-label.d.vue.ts +7 -0
- package/dist/runtime/form/fields/choice-card/choice-card-label.vue +27 -1
- package/dist/runtime/form/fields/choice-card/choice-card-label.vue.d.ts +7 -0
- package/dist/runtime/form/fields/choice-card/types.d.ts +35 -1
- package/dist/runtime/form/fields/choice-card/use-choice-card.d.ts +7 -3
- package/dist/runtime/form/fields/choice-card/use-choice-card.js +37 -15
- package/dist/runtime/form/fields/choice-card/utils.d.ts +10 -0
- package/dist/runtime/form/fields/choice-card/utils.js +6 -0
- package/dist/runtime/form/fields/hierarchy/component.vue +3 -2
- package/dist/runtime/form/fields/index.d.ts +4 -0
- package/dist/runtime/form/fields/radio/component.vue +19 -2
- package/dist/runtime/form/fields/radio/types.d.ts +2 -2
- package/dist/runtime/form/fields/radio-card/component.vue +58 -28
- package/dist/runtime/form/fields/radio-card/config.d.ts +1 -0
- package/dist/runtime/form/fields/radio-card/config.js +1 -1
- package/dist/runtime/form/fields/radio-card/types.d.ts +3 -3
- package/dist/runtime/form/fields/select/component.vue +56 -58
- package/dist/runtime/form/fields/select/config.d.ts +1 -0
- package/dist/runtime/form/fields/select/config.js +1 -1
- package/dist/runtime/form/fields/select/types.d.ts +2 -2
- package/dist/runtime/form/types/field-base.d.ts +6 -0
- package/dist/runtime/form/types/field-kind.d.ts +3 -1
- package/dist/runtime/form/types/field.d.ts +1 -0
- package/dist/runtime/form/types/layout.d.ts +6 -0
- package/dist/runtime/form/types/options.d.ts +137 -0
- package/dist/runtime/form/types/page.d.ts +20 -8
- package/dist/runtime/form/types/ui.d.ts +29 -4
- package/dist/runtime/form/utils/disabled.d.ts +11 -0
- package/dist/runtime/form/utils/disabled.js +11 -0
- package/dist/runtime/form/utils/field-instance.js +3 -0
- package/dist/runtime/form/utils/options.d.ts +56 -11
- package/dist/runtime/form/utils/options.js +86 -0
- package/dist/runtime/form/utils/page-surface.d.ts +26 -0
- package/dist/runtime/form/utils/page-surface.js +28 -0
- package/dist/runtime/form/utils/page.d.ts +21 -1
- package/dist/runtime/form/utils/page.js +24 -2
- package/dist/runtime/i18n/locales/en.js +28 -8
- package/dist/runtime/i18n/locales/fr.js +28 -8
- package/dist/runtime/i18n/types.d.ts +46 -7
- package/dist/runtime/spreadsheet/components/internal/spreadsheet-import-column-row.d.vue.ts +2 -2
- package/dist/runtime/spreadsheet/components/internal/spreadsheet-import-column-row.vue.d.ts +2 -2
- package/dist/runtime/table/components/actions/row-actions.d.vue.ts +2 -0
- package/dist/runtime/table/components/actions/row-actions.vue +8 -3
- package/dist/runtime/table/components/actions/row-actions.vue.d.ts +2 -0
- package/dist/runtime/table/components/data-list/data-list-content.vue +7 -1
- package/dist/runtime/table/components/data-list/data-list-default.d.vue.ts +16 -16
- package/dist/runtime/table/components/data-list/data-list-default.vue +3 -0
- package/dist/runtime/table/components/data-list/data-list-default.vue.d.ts +16 -16
- package/dist/runtime/table/components/data-list/data-list-layout-switch.vue +7 -9
- package/dist/runtime/table/components/data-list/data-list-root.vue +5 -6
- package/dist/runtime/table/components/data-list/data-list-sort-menu.vue +3 -1
- package/dist/runtime/table/components/data-list/data-list-table.d.vue.ts +8 -1
- package/dist/runtime/table/components/data-list/data-list-table.vue +18 -1
- package/dist/runtime/table/components/data-list/data-list-table.vue.d.ts +8 -1
- package/dist/runtime/table/components/data-list/data-list-view-toggle.d.vue.ts +25 -0
- package/dist/runtime/table/components/data-list/data-list-view-toggle.vue +57 -0
- package/dist/runtime/table/components/data-list/data-list-view-toggle.vue.d.ts +25 -0
- package/dist/runtime/table/components/data-list/sort-menu-panel.vue +1 -1
- package/dist/runtime/table/components/filters/tags/boolean-filter-tag.d.vue.ts +2 -2
- package/dist/runtime/table/components/filters/tags/boolean-filter-tag.vue.d.ts +2 -2
- package/dist/runtime/table/components/filters/tags/date-filter-tag.d.vue.ts +2 -2
- package/dist/runtime/table/components/filters/tags/date-filter-tag.vue.d.ts +2 -2
- package/dist/runtime/table/components/filters/tags/number-filter-tag.d.vue.ts +2 -2
- package/dist/runtime/table/components/filters/tags/number-filter-tag.vue.d.ts +2 -2
- package/dist/runtime/table/components/filters/tags/option-filter-tag.d.vue.ts +2 -2
- package/dist/runtime/table/components/filters/tags/option-filter-tag.vue.d.ts +2 -2
- package/dist/runtime/table/components/filters/tags/text-filter-tag.d.vue.ts +2 -2
- package/dist/runtime/table/components/filters/tags/text-filter-tag.vue.d.ts +2 -2
- package/dist/runtime/table/components/layout/table-footer.d.vue.ts +6 -4
- package/dist/runtime/table/components/layout/table-footer.vue +80 -3
- package/dist/runtime/table/components/layout/table-footer.vue.d.ts +6 -4
- package/dist/runtime/table/components/summary/summary-content.d.ts +13 -0
- package/dist/runtime/table/components/summary/summary-content.js +5 -0
- package/dist/runtime/table/components/summary/summary-renderer.d.vue.ts +31 -0
- package/dist/runtime/table/components/summary/summary-renderer.vue +282 -0
- package/dist/runtime/table/components/summary/summary-renderer.vue.d.ts +31 -0
- package/dist/runtime/table/components/summary/summary-row.d.vue.ts +19 -0
- package/dist/runtime/table/components/summary/summary-row.vue +102 -0
- package/dist/runtime/table/components/summary/summary-row.vue.d.ts +19 -0
- package/dist/runtime/table/components/table/table-empty-state.vue +39 -9
- package/dist/runtime/table/components/table/table-renderer.vue +1 -1
- package/dist/runtime/table/components/table/table-row-actions-control.vue +10 -6
- package/dist/runtime/table/components/table/table-selection-control.d.vue.ts +5 -1
- package/dist/runtime/table/components/table/table-selection-control.vue +17 -4
- package/dist/runtime/table/components/table/table-selection-control.vue.d.ts +5 -1
- package/dist/runtime/table/components/table/table-tree-control.vue +2 -1
- package/dist/runtime/table/components/table/table-tree-header.vue +0 -1
- package/dist/runtime/table/composables/use-table-api.d.ts +2 -0
- package/dist/runtime/table/composables/use-table-api.js +8 -0
- package/dist/runtime/table/composables/use-table-columns.d.ts +2 -0
- package/dist/runtime/table/composables/use-table-controls.d.ts +6 -0
- package/dist/runtime/table/composables/use-table-controls.js +6 -3
- package/dist/runtime/table/composables/use-table-internals.d.ts +33 -0
- package/dist/runtime/table/composables/use-table-internals.js +9 -0
- package/dist/runtime/table/composables/use-table-row-labels.d.ts +16 -0
- package/dist/runtime/table/composables/use-table-row-labels.js +22 -0
- package/dist/runtime/table/composables/use-table-row-summary.d.ts +18 -0
- package/dist/runtime/table/composables/use-table-row-summary.js +41 -0
- package/dist/runtime/table/constants/mobile.d.ts +79 -0
- package/dist/runtime/table/constants/mobile.js +17 -0
- package/dist/runtime/table/constants/summary.d.ts +67 -0
- package/dist/runtime/table/constants/summary.js +31 -0
- package/dist/runtime/table/types/data-list.d.ts +58 -8
- package/dist/runtime/table/types/layout.d.ts +73 -0
- package/dist/runtime/table/types/remote-options.d.ts +4 -1
- package/dist/runtime/table/types/schema.d.ts +9 -1
- package/dist/runtime/table/types/table-api.d.ts +12 -0
- package/dist/runtime/table/utils/columns/defs.js +3 -1
- package/dist/runtime/table/utils/columns/render.d.ts +2 -0
- package/dist/runtime/table/utils/columns/render.js +2 -2
- package/dist/runtime/table/utils/data-list-ui.d.ts +1 -1
- package/dist/runtime/table/utils/data-list-ui.js +3 -1
- package/dist/runtime/table/utils/mobile-defaults.d.ts +7 -0
- package/dist/runtime/table/utils/mobile-defaults.js +25 -0
- package/dist/runtime/table/utils/remote-table-options.js +1 -1
- package/package.json +1 -1
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
* badge while a form with `controls.dirtyCheck` is modified, and the page actions. It stays
|
|
4
4
|
* pinned while the page scrolls on wide layouts, and sections scroll to just below it. The badge
|
|
5
5
|
* keeps its place while the form is unmodified, hidden, and does not grow its line, so the first
|
|
6
|
-
* edit neither shifts the page nor resizes the pinned header.
|
|
6
|
+
* edit neither shifts the page nor resizes the pinned header. The header spans the page, but on a
|
|
7
|
+
* page without a navigation its row takes the centered column of the body, so both share their
|
|
8
|
+
* edges.
|
|
7
9
|
*/
|
|
8
10
|
type __VLS_Slots = {
|
|
9
11
|
/** Before the heading, e.g. an avatar of the record. */
|
|
@@ -6,6 +6,7 @@ import { useUiToolsLocale } from "../../../i18n/use-locale";
|
|
|
6
6
|
import { useFormPageContext } from "../../composables/use-form-page";
|
|
7
7
|
import { useFormUi } from "../../composables/use-form-ui";
|
|
8
8
|
import { getFormHeader } from "../../utils/overlay";
|
|
9
|
+
import { FORM_PAGE_COLUMN } from "../../utils/page-surface";
|
|
9
10
|
import { isRecord } from "../../utils/path";
|
|
10
11
|
import { resolveFormBoundaryText } from "../../utils/text";
|
|
11
12
|
import { mergeFormUiClass } from "../../utils/ui";
|
|
@@ -20,6 +21,12 @@ const eyebrow = computed(() => headerText(header.value, "eyebrow"));
|
|
|
20
21
|
const title = computed(() => headerText(header.value, "title"));
|
|
21
22
|
const description = computed(() => headerText(header.value, "description"));
|
|
22
23
|
const unsaved = computed(() => page.dirtyCheck.value && page.root.runtime.isDirty.value);
|
|
24
|
+
const ROW = "flex flex-col gap-3 @3xl/form-page:flex-row @3xl/form-page:items-center @3xl/form-page:justify-between @3xl/form-page:gap-5";
|
|
25
|
+
const PADDING_X = "px-4 @3xl/form-page:px-7";
|
|
26
|
+
const headerClass = computed(() => page.navigationVisible.value ? `${ROW} ${PADDING_X}` : "");
|
|
27
|
+
const rowClass = computed(
|
|
28
|
+
() => page.navigationVisible.value ? "contents" : `${ROW} ${PADDING_X} ${FORM_PAGE_COLUMN}`
|
|
29
|
+
);
|
|
23
30
|
const element = useTemplateRef("element");
|
|
24
31
|
useResizeObserver(element, () => {
|
|
25
32
|
const node = element.value;
|
|
@@ -38,62 +45,65 @@ function headerText(config, key) {
|
|
|
38
45
|
ref="element"
|
|
39
46
|
:class="
|
|
40
47
|
mergeFormUiClass(
|
|
41
|
-
'z-10
|
|
48
|
+
'z-10 border-b border-default bg-default py-4 @3xl/form-page:sticky @3xl/form-page:top-0 @3xl/form-page:pt-[18px] @3xl/form-page:pb-4',
|
|
49
|
+
headerClass,
|
|
42
50
|
pageUi?.header
|
|
43
51
|
)
|
|
44
52
|
"
|
|
45
53
|
data-form-page-header
|
|
46
54
|
>
|
|
47
|
-
<div :class="mergeFormUiClass(
|
|
48
|
-
<
|
|
49
|
-
|
|
50
|
-
<
|
|
51
|
-
|
|
52
|
-
|
|
55
|
+
<div :class="mergeFormUiClass(rowClass, pageUi?.headerRow)" data-form-page-header-row>
|
|
56
|
+
<div :class="mergeFormUiClass('flex min-w-0 items-center gap-3.5', pageUi?.headerContent)">
|
|
57
|
+
<slot name="leading" />
|
|
58
|
+
<div :class="mergeFormUiClass('grid min-w-0 gap-1.5', pageUi?.heading)">
|
|
59
|
+
<p
|
|
60
|
+
v-if="eyebrow || $slots.eyebrow"
|
|
61
|
+
:class="
|
|
53
62
|
mergeFormUiClass(
|
|
54
63
|
'text-[11px] font-semibold tracking-[0.08em] text-dimmed uppercase',
|
|
55
64
|
pageUi?.eyebrow
|
|
56
65
|
)
|
|
57
66
|
"
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
67
|
+
>
|
|
68
|
+
<slot name="eyebrow">{{ eyebrow }}</slot>
|
|
69
|
+
</p>
|
|
70
|
+
<h1
|
|
71
|
+
v-if="title || $slots.title"
|
|
72
|
+
:class="
|
|
64
73
|
mergeFormUiClass(
|
|
65
74
|
'm-0 truncate text-[22px] leading-[1.1] font-semibold tracking-[-0.025em] text-highlighted @3xl/form-page:text-[28px]',
|
|
66
75
|
pageUi?.title
|
|
67
76
|
)
|
|
68
77
|
"
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
78
|
+
>
|
|
79
|
+
<slot name="title">{{ title }}</slot>
|
|
80
|
+
</h1>
|
|
81
|
+
<div
|
|
82
|
+
v-if="description || page.dirtyCheck.value || $slots.description"
|
|
83
|
+
:class="
|
|
75
84
|
mergeFormUiClass(
|
|
76
85
|
'flex flex-wrap items-center gap-2.5 text-[13.5px] text-muted',
|
|
77
86
|
pageUi?.meta
|
|
78
87
|
)
|
|
79
88
|
"
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
89
|
+
>
|
|
90
|
+
<slot name="description">
|
|
91
|
+
<span v-if="description">{{ description }}</span>
|
|
92
|
+
</slot>
|
|
93
|
+
<UBadge
|
|
94
|
+
v-if="page.dirtyCheck.value"
|
|
95
|
+
color="warning"
|
|
96
|
+
variant="soft"
|
|
97
|
+
:label="t('form.page.unsavedChanges')"
|
|
98
|
+
:class="mergeFormUiClass(unsaved ? '-my-1' : '-my-1 invisible', pageUi?.unsaved)"
|
|
99
|
+
:data-form-page-unsaved="unsaved ? '' : void 0"
|
|
100
|
+
/>
|
|
101
|
+
</div>
|
|
92
102
|
</div>
|
|
93
103
|
</div>
|
|
104
|
+
<slot name="actions">
|
|
105
|
+
<FormPageActions />
|
|
106
|
+
</slot>
|
|
94
107
|
</div>
|
|
95
|
-
<slot name="actions">
|
|
96
|
-
<FormPageActions />
|
|
97
|
-
</slot>
|
|
98
108
|
</header>
|
|
99
109
|
</template>
|
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
* badge while a form with `controls.dirtyCheck` is modified, and the page actions. It stays
|
|
4
4
|
* pinned while the page scrolls on wide layouts, and sections scroll to just below it. The badge
|
|
5
5
|
* keeps its place while the form is unmodified, hidden, and does not grow its line, so the first
|
|
6
|
-
* edit neither shifts the page nor resizes the pinned header.
|
|
6
|
+
* edit neither shifts the page nor resizes the pinned header. The header spans the page, but on a
|
|
7
|
+
* page without a navigation its row takes the centered column of the body, so both share their
|
|
8
|
+
* edges.
|
|
7
9
|
*/
|
|
8
10
|
type __VLS_Slots = {
|
|
9
11
|
/** Before the heading, e.g. an avatar of the record. */
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import type { FormPageSectionState } from '../../types/index.js';
|
|
2
2
|
/**
|
|
3
3
|
* Navigation of a form page: one entry per visible section, following the section in view.
|
|
4
|
-
* An entry shows whether its section is complete,
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* An entry shows whether its section is complete, to fix, to complete, or optional with nothing
|
|
5
|
+
* entered (a dashed circle and an "Optional" tag, never "to complete"), and, with
|
|
6
|
+
* `controls.dirtyCheck`, a dot on modified sections. The footer sums up the sections left to
|
|
7
|
+
* complete, which leaves out untouched optional ones, or the modified ones with dirty checking.
|
|
7
8
|
*
|
|
8
9
|
* From 768px of page width it is a pinned column; below, a row of chips that scrolls sideways.
|
|
10
|
+
* It renders nothing while the page has fewer visible sections than `navigation.minSections`.
|
|
9
11
|
*/
|
|
10
12
|
type __VLS_Slots = {
|
|
11
13
|
/** Replaces the heading, which comes from the schema `navigation.title`. */
|
|
@@ -73,6 +73,7 @@ function select(event, key) {
|
|
|
73
73
|
|
|
74
74
|
<template>
|
|
75
75
|
<nav
|
|
76
|
+
v-if="page.navigationVisible.value"
|
|
76
77
|
:aria-labelledby="page.navigationTitle.value || $slots.title ? titleId : void 0"
|
|
77
78
|
:aria-label="page.navigationTitle.value || $slots.title ? void 0 : t('form.page.navigation')"
|
|
78
79
|
:style="{ '--nut-form-page-header': `${page.stickyOffset.value}px` }"
|
|
@@ -138,7 +139,7 @@ function select(event, key) {
|
|
|
138
139
|
aria-hidden="true"
|
|
139
140
|
:class="
|
|
140
141
|
mergeFormUiClass(
|
|
141
|
-
'grid size-4 shrink-0 place-items-center rounded-full border-[1.5px] border-accented text-[10px] leading-none font-bold group-data-[active]:border-primary data-[state=complete]:border-(--ui-text-highlighted) data-[state=complete]:bg-(--ui-text-highlighted) data-[state=complete]:text-(--ui-bg) data-[state=invalid]:border-error data-[state=invalid]:bg-error data-[state=invalid]:text-inverted group-data-[active]:data-[state=complete]:border-primary group-data-[active]:data-[state=complete]:bg-primary group-data-[active]:data-[state=complete]:text-inverted',
|
|
142
|
+
'grid size-4 shrink-0 place-items-center rounded-full border-[1.5px] border-accented text-[10px] leading-none font-bold group-data-[active]:border-primary data-[state=optional]:border-dashed data-[state=complete]:border-(--ui-text-highlighted) data-[state=complete]:bg-(--ui-text-highlighted) data-[state=complete]:text-(--ui-bg) data-[state=invalid]:border-error data-[state=invalid]:bg-error data-[state=invalid]:text-inverted group-data-[active]:data-[state=complete]:border-primary group-data-[active]:data-[state=complete]:bg-primary group-data-[active]:data-[state=complete]:text-inverted',
|
|
142
143
|
pageUi?.navigationIndicator
|
|
143
144
|
)
|
|
144
145
|
"
|
|
@@ -182,15 +183,17 @@ function select(event, key) {
|
|
|
182
183
|
data-form-page-dirty
|
|
183
184
|
/>
|
|
184
185
|
<span
|
|
185
|
-
v-else-if="section.
|
|
186
|
+
v-else-if="section.status === 'optional'"
|
|
187
|
+
aria-hidden="true"
|
|
186
188
|
:class="
|
|
187
189
|
mergeFormUiClass(
|
|
188
190
|
'hidden shrink-0 text-[11px] font-normal text-dimmed @3xl/form-page:inline',
|
|
189
191
|
pageUi?.navigationOptional
|
|
190
192
|
)
|
|
191
193
|
"
|
|
194
|
+
data-form-page-optional
|
|
192
195
|
>
|
|
193
|
-
{{ t("form.page.optional") }}
|
|
196
|
+
{{ t("form.page.status.optional") }}
|
|
194
197
|
</span>
|
|
195
198
|
</a>
|
|
196
199
|
</slot>
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import type { FormPageSectionState } from '../../types/index.js';
|
|
2
2
|
/**
|
|
3
3
|
* Navigation of a form page: one entry per visible section, following the section in view.
|
|
4
|
-
* An entry shows whether its section is complete,
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* An entry shows whether its section is complete, to fix, to complete, or optional with nothing
|
|
5
|
+
* entered (a dashed circle and an "Optional" tag, never "to complete"), and, with
|
|
6
|
+
* `controls.dirtyCheck`, a dot on modified sections. The footer sums up the sections left to
|
|
7
|
+
* complete, which leaves out untouched optional ones, or the modified ones with dirty checking.
|
|
7
8
|
*
|
|
8
9
|
* From 768px of page width it is a pinned column; below, a row of chips that scrolls sideways.
|
|
10
|
+
* It renders nothing while the page has fewer visible sections than `navigation.minSections`.
|
|
9
11
|
*/
|
|
10
12
|
type __VLS_Slots = {
|
|
11
13
|
/** Replaces the heading, which comes from the schema `navigation.title`. */
|
|
@@ -50,7 +50,7 @@ onBeforeUnmount(() => unregister?.());
|
|
|
50
50
|
}"
|
|
51
51
|
:class="
|
|
52
52
|
mergeFormUiClass(
|
|
53
|
-
|
|
53
|
+
`flex min-w-0 flex-col ${page.surfaceClasses.value.section}`,
|
|
54
54
|
pageUi?.section
|
|
55
55
|
)
|
|
56
56
|
"
|
|
@@ -77,7 +77,7 @@ onBeforeUnmount(() => unregister?.());
|
|
|
77
77
|
v-if="section.description"
|
|
78
78
|
:class="
|
|
79
79
|
mergeFormUiClass(
|
|
80
|
-
|
|
80
|
+
`m-0 text-[13px] text-muted ${page.surfaceClasses.value.sectionDescription}`,
|
|
81
81
|
pageUi?.sectionDescription
|
|
82
82
|
)
|
|
83
83
|
"
|
|
@@ -85,11 +85,12 @@ onBeforeUnmount(() => unregister?.());
|
|
|
85
85
|
{{ section.description }}
|
|
86
86
|
</p>
|
|
87
87
|
<UBadge
|
|
88
|
-
v-if="section.optional"
|
|
88
|
+
v-if="section.status === 'optional'"
|
|
89
89
|
color="neutral"
|
|
90
90
|
variant="soft"
|
|
91
|
-
:label="t('form.page.optional')"
|
|
92
|
-
:class="
|
|
91
|
+
:label="t('form.page.status.optional')"
|
|
92
|
+
:class="pageUi?.sectionOptional"
|
|
93
|
+
data-form-page-optional
|
|
93
94
|
/>
|
|
94
95
|
<div
|
|
95
96
|
v-if="page.dirtyCheck.value || $slots.actions"
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import type { FormPageSectionState } from '../../types/index.js';
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
* with `controls.dirtyCheck`, a
|
|
5
|
-
* stand in while the schema context
|
|
3
|
+
* Sections of a form page, one per visible section, each with its title, description, fields, and,
|
|
4
|
+
* with `controls.dirtyCheck`, a mark and a reset button while it is modified. They are cards, or
|
|
5
|
+
* plain blocks with the `page.surface` UI option. Skeletons stand in while the schema context
|
|
6
|
+
* loads.
|
|
6
7
|
*/
|
|
7
8
|
type __VLS_Slots = {
|
|
8
9
|
/** Extra buttons in a section header, before its reset button. */
|
|
@@ -18,7 +18,12 @@ const { contextError, contextLoading, contextPending, refreshContext } = page.ro
|
|
|
18
18
|
|
|
19
19
|
<template>
|
|
20
20
|
<div
|
|
21
|
-
:class="
|
|
21
|
+
:class="
|
|
22
|
+
mergeFormUiClass(
|
|
23
|
+
`flex min-w-0 flex-col ${page.surfaceClasses.value.sections}`,
|
|
24
|
+
pageUi?.sections
|
|
25
|
+
)
|
|
26
|
+
"
|
|
22
27
|
data-form-page-sections
|
|
23
28
|
>
|
|
24
29
|
<UAlert
|
|
@@ -48,7 +53,7 @@ const { contextError, contextLoading, contextPending, refreshContext } = page.ro
|
|
|
48
53
|
:key="section.key"
|
|
49
54
|
:class="
|
|
50
55
|
mergeFormUiClass(
|
|
51
|
-
|
|
56
|
+
`grid gap-4 ${page.surfaceClasses.value.sectionSkeleton}`,
|
|
52
57
|
pageUi?.sectionSkeleton
|
|
53
58
|
)
|
|
54
59
|
"
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import type { FormPageSectionState } from '../../types/index.js';
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
* with `controls.dirtyCheck`, a
|
|
5
|
-
* stand in while the schema context
|
|
3
|
+
* Sections of a form page, one per visible section, each with its title, description, fields, and,
|
|
4
|
+
* with `controls.dirtyCheck`, a mark and a reset button while it is modified. They are cards, or
|
|
5
|
+
* plain blocks with the `page.surface` UI option. Skeletons stand in while the schema context
|
|
6
|
+
* loads.
|
|
6
7
|
*/
|
|
7
8
|
type __VLS_Slots = {
|
|
8
9
|
/** Extra buttons in a section header, before its reset button. */
|
|
@@ -2,6 +2,8 @@ import type { FormPageSectionState, FormRendererController, FormUiConfig, FormVa
|
|
|
2
2
|
/**
|
|
3
3
|
* A form laid out as a page: a header with the title and the actions, a navigation that follows
|
|
4
4
|
* the section in view, and one card per section. Render a schema from `defineFormPageSchema`.
|
|
5
|
+
* The `page.surface` UI option draws the sections as `plain` blocks instead of cards, and the
|
|
6
|
+
* schema `navigation.minSections` leaves the navigation out of a page with few sections.
|
|
5
7
|
*
|
|
6
8
|
* The page scrolls on its own, so give it a height (`h-full` in a layout that sizes its main
|
|
7
9
|
* area). Put parts in the default slot to compose another layout: `FormPageHeader`,
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { computed, useTemplateRef } from "vue";
|
|
3
3
|
import { provideFormPage, useFormPage } from "../../composables/use-form-page";
|
|
4
4
|
import { useFormRoot } from "../../composables/use-form-root";
|
|
5
|
+
import { FORM_PAGE_COLUMN } from "../../utils/page-surface";
|
|
5
6
|
import { mergeFormUiClass } from "../../utils/ui";
|
|
6
7
|
import FormPageHeader from "./form-page-header.vue";
|
|
7
8
|
import FormPageNavigation from "./form-page-navigation.vue";
|
|
@@ -30,6 +31,10 @@ const root = useFormRoot({
|
|
|
30
31
|
});
|
|
31
32
|
const page = provideFormPage(useFormPage({ element: () => element.value, hash: () => hash, root }));
|
|
32
33
|
const pageUi = computed(() => root.formUi.ui.value.page?.ui);
|
|
34
|
+
const BODY_UI = {
|
|
35
|
+
beside: "grid gap-4 px-4 pt-4 pb-16 @3xl/form-page:grid-cols-[200px_minmax(0,1fr)] @3xl/form-page:items-start @3xl/form-page:gap-7 @3xl/form-page:px-7 @3xl/form-page:pt-6 @3xl/form-page:pb-20 @5xl/form-page:grid-cols-[230px_minmax(0,760px)]",
|
|
36
|
+
single: `${FORM_PAGE_COLUMN} grid gap-4 px-4 pt-4 pb-16 @3xl/form-page:gap-7 @3xl/form-page:px-7 @3xl/form-page:pt-6 @3xl/form-page:pb-20`
|
|
37
|
+
};
|
|
33
38
|
</script>
|
|
34
39
|
|
|
35
40
|
<template>
|
|
@@ -37,8 +42,12 @@ const pageUi = computed(() => root.formUi.ui.value.page?.ui);
|
|
|
37
42
|
ref="element"
|
|
38
43
|
novalidate
|
|
39
44
|
:class="
|
|
40
|
-
mergeFormUiClass(
|
|
45
|
+
mergeFormUiClass(
|
|
46
|
+
`@container/form-page h-full min-w-0 overflow-y-auto ${page.surfaceClasses.value.root}`,
|
|
47
|
+
pageUi?.root
|
|
48
|
+
)
|
|
41
49
|
"
|
|
50
|
+
:data-surface="page.surface.value"
|
|
42
51
|
data-form-page
|
|
43
52
|
@submit.prevent="root.submit"
|
|
44
53
|
>
|
|
@@ -63,7 +72,7 @@ const pageUi = computed(() => root.formUi.ui.value.page?.ui);
|
|
|
63
72
|
<div
|
|
64
73
|
:class="
|
|
65
74
|
mergeFormUiClass(
|
|
66
|
-
|
|
75
|
+
page.navigationVisible.value ? BODY_UI.beside : BODY_UI.single,
|
|
67
76
|
pageUi?.body
|
|
68
77
|
)
|
|
69
78
|
"
|
|
@@ -2,6 +2,8 @@ import type { FormPageSectionState, FormRendererController, FormUiConfig, FormVa
|
|
|
2
2
|
/**
|
|
3
3
|
* A form laid out as a page: a header with the title and the actions, a navigation that follows
|
|
4
4
|
* the section in view, and one card per section. Render a schema from `defineFormPageSchema`.
|
|
5
|
+
* The `page.surface` UI option draws the sections as `plain` blocks instead of cards, and the
|
|
6
|
+
* schema `navigation.minSections` leaves the navigation out of a page with few sections.
|
|
5
7
|
*
|
|
6
8
|
* The page scrolls on its own, so give it a height (`h-full` in a layout that sizes its main
|
|
7
9
|
* area). Put parts in the default slot to compose another layout: `FormPageHeader`,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import UAlert from "@nuxt/ui/components/Alert.vue";
|
|
3
3
|
import { computed, ref, useId, watchEffect } from "vue";
|
|
4
|
+
import { useUiToolsLocale } from "../../../i18n/use-locale";
|
|
4
5
|
import { useFieldEffects } from "../../composables/use-field-effects";
|
|
5
6
|
import {
|
|
6
7
|
provideFormFieldBare,
|
|
@@ -67,6 +68,7 @@ const props = defineProps({
|
|
|
67
68
|
controlAttrs: { type: null, required: false }
|
|
68
69
|
});
|
|
69
70
|
const form = useFormRuntimeContext();
|
|
71
|
+
const { t } = useUiToolsLocale();
|
|
70
72
|
const element = ref(null);
|
|
71
73
|
const bare = computed(() => props.bare === true);
|
|
72
74
|
const controlId = useId();
|
|
@@ -208,8 +210,8 @@ function resolveControlLabel(controlField) {
|
|
|
208
210
|
color="neutral"
|
|
209
211
|
variant="soft"
|
|
210
212
|
icon="i-lucide-construction"
|
|
211
|
-
title="
|
|
212
|
-
:description="
|
|
213
|
+
:title="t('form.fields.unsupported.title')"
|
|
214
|
+
:description="t('form.fields.unsupported.description', { type: field.type.value })"
|
|
213
215
|
/>
|
|
214
216
|
</template>
|
|
215
217
|
|
|
@@ -225,8 +227,8 @@ function resolveControlLabel(controlField) {
|
|
|
225
227
|
color="neutral"
|
|
226
228
|
variant="soft"
|
|
227
229
|
icon="i-lucide-construction"
|
|
228
|
-
title="
|
|
229
|
-
:description="
|
|
230
|
+
:title="t('form.fields.unsupported.title')"
|
|
231
|
+
:description="t('form.fields.unsupported.description', { type: field.type.value })"
|
|
230
232
|
/>
|
|
231
233
|
</div>
|
|
232
234
|
</template>
|
|
@@ -9,12 +9,12 @@ declare var __VLS_1: {
|
|
|
9
9
|
description: string | undefined;
|
|
10
10
|
hint: string | undefined;
|
|
11
11
|
required: any;
|
|
12
|
-
},
|
|
12
|
+
}, __VLS_67: {
|
|
13
13
|
label: string | undefined;
|
|
14
14
|
description: string | undefined;
|
|
15
15
|
hint: string | undefined;
|
|
16
16
|
required: any;
|
|
17
|
-
},
|
|
17
|
+
}, __VLS_81: {
|
|
18
18
|
label: string | undefined;
|
|
19
19
|
description: string | undefined;
|
|
20
20
|
hint: string | undefined;
|
|
@@ -23,9 +23,9 @@ declare var __VLS_1: {
|
|
|
23
23
|
type __VLS_Slots = {} & {
|
|
24
24
|
default?: (props: typeof __VLS_1) => any;
|
|
25
25
|
} & {
|
|
26
|
-
default?: (props: typeof
|
|
26
|
+
default?: (props: typeof __VLS_67) => any;
|
|
27
27
|
} & {
|
|
28
|
-
default?: (props: typeof
|
|
28
|
+
default?: (props: typeof __VLS_81) => any;
|
|
29
29
|
};
|
|
30
30
|
declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
31
31
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
@@ -11,6 +11,7 @@ import { useFormFieldBare } from "../../composables/use-form-field-chrome";
|
|
|
11
11
|
import { useFormRuntimeContext } from "../../composables/use-form-runtime";
|
|
12
12
|
import { useFormUi } from "../../composables/use-form-ui";
|
|
13
13
|
import { getSchemaDirtyCheck } from "../../utils/controls";
|
|
14
|
+
import { resolveFieldDisabledReason } from "../../utils/disabled";
|
|
14
15
|
import { createFormFieldInstance } from "../../utils/field-instance";
|
|
15
16
|
import { isFunction, isNumber, isString } from "../../utils/predicate";
|
|
16
17
|
import { resolveRequired } from "../../utils/state";
|
|
@@ -85,6 +86,9 @@ const help = computed(
|
|
|
85
86
|
() => field.value.capability.has("hint") && "help" in props.field ? resolveFieldText(props.field.help, params.value) : void 0
|
|
86
87
|
);
|
|
87
88
|
const shellHelp = computed(() => props.inlineLabel ? void 0 : help.value);
|
|
89
|
+
const disabledReason = computed(
|
|
90
|
+
() => field.value.capability.has("hint") ? resolveFieldDisabledReason(props.field, params.value) : void 0
|
|
91
|
+
);
|
|
88
92
|
const dirty = computed(
|
|
89
93
|
() => "dirtyCheck" in props.field && (props.field.dirtyCheck === true || getSchemaDirtyCheck(form.schema.value)) && form.dirtyPaths.value.includes(props.path.join("."))
|
|
90
94
|
);
|
|
@@ -130,7 +134,7 @@ function renderLabelExtra() {
|
|
|
130
134
|
:description="shellDescription"
|
|
131
135
|
:hint="shellLabelExtra === void 0 || shellLabelExtra === null ? shellHint : void 0"
|
|
132
136
|
:error="error"
|
|
133
|
-
:help="shellHelp"
|
|
137
|
+
:help="shellHelp ?? disabledReason"
|
|
134
138
|
:required="required"
|
|
135
139
|
:size="formUi.controlSize.value"
|
|
136
140
|
:orientation="orientation"
|
|
@@ -183,6 +187,26 @@ function renderLabelExtra() {
|
|
|
183
187
|
<component :is="renderLabelExtra" />
|
|
184
188
|
</span>
|
|
185
189
|
</template>
|
|
190
|
+
<template v-if="disabledReason" #help>
|
|
191
|
+
<span v-if="shellHelp" class="block">{{ shellHelp }}</span>
|
|
192
|
+
<span
|
|
193
|
+
:class="
|
|
194
|
+
mergeFormUiClass(
|
|
195
|
+
'flex items-start gap-1.5',
|
|
196
|
+
shellHelp ? 'mt-1' : void 0,
|
|
197
|
+
fieldUi?.disabledReason
|
|
198
|
+
)
|
|
199
|
+
"
|
|
200
|
+
data-form-disabled-reason=""
|
|
201
|
+
>
|
|
202
|
+
<UIcon
|
|
203
|
+
name="i-lucide-lock"
|
|
204
|
+
aria-hidden="true"
|
|
205
|
+
:class="mergeFormUiClass('mt-0.5 size-3.5 shrink-0', fieldUi?.disabledReasonIcon)"
|
|
206
|
+
/>
|
|
207
|
+
<span>{{ disabledReason }}</span>
|
|
208
|
+
</span>
|
|
209
|
+
</template>
|
|
186
210
|
<UCollapsible
|
|
187
211
|
v-if="collapsible"
|
|
188
212
|
v-model:open="open"
|
|
@@ -195,7 +219,7 @@ function renderLabelExtra() {
|
|
|
195
219
|
:icon="open ? 'i-lucide-chevron-down' : 'i-lucide-chevron-right'"
|
|
196
220
|
:class="mergeFormUiClass('justify-self-start', fieldUi?.collapseTrigger)"
|
|
197
221
|
>
|
|
198
|
-
{{ open ? "
|
|
222
|
+
{{ open ? t("form.fields.shell.collapse") : t("form.fields.shell.expand") }}
|
|
199
223
|
</UButton>
|
|
200
224
|
<template #content>
|
|
201
225
|
<div :class="mergeFormUiClass('flex items-start gap-2', fieldUi?.body)">
|
|
@@ -216,7 +240,7 @@ function renderLabelExtra() {
|
|
|
216
240
|
color="neutral"
|
|
217
241
|
variant="ghost"
|
|
218
242
|
size="xs"
|
|
219
|
-
aria-label="
|
|
243
|
+
:aria-label="t('form.fields.shell.reset')"
|
|
220
244
|
:class="fieldUi?.reset"
|
|
221
245
|
@click="resetField"
|
|
222
246
|
/>
|
|
@@ -239,7 +263,7 @@ function renderLabelExtra() {
|
|
|
239
263
|
color="neutral"
|
|
240
264
|
variant="ghost"
|
|
241
265
|
size="xs"
|
|
242
|
-
aria-label="
|
|
266
|
+
:aria-label="t('form.fields.shell.reset')"
|
|
243
267
|
:class="fieldUi?.reset"
|
|
244
268
|
@click="resetField"
|
|
245
269
|
/>
|
|
@@ -9,12 +9,12 @@ declare var __VLS_1: {
|
|
|
9
9
|
description: string | undefined;
|
|
10
10
|
hint: string | undefined;
|
|
11
11
|
required: any;
|
|
12
|
-
},
|
|
12
|
+
}, __VLS_67: {
|
|
13
13
|
label: string | undefined;
|
|
14
14
|
description: string | undefined;
|
|
15
15
|
hint: string | undefined;
|
|
16
16
|
required: any;
|
|
17
|
-
},
|
|
17
|
+
}, __VLS_81: {
|
|
18
18
|
label: string | undefined;
|
|
19
19
|
description: string | undefined;
|
|
20
20
|
hint: string | undefined;
|
|
@@ -23,9 +23,9 @@ declare var __VLS_1: {
|
|
|
23
23
|
type __VLS_Slots = {} & {
|
|
24
24
|
default?: (props: typeof __VLS_1) => any;
|
|
25
25
|
} & {
|
|
26
|
-
default?: (props: typeof
|
|
26
|
+
default?: (props: typeof __VLS_67) => any;
|
|
27
27
|
} & {
|
|
28
|
-
default?: (props: typeof
|
|
28
|
+
default?: (props: typeof __VLS_81) => any;
|
|
29
29
|
};
|
|
30
30
|
declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
31
31
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
@@ -143,7 +143,7 @@ defineExpose({
|
|
|
143
143
|
validate: runtime.validate
|
|
144
144
|
});
|
|
145
145
|
function stepLabel(index) {
|
|
146
|
-
return runtime.steps.value[index]?.label ??
|
|
146
|
+
return runtime.steps.value[index]?.label ?? t("form.steps.fallback", { number: index + 1 });
|
|
147
147
|
}
|
|
148
148
|
function getHeaderText(headerConfig, key) {
|
|
149
149
|
if (!isRecord(headerConfig)) {
|
|
@@ -245,7 +245,7 @@ function getSchemaShowStepper(schema) {
|
|
|
245
245
|
:size="formUi.controlSize.value"
|
|
246
246
|
icon="i-lucide-x"
|
|
247
247
|
:disabled="runtime.actionPending.value !== null"
|
|
248
|
-
aria-label="
|
|
248
|
+
:aria-label="t('form.actions.closeButton')"
|
|
249
249
|
:class="formUi.ui.value.root?.ui?.close"
|
|
250
250
|
@click="cancel"
|
|
251
251
|
/>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { VNodeChild } from 'vue';
|
|
2
|
+
import type { FormOptionRenderContext, ResolvedFormOption } from '../../types/index.js';
|
|
3
|
+
/**
|
|
4
|
+
* Label of an option in a radio or checkbox list: the leading visual, the label, and the suffix at
|
|
5
|
+
* the end of the row. The description stays with the Nuxt UI group, under the row. An option with a
|
|
6
|
+
* `renderOption` function shows what it returns instead, and a plain option shows its label as it
|
|
7
|
+
* always did.
|
|
8
|
+
*/
|
|
9
|
+
type __VLS_Props = {
|
|
10
|
+
option: ResolvedFormOption;
|
|
11
|
+
selected?: boolean;
|
|
12
|
+
render?: (context: FormOptionRenderContext) => VNodeChild;
|
|
13
|
+
};
|
|
14
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
15
|
+
declare const _default: typeof __VLS_export;
|
|
16
|
+
export default _default;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { resolveOptionLeading } from "../../utils/options";
|
|
3
|
+
import FormOptionLeading from "./form-option-leading.vue";
|
|
4
|
+
import FormOptionRender from "./form-option-render";
|
|
5
|
+
import FormOptionSuffix from "./form-option-suffix.vue";
|
|
6
|
+
const props = defineProps({
|
|
7
|
+
option: { type: Object, required: true },
|
|
8
|
+
selected: { type: Boolean, required: false },
|
|
9
|
+
render: { type: Function, required: false }
|
|
10
|
+
});
|
|
11
|
+
function content() {
|
|
12
|
+
const { item } = props.option;
|
|
13
|
+
if (item === void 0) return null;
|
|
14
|
+
return props.render?.({
|
|
15
|
+
disabled: props.option.disabled === true,
|
|
16
|
+
item,
|
|
17
|
+
option: props.option,
|
|
18
|
+
selected: props.selected === true
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
</script>
|
|
22
|
+
|
|
23
|
+
<template>
|
|
24
|
+
<span v-if="render" class="block whitespace-normal" data-form-option-custom>
|
|
25
|
+
<FormOptionRender :content="content" />
|
|
26
|
+
</span>
|
|
27
|
+
<span
|
|
28
|
+
v-else-if="resolveOptionLeading(option) || option.suffix"
|
|
29
|
+
class="flex min-w-0 items-center gap-2"
|
|
30
|
+
data-form-option-row
|
|
31
|
+
>
|
|
32
|
+
<FormOptionLeading :option="option" />
|
|
33
|
+
<span class="min-w-0 flex-1 break-words">{{ option.label }}</span>
|
|
34
|
+
<FormOptionSuffix :option="option" class="ps-2 font-normal" />
|
|
35
|
+
</span>
|
|
36
|
+
<template v-else>{{ option.label }}</template>
|
|
37
|
+
</template>
|