nuxt-ui-tools 1.2.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 +18 -2
- package/dist/runtime/dashboard/components/block/dashboard-block-state.d.vue.ts +2 -0
- package/dist/runtime/dashboard/components/block/dashboard-block-state.vue +4 -1
- package/dist/runtime/dashboard/components/block/dashboard-block-state.vue.d.ts +2 -0
- package/dist/runtime/dashboard/components/block/dashboard-chips.d.vue.ts +20 -0
- package/dist/runtime/dashboard/components/block/dashboard-chips.vue +42 -0
- package/dist/runtime/dashboard/components/block/dashboard-chips.vue.d.ts +20 -0
- package/dist/runtime/dashboard/components/block/dashboard-series-picker.d.vue.ts +8 -0
- package/dist/runtime/dashboard/components/block/dashboard-series-picker.vue +29 -0
- package/dist/runtime/dashboard/components/block/dashboard-series-picker.vue.d.ts +8 -0
- package/dist/runtime/dashboard/components/block/dashboard-skeleton.d.vue.ts +1 -1
- package/dist/runtime/dashboard/components/block/dashboard-skeleton.vue.d.ts +1 -1
- package/dist/runtime/dashboard/components/block/dashboard-view-scope.d.vue.ts +21 -0
- package/dist/runtime/dashboard/components/block/dashboard-view-scope.vue +12 -0
- package/dist/runtime/dashboard/components/block/dashboard-view-scope.vue.d.ts +21 -0
- package/dist/runtime/dashboard/components/dashboard-alerts.vue +3 -3
- package/dist/runtime/dashboard/components/dashboard-bar-chart.d.vue.ts +14 -3
- package/dist/runtime/dashboard/components/dashboard-bar-chart.vue +30 -9
- package/dist/runtime/dashboard/components/dashboard-bar-chart.vue.d.ts +14 -3
- package/dist/runtime/dashboard/components/dashboard-bars.vue +4 -4
- package/dist/runtime/dashboard/components/dashboard-card.vue +28 -6
- package/dist/runtime/dashboard/components/dashboard-combo-chart.d.vue.ts +6 -1
- package/dist/runtime/dashboard/components/dashboard-combo-chart.vue +13 -3
- package/dist/runtime/dashboard/components/dashboard-combo-chart.vue.d.ts +6 -1
- package/dist/runtime/dashboard/components/dashboard-donut-chart.vue +5 -5
- package/dist/runtime/dashboard/components/dashboard-feed.vue +1 -1
- package/dist/runtime/dashboard/components/dashboard-filter.d.vue.ts +67 -0
- package/dist/runtime/dashboard/components/dashboard-filter.vue +134 -0
- package/dist/runtime/dashboard/components/dashboard-filter.vue.d.ts +67 -0
- package/dist/runtime/dashboard/components/dashboard-filters.d.vue.ts +49 -0
- package/dist/runtime/dashboard/components/dashboard-filters.vue +96 -0
- package/dist/runtime/dashboard/components/dashboard-filters.vue.d.ts +49 -0
- package/dist/runtime/dashboard/components/dashboard-funnel.vue +5 -5
- package/dist/runtime/dashboard/components/dashboard-gauge.vue +3 -3
- package/dist/runtime/dashboard/components/dashboard-grid.d.vue.ts +10 -3
- package/dist/runtime/dashboard/components/dashboard-grid.vue +24 -9
- package/dist/runtime/dashboard/components/dashboard-grid.vue.d.ts +10 -3
- package/dist/runtime/dashboard/components/dashboard-line-chart.d.vue.ts +14 -3
- package/dist/runtime/dashboard/components/dashboard-line-chart.vue +30 -9
- package/dist/runtime/dashboard/components/dashboard-line-chart.vue.d.ts +14 -3
- package/dist/runtime/dashboard/components/dashboard-list.d.vue.ts +3 -0
- package/dist/runtime/dashboard/components/dashboard-list.vue +18 -6
- package/dist/runtime/dashboard/components/dashboard-list.vue.d.ts +3 -0
- package/dist/runtime/dashboard/components/dashboard-page.d.vue.ts +53 -0
- package/dist/runtime/dashboard/components/dashboard-page.vue +156 -0
- package/dist/runtime/dashboard/components/dashboard-page.vue.d.ts +53 -0
- package/dist/runtime/dashboard/components/dashboard-paired-bars.vue +4 -4
- package/dist/runtime/dashboard/components/dashboard-refresh.d.vue.ts +1 -1
- package/dist/runtime/dashboard/components/dashboard-refresh.vue +1 -0
- package/dist/runtime/dashboard/components/dashboard-refresh.vue.d.ts +1 -1
- package/dist/runtime/dashboard/components/dashboard-stack-bar.vue +4 -4
- package/dist/runtime/dashboard/components/dashboard-stat.d.vue.ts +14 -2
- package/dist/runtime/dashboard/components/dashboard-stat.vue +28 -10
- package/dist/runtime/dashboard/components/dashboard-stat.vue.d.ts +14 -2
- package/dist/runtime/dashboard/components/dashboard-stats.vue +3 -3
- package/dist/runtime/dashboard/components/dashboard-table.d.vue.ts +1 -1
- package/dist/runtime/dashboard/components/dashboard-table.vue +3 -3
- package/dist/runtime/dashboard/components/dashboard-table.vue.d.ts +1 -1
- package/dist/runtime/dashboard/components/dashboard-tabs.d.vue.ts +1 -1
- package/dist/runtime/dashboard/components/dashboard-tabs.vue.d.ts +1 -1
- package/dist/runtime/dashboard/components/dashboard-total.d.vue.ts +7 -2
- package/dist/runtime/dashboard/components/dashboard-total.vue +10 -2
- package/dist/runtime/dashboard/components/dashboard-total.vue.d.ts +7 -2
- package/dist/runtime/dashboard/components/dashboard-view-tabs.d.vue.ts +33 -0
- package/dist/runtime/dashboard/components/dashboard-view-tabs.vue +66 -0
- package/dist/runtime/dashboard/components/dashboard-view-tabs.vue.d.ts +33 -0
- package/dist/runtime/dashboard/components/dashboard-widget.vue +1 -1
- package/dist/runtime/dashboard/components/filter/dashboard-filter-menu.d.vue.ts +44 -0
- package/dist/runtime/dashboard/components/filter/dashboard-filter-menu.vue +220 -0
- package/dist/runtime/dashboard/components/filter/dashboard-filter-menu.vue.d.ts +44 -0
- package/dist/runtime/dashboard/composables/use-dashboard-api.d.ts +6 -1
- package/dist/runtime/dashboard/composables/use-dashboard-api.js +29 -6
- package/dist/runtime/dashboard/composables/use-dashboard-block.d.ts +5 -4
- package/dist/runtime/dashboard/composables/use-dashboard-block.js +32 -15
- package/dist/runtime/dashboard/composables/use-dashboard-chart.d.ts +8 -1
- package/dist/runtime/dashboard/composables/use-dashboard-chart.js +16 -4
- package/dist/runtime/dashboard/composables/use-dashboard-context.d.ts +50 -0
- package/dist/runtime/dashboard/composables/use-dashboard-context.js +56 -0
- package/dist/runtime/dashboard/composables/use-dashboard-derived.js +6 -1
- package/dist/runtime/dashboard/composables/use-dashboard-filter-control.d.ts +16 -0
- package/dist/runtime/dashboard/composables/use-dashboard-filter-control.js +161 -0
- package/dist/runtime/dashboard/composables/use-dashboard-filter-scope.d.ts +37 -0
- package/dist/runtime/dashboard/composables/use-dashboard-filter-scope.js +107 -0
- package/dist/runtime/dashboard/composables/use-dashboard-format.d.ts +46 -6
- package/dist/runtime/dashboard/composables/use-dashboard-format.js +51 -8
- package/dist/runtime/dashboard/composables/use-dashboard-options.d.ts +11 -4
- package/dist/runtime/dashboard/composables/use-dashboard-options.js +33 -47
- package/dist/runtime/dashboard/composables/use-dashboard-remote-options.d.ts +8 -5
- package/dist/runtime/dashboard/composables/use-dashboard-remote-options.js +59 -70
- package/dist/runtime/dashboard/composables/use-dashboard-resource.d.ts +15 -4
- package/dist/runtime/dashboard/composables/use-dashboard-resource.js +52 -17
- package/dist/runtime/dashboard/composables/use-dashboard-scope.d.ts +10 -7
- package/dist/runtime/dashboard/composables/use-dashboard-scope.js +26 -16
- package/dist/runtime/dashboard/composables/use-dashboard-series-picker.d.ts +20 -0
- package/dist/runtime/dashboard/composables/use-dashboard-series-picker.js +30 -0
- package/dist/runtime/dashboard/composables/use-dashboard-time.d.ts +2 -0
- package/dist/runtime/dashboard/composables/use-dashboard-time.js +4 -1
- package/dist/runtime/dashboard/composables/use-dashboard-ui.d.ts +12 -2
- package/dist/runtime/dashboard/composables/use-dashboard-ui.js +3 -0
- package/dist/runtime/dashboard/composables/use-dashboard-views.d.ts +15 -3
- package/dist/runtime/dashboard/composables/use-dashboard-views.js +33 -10
- package/dist/runtime/dashboard/composables/use-dashboard.d.ts +18 -12
- package/dist/runtime/dashboard/composables/use-dashboard.js +98 -9
- package/dist/runtime/dashboard/index.d.ts +3 -1
- package/dist/runtime/dashboard/index.js +3 -1
- package/dist/runtime/dashboard/schema/index.d.ts +62 -30
- package/dist/runtime/dashboard/schema/index.js +3 -0
- package/dist/runtime/dashboard/types/blocks.d.ts +30 -4
- package/dist/runtime/dashboard/types/charts.d.ts +2 -2
- package/dist/runtime/dashboard/types/controls.d.ts +123 -0
- package/dist/runtime/dashboard/types/filters.d.ts +236 -0
- package/dist/runtime/dashboard/types/index.d.ts +3 -2
- package/dist/runtime/dashboard/types/page.d.ts +17 -0
- package/dist/runtime/dashboard/types/page.js +0 -0
- package/dist/runtime/dashboard/types/resource.d.ts +66 -28
- package/dist/runtime/dashboard/types/runtime.d.ts +39 -8
- package/dist/runtime/dashboard/types/schema.d.ts +94 -54
- package/dist/runtime/dashboard/types/ui.d.ts +78 -0
- package/dist/runtime/dashboard/utils/builders/dashboard-filters.d.ts +142 -0
- package/dist/runtime/dashboard/utils/builders/dashboard-filters.js +135 -0
- package/dist/runtime/dashboard/utils/charts.d.ts +4 -15
- package/dist/runtime/dashboard/utils/charts.js +26 -28
- package/dist/runtime/dashboard/utils/{params/codecs.d.ts → codecs.d.ts} +2 -2
- package/dist/runtime/dashboard/utils/{params/codecs.js → codecs.js} +1 -1
- package/dist/runtime/dashboard/utils/environment.d.ts +36 -0
- package/dist/runtime/dashboard/utils/environment.js +30 -0
- package/dist/runtime/dashboard/utils/filters.d.ts +44 -0
- package/dist/runtime/dashboard/utils/filters.js +62 -0
- package/dist/runtime/dashboard/utils/format.d.ts +25 -0
- package/dist/runtime/dashboard/utils/format.js +66 -0
- package/dist/runtime/dashboard/utils/grid.d.ts +17 -0
- package/dist/runtime/dashboard/utils/grid.js +14 -0
- package/dist/runtime/dashboard/utils/options.d.ts +3 -1
- package/dist/runtime/dashboard/utils/options.js +6 -0
- package/dist/runtime/dashboard/utils/remote.d.ts +7 -0
- package/dist/runtime/dashboard/utils/remote.js +14 -0
- package/dist/runtime/dashboard/utils/resource.d.ts +16 -7
- package/dist/runtime/dashboard/utils/resource.js +15 -9
- package/dist/runtime/dashboard/utils/schema.d.ts +8 -3
- package/dist/runtime/dashboard/utils/schema.js +9 -4
- package/dist/runtime/dashboard/utils/state.d.ts +11 -6
- package/dist/runtime/dashboard/utils/state.js +10 -5
- package/dist/runtime/dashboard/utils/time.d.ts +2 -0
- package/dist/runtime/dashboard/utils/time.js +11 -1
- package/dist/runtime/dashboard/utils/ui.d.ts +1 -1
- package/dist/runtime/dashboard/utils/ui.js +1 -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 +26 -195
- 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/card-selection.d.ts +1 -0
- package/dist/runtime/form/fields/card-selection.js +1 -0
- package/dist/runtime/form/fields/checkbox-card/component.vue +28 -17
- package/dist/runtime/form/fields/checkbox-card/types.d.ts +2 -5
- package/dist/runtime/form/fields/checkbox-group/component.vue +5 -0
- 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/component.vue +10 -0
- package/dist/runtime/form/fields/radio-card/component.vue +17 -16
- 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/options.d.ts +1 -11
- 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/focus.js +1 -1
- 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 +47 -0
- package/dist/runtime/i18n/locales/fr.js +47 -0
- package/dist/runtime/i18n/types.d.ts +70 -0
- package/dist/runtime/shared/styles/tokens.css +1 -1
- package/dist/runtime/shared/types/query.d.ts +8 -0
- package/dist/runtime/table/types/index.d.ts +1 -0
- package/dist/runtime/table/types/remote-options.d.ts +64 -0
- package/dist/runtime/table/types/remote-options.js +0 -0
- package/dist/runtime/table/types/source.d.ts +10 -1
- package/dist/runtime/table/utils/builders/table-source.d.ts +2 -6
- package/dist/runtime/table/utils/index.d.ts +1 -0
- package/dist/runtime/table/utils/index.js +1 -0
- package/dist/runtime/table/utils/remote-table-options.d.ts +26 -0
- package/dist/runtime/table/utils/remote-table-options.js +88 -0
- package/package.json +4 -1
- package/dist/runtime/dashboard/composables/use-dashboard-param-scope.d.ts +0 -30
- package/dist/runtime/dashboard/composables/use-dashboard-param-scope.js +0 -71
- package/dist/runtime/dashboard/types/options.d.ts +0 -46
- package/dist/runtime/dashboard/types/params.d.ts +0 -115
- package/dist/runtime/dashboard/utils/builders/dashboard-params.d.ts +0 -85
- package/dist/runtime/dashboard/utils/builders/dashboard-params.js +0 -87
- /package/dist/runtime/dashboard/types/{options.js → controls.js} +0 -0
- /package/dist/runtime/dashboard/types/{params.js → filters.js} +0 -0
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import UAlert from "@nuxt/ui/components/Alert.vue";
|
|
3
|
+
import UButton from "@nuxt/ui/components/Button.vue";
|
|
4
|
+
import USkeleton from "@nuxt/ui/components/Skeleton.vue";
|
|
5
|
+
import { computed } from "vue";
|
|
6
|
+
import { useUiToolsLocale } from "../../../i18n/use-locale";
|
|
7
|
+
import { useFormPageContext } from "../../composables/use-form-page";
|
|
8
|
+
import { useFormUi } from "../../composables/use-form-ui";
|
|
9
|
+
import { mergeFormUiClass } from "../../utils/ui";
|
|
10
|
+
import FormPageSection from "./form-page-section.vue";
|
|
11
|
+
defineSlots();
|
|
12
|
+
const page = useFormPageContext();
|
|
13
|
+
const formUi = useFormUi();
|
|
14
|
+
const { t } = useUiToolsLocale();
|
|
15
|
+
const pageUi = computed(() => formUi.ui.value.page?.ui);
|
|
16
|
+
const { contextError, contextLoading, contextPending, refreshContext } = page.root;
|
|
17
|
+
</script>
|
|
18
|
+
|
|
19
|
+
<template>
|
|
20
|
+
<div
|
|
21
|
+
:class="mergeFormUiClass('flex min-w-0 flex-col gap-[18px]', pageUi?.sections)"
|
|
22
|
+
data-form-page-sections
|
|
23
|
+
>
|
|
24
|
+
<UAlert
|
|
25
|
+
v-if="contextError"
|
|
26
|
+
color="error"
|
|
27
|
+
variant="soft"
|
|
28
|
+
icon="i-lucide-circle-alert"
|
|
29
|
+
:title="t('form.states.contextError.title')"
|
|
30
|
+
:description="contextError"
|
|
31
|
+
>
|
|
32
|
+
<template #actions>
|
|
33
|
+
<UButton
|
|
34
|
+
type="button"
|
|
35
|
+
color="error"
|
|
36
|
+
variant="outline"
|
|
37
|
+
size="xs"
|
|
38
|
+
:loading="contextLoading"
|
|
39
|
+
@click="refreshContext"
|
|
40
|
+
>
|
|
41
|
+
{{ t("form.states.contextError.action") }}
|
|
42
|
+
</UButton>
|
|
43
|
+
</template>
|
|
44
|
+
</UAlert>
|
|
45
|
+
<template v-if="contextPending">
|
|
46
|
+
<div
|
|
47
|
+
v-for="section in page.sections.value"
|
|
48
|
+
:key="section.key"
|
|
49
|
+
:class="
|
|
50
|
+
mergeFormUiClass(
|
|
51
|
+
'grid gap-4 rounded-xl border border-default bg-default px-6 pt-[22px] pb-6',
|
|
52
|
+
pageUi?.sectionSkeleton
|
|
53
|
+
)
|
|
54
|
+
"
|
|
55
|
+
data-form-skeleton
|
|
56
|
+
>
|
|
57
|
+
<USkeleton class="h-5 w-40" />
|
|
58
|
+
<USkeleton class="h-9 w-full" />
|
|
59
|
+
<USkeleton class="h-9 w-2/3" />
|
|
60
|
+
</div>
|
|
61
|
+
</template>
|
|
62
|
+
<template v-else>
|
|
63
|
+
<FormPageSection
|
|
64
|
+
v-for="item in page.items.value"
|
|
65
|
+
:key="item.section.key"
|
|
66
|
+
:entry="item.entry"
|
|
67
|
+
:section="item.section"
|
|
68
|
+
>
|
|
69
|
+
<template v-if="$slots.actions" #actions="slotProps">
|
|
70
|
+
<slot name="actions" v-bind="slotProps" />
|
|
71
|
+
</template>
|
|
72
|
+
</FormPageSection>
|
|
73
|
+
</template>
|
|
74
|
+
</div>
|
|
75
|
+
</template>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { FormPageSectionState } from '../../types/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Cards of a form page, one per visible section, each with its title, description, fields, and,
|
|
4
|
+
* with `controls.dirtyCheck`, a ring and a reset button while it is modified. Skeleton cards
|
|
5
|
+
* stand in while the schema context loads.
|
|
6
|
+
*/
|
|
7
|
+
type __VLS_Slots = {
|
|
8
|
+
/** Extra buttons in a section header, before its reset button. */
|
|
9
|
+
actions?: (props: {
|
|
10
|
+
section: FormPageSectionState;
|
|
11
|
+
}) => unknown;
|
|
12
|
+
};
|
|
13
|
+
declare const __VLS_base: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
14
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
15
|
+
declare const _default: typeof __VLS_export;
|
|
16
|
+
export default _default;
|
|
17
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
18
|
+
new (): {
|
|
19
|
+
$slots: S;
|
|
20
|
+
};
|
|
21
|
+
};
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import type { FormPageSectionState, FormRendererController, FormUiConfig, FormValue } from '../../types/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* A form laid out as a page: a header with the title and the actions, a navigation that follows
|
|
4
|
+
* the section in view, and one card per section. Render a schema from `defineFormPageSchema`.
|
|
5
|
+
*
|
|
6
|
+
* The page scrolls on its own, so give it a height (`h-full` in a layout that sizes its main
|
|
7
|
+
* area). Put parts in the default slot to compose another layout: `FormPageHeader`,
|
|
8
|
+
* `FormPageNavigation`, `FormPageSections`, and `FormPageActions` read the page they render in.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```vue
|
|
12
|
+
* <!-- const form = useForm({ schema: accountFormSchema(), onSubmit: createAccount }) -->
|
|
13
|
+
* <UiFormPage :form />
|
|
14
|
+
*
|
|
15
|
+
* <UiFormPage :form>
|
|
16
|
+
* <UiFormPageHeader />
|
|
17
|
+
* <div class="grid grid-cols-[minmax(0,1fr)_240px] gap-6 p-6">
|
|
18
|
+
* <UiFormPageSections />
|
|
19
|
+
* <UiFormPageNavigation />
|
|
20
|
+
* </div>
|
|
21
|
+
* </UiFormPage>
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
type __VLS_Props = {
|
|
25
|
+
form: FormRendererController;
|
|
26
|
+
/**
|
|
27
|
+
* Records the section picked in the navigation in the URL hash (`#identity`), and opens the
|
|
28
|
+
* page on the section the hash names. Defaults to `true`.
|
|
29
|
+
*/
|
|
30
|
+
hash?: boolean;
|
|
31
|
+
/** Presentation overrides, merged after the app config and the schema `ui`. */
|
|
32
|
+
ui?: FormUiConfig;
|
|
33
|
+
};
|
|
34
|
+
type __VLS_Slots = {
|
|
35
|
+
/** Replaces the whole layout with parts of the page. */
|
|
36
|
+
default?: () => unknown;
|
|
37
|
+
/** Slots of the default header: see `FormPageHeader`. */
|
|
38
|
+
'header-leading'?: () => unknown;
|
|
39
|
+
'header-eyebrow'?: () => unknown;
|
|
40
|
+
'header-title'?: () => unknown;
|
|
41
|
+
'header-description'?: () => unknown;
|
|
42
|
+
'header-actions'?: () => unknown;
|
|
43
|
+
/** Slots of the default navigation: see `FormPageNavigation`. */
|
|
44
|
+
'navigation-title'?: () => unknown;
|
|
45
|
+
'navigation-item'?: (props: {
|
|
46
|
+
section: FormPageSectionState;
|
|
47
|
+
active: boolean;
|
|
48
|
+
select: () => void;
|
|
49
|
+
}) => unknown;
|
|
50
|
+
'navigation-footer'?: (props: {
|
|
51
|
+
sections: readonly FormPageSectionState[];
|
|
52
|
+
remaining: number;
|
|
53
|
+
modified: number;
|
|
54
|
+
}) => unknown;
|
|
55
|
+
/** Extra buttons in a section header: see `FormPageSections`. */
|
|
56
|
+
'section-actions'?: (props: {
|
|
57
|
+
section: FormPageSectionState;
|
|
58
|
+
}) => unknown;
|
|
59
|
+
};
|
|
60
|
+
declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
61
|
+
submit: (value: import("../../../shared/index.js").GenericObject, result: {
|
|
62
|
+
success: boolean;
|
|
63
|
+
data?: FormValue;
|
|
64
|
+
}) => any;
|
|
65
|
+
cancel: (value: import("../../../shared/index.js").GenericObject) => any;
|
|
66
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
67
|
+
onSubmit?: ((value: import("../../../shared/index.js").GenericObject, result: {
|
|
68
|
+
success: boolean;
|
|
69
|
+
data?: FormValue;
|
|
70
|
+
}) => any) | undefined;
|
|
71
|
+
onCancel?: ((value: import("../../../shared/index.js").GenericObject) => any) | undefined;
|
|
72
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
73
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
74
|
+
declare const _default: typeof __VLS_export;
|
|
75
|
+
export default _default;
|
|
76
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
77
|
+
new (): {
|
|
78
|
+
$slots: S;
|
|
79
|
+
};
|
|
80
|
+
};
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { computed, useTemplateRef } from "vue";
|
|
3
|
+
import { provideFormPage, useFormPage } from "../../composables/use-form-page";
|
|
4
|
+
import { useFormRoot } from "../../composables/use-form-root";
|
|
5
|
+
import { mergeFormUiClass } from "../../utils/ui";
|
|
6
|
+
import FormPageHeader from "./form-page-header.vue";
|
|
7
|
+
import FormPageNavigation from "./form-page-navigation.vue";
|
|
8
|
+
import FormPageSections from "./form-page-sections.vue";
|
|
9
|
+
const {
|
|
10
|
+
form,
|
|
11
|
+
hash = true,
|
|
12
|
+
ui = void 0
|
|
13
|
+
} = defineProps({
|
|
14
|
+
form: { type: Object, required: true },
|
|
15
|
+
hash: { type: Boolean, required: false },
|
|
16
|
+
ui: { type: Object, required: false }
|
|
17
|
+
});
|
|
18
|
+
const emit = defineEmits(["submit", "cancel"]);
|
|
19
|
+
defineSlots();
|
|
20
|
+
const element = useTemplateRef("element");
|
|
21
|
+
const root = useFormRoot({
|
|
22
|
+
form: () => form,
|
|
23
|
+
input: () => void 0,
|
|
24
|
+
onCancelled: (value) => emit("cancel", value),
|
|
25
|
+
onSubmitted: (value, result) => emit("submit", value, result),
|
|
26
|
+
schema: () => void 0,
|
|
27
|
+
syncInput: () => void 0,
|
|
28
|
+
ui: () => ui,
|
|
29
|
+
validate: () => void 0
|
|
30
|
+
});
|
|
31
|
+
const page = provideFormPage(useFormPage({ element: () => element.value, hash: () => hash, root }));
|
|
32
|
+
const pageUi = computed(() => root.formUi.ui.value.page?.ui);
|
|
33
|
+
</script>
|
|
34
|
+
|
|
35
|
+
<template>
|
|
36
|
+
<form
|
|
37
|
+
ref="element"
|
|
38
|
+
novalidate
|
|
39
|
+
:class="
|
|
40
|
+
mergeFormUiClass('@container/form-page h-full min-w-0 overflow-y-auto bg-muted', pageUi?.root)
|
|
41
|
+
"
|
|
42
|
+
:style="{ '--nut-form-page-header': `${page.stickyOffset.value}px` }"
|
|
43
|
+
data-form-page
|
|
44
|
+
@submit.prevent="root.submit"
|
|
45
|
+
>
|
|
46
|
+
<slot>
|
|
47
|
+
<FormPageHeader>
|
|
48
|
+
<template v-if="$slots['header-leading']" #leading>
|
|
49
|
+
<slot name="header-leading" />
|
|
50
|
+
</template>
|
|
51
|
+
<template v-if="$slots['header-eyebrow']" #eyebrow>
|
|
52
|
+
<slot name="header-eyebrow" />
|
|
53
|
+
</template>
|
|
54
|
+
<template v-if="$slots['header-title']" #title>
|
|
55
|
+
<slot name="header-title" />
|
|
56
|
+
</template>
|
|
57
|
+
<template v-if="$slots['header-description']" #description>
|
|
58
|
+
<slot name="header-description" />
|
|
59
|
+
</template>
|
|
60
|
+
<template v-if="$slots['header-actions']" #actions>
|
|
61
|
+
<slot name="header-actions" />
|
|
62
|
+
</template>
|
|
63
|
+
</FormPageHeader>
|
|
64
|
+
<div
|
|
65
|
+
:class="
|
|
66
|
+
mergeFormUiClass(
|
|
67
|
+
'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)]',
|
|
68
|
+
pageUi?.body
|
|
69
|
+
)
|
|
70
|
+
"
|
|
71
|
+
>
|
|
72
|
+
<FormPageNavigation>
|
|
73
|
+
<template v-if="$slots['navigation-title']" #title>
|
|
74
|
+
<slot name="navigation-title" />
|
|
75
|
+
</template>
|
|
76
|
+
<template v-if="$slots['navigation-item']" #item="slotProps">
|
|
77
|
+
<slot name="navigation-item" v-bind="slotProps" />
|
|
78
|
+
</template>
|
|
79
|
+
<template v-if="$slots['navigation-footer']" #footer="slotProps">
|
|
80
|
+
<slot name="navigation-footer" v-bind="slotProps" />
|
|
81
|
+
</template>
|
|
82
|
+
</FormPageNavigation>
|
|
83
|
+
<FormPageSections>
|
|
84
|
+
<template v-if="$slots['section-actions']" #actions="slotProps">
|
|
85
|
+
<slot name="section-actions" v-bind="slotProps" />
|
|
86
|
+
</template>
|
|
87
|
+
</FormPageSections>
|
|
88
|
+
</div>
|
|
89
|
+
</slot>
|
|
90
|
+
</form>
|
|
91
|
+
</template>
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import type { FormPageSectionState, FormRendererController, FormUiConfig, FormValue } from '../../types/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* A form laid out as a page: a header with the title and the actions, a navigation that follows
|
|
4
|
+
* the section in view, and one card per section. Render a schema from `defineFormPageSchema`.
|
|
5
|
+
*
|
|
6
|
+
* The page scrolls on its own, so give it a height (`h-full` in a layout that sizes its main
|
|
7
|
+
* area). Put parts in the default slot to compose another layout: `FormPageHeader`,
|
|
8
|
+
* `FormPageNavigation`, `FormPageSections`, and `FormPageActions` read the page they render in.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```vue
|
|
12
|
+
* <!-- const form = useForm({ schema: accountFormSchema(), onSubmit: createAccount }) -->
|
|
13
|
+
* <UiFormPage :form />
|
|
14
|
+
*
|
|
15
|
+
* <UiFormPage :form>
|
|
16
|
+
* <UiFormPageHeader />
|
|
17
|
+
* <div class="grid grid-cols-[minmax(0,1fr)_240px] gap-6 p-6">
|
|
18
|
+
* <UiFormPageSections />
|
|
19
|
+
* <UiFormPageNavigation />
|
|
20
|
+
* </div>
|
|
21
|
+
* </UiFormPage>
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
type __VLS_Props = {
|
|
25
|
+
form: FormRendererController;
|
|
26
|
+
/**
|
|
27
|
+
* Records the section picked in the navigation in the URL hash (`#identity`), and opens the
|
|
28
|
+
* page on the section the hash names. Defaults to `true`.
|
|
29
|
+
*/
|
|
30
|
+
hash?: boolean;
|
|
31
|
+
/** Presentation overrides, merged after the app config and the schema `ui`. */
|
|
32
|
+
ui?: FormUiConfig;
|
|
33
|
+
};
|
|
34
|
+
type __VLS_Slots = {
|
|
35
|
+
/** Replaces the whole layout with parts of the page. */
|
|
36
|
+
default?: () => unknown;
|
|
37
|
+
/** Slots of the default header: see `FormPageHeader`. */
|
|
38
|
+
'header-leading'?: () => unknown;
|
|
39
|
+
'header-eyebrow'?: () => unknown;
|
|
40
|
+
'header-title'?: () => unknown;
|
|
41
|
+
'header-description'?: () => unknown;
|
|
42
|
+
'header-actions'?: () => unknown;
|
|
43
|
+
/** Slots of the default navigation: see `FormPageNavigation`. */
|
|
44
|
+
'navigation-title'?: () => unknown;
|
|
45
|
+
'navigation-item'?: (props: {
|
|
46
|
+
section: FormPageSectionState;
|
|
47
|
+
active: boolean;
|
|
48
|
+
select: () => void;
|
|
49
|
+
}) => unknown;
|
|
50
|
+
'navigation-footer'?: (props: {
|
|
51
|
+
sections: readonly FormPageSectionState[];
|
|
52
|
+
remaining: number;
|
|
53
|
+
modified: number;
|
|
54
|
+
}) => unknown;
|
|
55
|
+
/** Extra buttons in a section header: see `FormPageSections`. */
|
|
56
|
+
'section-actions'?: (props: {
|
|
57
|
+
section: FormPageSectionState;
|
|
58
|
+
}) => unknown;
|
|
59
|
+
};
|
|
60
|
+
declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
61
|
+
submit: (value: import("../../../shared/index.js").GenericObject, result: {
|
|
62
|
+
success: boolean;
|
|
63
|
+
data?: FormValue;
|
|
64
|
+
}) => any;
|
|
65
|
+
cancel: (value: import("../../../shared/index.js").GenericObject) => any;
|
|
66
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
67
|
+
onSubmit?: ((value: import("../../../shared/index.js").GenericObject, result: {
|
|
68
|
+
success: boolean;
|
|
69
|
+
data?: FormValue;
|
|
70
|
+
}) => any) | undefined;
|
|
71
|
+
onCancel?: ((value: import("../../../shared/index.js").GenericObject) => any) | undefined;
|
|
72
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
73
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
74
|
+
declare const _default: typeof __VLS_export;
|
|
75
|
+
export default _default;
|
|
76
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
77
|
+
new (): {
|
|
78
|
+
$slots: S;
|
|
79
|
+
};
|
|
80
|
+
};
|
|
@@ -10,8 +10,8 @@ import { useUiToolsLocale } from "../../../i18n/use-locale";
|
|
|
10
10
|
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
|
+
import { getSchemaDirtyCheck } from "../../utils/controls";
|
|
13
14
|
import { createFormFieldInstance } from "../../utils/field-instance";
|
|
14
|
-
import { isRecord } from "../../utils/path";
|
|
15
15
|
import { isFunction, isNumber, isString } from "../../utils/predicate";
|
|
16
16
|
import { resolveRequired } from "../../utils/state";
|
|
17
17
|
import { resolveFieldDescription, resolveFormText } from "../../utils/text";
|
|
@@ -85,21 +85,17 @@ const help = computed(
|
|
|
85
85
|
);
|
|
86
86
|
const shellHelp = computed(() => props.inlineLabel ? void 0 : help.value);
|
|
87
87
|
const dirty = computed(
|
|
88
|
-
() => "dirtyCheck" in props.field && (props.field.dirtyCheck === true ||
|
|
88
|
+
() => "dirtyCheck" in props.field && (props.field.dirtyCheck === true || getSchemaDirtyCheck(form.schema.value)) && form.dirtyPaths.value.includes(props.path.join("."))
|
|
89
89
|
);
|
|
90
|
-
function schemaDirtyCheck() {
|
|
91
|
-
const schema = form.schema.value;
|
|
92
|
-
if (!isRecord(schema) || !isRecord(schema.controls)) {
|
|
93
|
-
return false;
|
|
94
|
-
}
|
|
95
|
-
return schema.controls.dirtyCheck === true;
|
|
96
|
-
}
|
|
97
90
|
const open = ref(!("collapsed" in props.field && props.field.collapsed === true));
|
|
98
91
|
const collapsible = computed(() => "collapsible" in props.field && props.field.collapsible === true);
|
|
99
92
|
const fieldUi = computed(() => formUi.ui.value.field?.ui);
|
|
93
|
+
const stacked = computed(
|
|
94
|
+
() => orientation.value === "vertical" && Boolean(shellLabel.value || shellDescription.value)
|
|
95
|
+
);
|
|
100
96
|
const nuxtFieldUi = computed(() => ({
|
|
101
97
|
container: mergeFormUiClass(
|
|
102
|
-
orientation.value === "horizontal" ? "min-w-0 flex-1" : void 0,
|
|
98
|
+
orientation.value === "horizontal" ? "min-w-0 flex-1" : stacked.value ? "mt-0" : void 0,
|
|
103
99
|
fieldUi.value?.container
|
|
104
100
|
),
|
|
105
101
|
description: fieldUi.value?.description,
|
|
@@ -111,7 +107,7 @@ const nuxtFieldUi = computed(() => ({
|
|
|
111
107
|
orientation.value === "horizontal" && labelWidth.value ? "w-(--nut-form-label-width) shrink-0" : void 0,
|
|
112
108
|
fieldUi.value?.labelWrapper
|
|
113
109
|
),
|
|
114
|
-
root: fieldUi.value?.root,
|
|
110
|
+
root: mergeFormUiClass(stacked.value ? "flex flex-col gap-1.5" : void 0, fieldUi.value?.root),
|
|
115
111
|
wrapper: fieldUi.value?.wrapper
|
|
116
112
|
}));
|
|
117
113
|
function resetField() {
|
|
@@ -4,27 +4,17 @@ import UBadge from "@nuxt/ui/components/Badge.vue";
|
|
|
4
4
|
import UButton from "@nuxt/ui/components/Button.vue";
|
|
5
5
|
import USkeleton from "@nuxt/ui/components/Skeleton.vue";
|
|
6
6
|
import { useScrollShadow } from "@nuxt/ui/composables/useScrollShadow";
|
|
7
|
-
import {
|
|
8
|
-
import { computed, nextTick, onBeforeUnmount, onMounted, ref, watch } from "vue";
|
|
9
|
-
import { useRouter } from "vue-router";
|
|
7
|
+
import { computed, nextTick, ref, watch } from "vue";
|
|
10
8
|
import { useUiToolsLocale } from "#ui-tools/i18n";
|
|
11
9
|
import { useFormActions } from "../../composables/use-form-actions";
|
|
12
10
|
import { useFormGridLayout } from "../../composables/use-form-layout";
|
|
13
|
-
import {
|
|
14
|
-
import { provideFormUi } from "../../composables/use-form-ui";
|
|
11
|
+
import { useFormRoot } from "../../composables/use-form-root";
|
|
15
12
|
import { getFormHeader } from "../../utils/overlay";
|
|
16
13
|
import { isRecord } from "../../utils/path";
|
|
17
|
-
import {
|
|
18
|
-
isBoolean,
|
|
19
|
-
isFunction,
|
|
20
|
-
isNumber,
|
|
21
|
-
isString,
|
|
22
|
-
isUndefined,
|
|
23
|
-
stringArray
|
|
24
|
-
} from "../../utils/predicate";
|
|
14
|
+
import { isFunction, isNumber, isString } from "../../utils/predicate";
|
|
25
15
|
import { getSchemaFields, getSchemaSteps, isSteppedSchema } from "../../utils/state";
|
|
26
16
|
import { resolveFormText } from "../../utils/text";
|
|
27
|
-
import {
|
|
17
|
+
import { mergeFormUiClass } from "../../utils/ui";
|
|
28
18
|
import FormActions from "../actions/form-actions.vue";
|
|
29
19
|
import FormFieldRenderer from "../renderer/form-field-renderer.vue";
|
|
30
20
|
import FormDirectionalTransition from "../utils/form-directional-transition.vue";
|
|
@@ -38,68 +28,28 @@ const props = defineProps({
|
|
|
38
28
|
showCloseButton: { type: Boolean, required: false },
|
|
39
29
|
ui: { type: Object, required: false }
|
|
40
30
|
});
|
|
41
|
-
const router = useRouter();
|
|
42
31
|
const emit = defineEmits(["submit", "cancel"]);
|
|
43
32
|
const { t } = useUiToolsLocale();
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
const syncInputRef = computed(
|
|
53
|
-
() => props.form?.syncInput.value ?? props.syncInput ?? getSchemaSyncInput(schemaRef.value)
|
|
54
|
-
);
|
|
55
|
-
const validationModeRef = computed(
|
|
56
|
-
() => props.form?.validationMode.value ?? props.validate ?? getSchemaValidationMode(schemaRef.value)
|
|
57
|
-
);
|
|
58
|
-
const runtime = useFormRuntime({
|
|
59
|
-
input: inputRef,
|
|
33
|
+
const {
|
|
34
|
+
cancel,
|
|
35
|
+
contextError,
|
|
36
|
+
contextLoading,
|
|
37
|
+
contextPending,
|
|
38
|
+
formUi,
|
|
39
|
+
refreshContext,
|
|
40
|
+
runtime,
|
|
60
41
|
schema: schemaRef,
|
|
61
|
-
|
|
62
|
-
|
|
42
|
+
submit
|
|
43
|
+
} = useFormRoot({
|
|
44
|
+
form: () => props.form,
|
|
45
|
+
input: () => props.input,
|
|
46
|
+
onCancelled: (value) => emit("cancel", value),
|
|
47
|
+
onSubmitted: (value, result) => emit("submit", value, result),
|
|
48
|
+
schema: () => props.schema,
|
|
49
|
+
syncInput: () => props.syncInput,
|
|
50
|
+
ui: () => props.ui,
|
|
51
|
+
validate: () => props.validate
|
|
63
52
|
});
|
|
64
|
-
provideFormRuntime(runtime);
|
|
65
|
-
watch(
|
|
66
|
-
() => props.form,
|
|
67
|
-
(controller, previousController) => {
|
|
68
|
-
previousController?.unbind(runtime);
|
|
69
|
-
controller?.bind(runtime);
|
|
70
|
-
},
|
|
71
|
-
{ immediate: true }
|
|
72
|
-
);
|
|
73
|
-
onBeforeUnmount(() => props.form?.unbind(runtime));
|
|
74
|
-
onMounted(async () => {
|
|
75
|
-
await nextTick();
|
|
76
|
-
const target = getSchemaAutoFocus(schemaRef.value);
|
|
77
|
-
if (isString(target)) {
|
|
78
|
-
await runtime.focusField(target);
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
if (target === true) {
|
|
82
|
-
await focusFirstRenderedField();
|
|
83
|
-
}
|
|
84
|
-
});
|
|
85
|
-
if (import.meta.client) {
|
|
86
|
-
let handleBeforeUnload = function(event) {
|
|
87
|
-
if (!shouldConfirmDirtyNavigation()) {
|
|
88
|
-
return;
|
|
89
|
-
}
|
|
90
|
-
event.preventDefault();
|
|
91
|
-
event.returnValue = "";
|
|
92
|
-
};
|
|
93
|
-
window.addEventListener("beforeunload", handleBeforeUnload);
|
|
94
|
-
onBeforeUnmount(() => window.removeEventListener("beforeunload", handleBeforeUnload));
|
|
95
|
-
}
|
|
96
|
-
const removeRouteGuard = router.beforeEach(() => {
|
|
97
|
-
if (!shouldConfirmDirtyNavigation()) {
|
|
98
|
-
return true;
|
|
99
|
-
}
|
|
100
|
-
return window.confirm(getDirtyNavigationMessage());
|
|
101
|
-
});
|
|
102
|
-
onBeforeUnmount(removeRouteGuard);
|
|
103
53
|
const viewportRef = ref(null);
|
|
104
54
|
const viewportShadow = useScrollShadow(viewportRef, { size: 20 });
|
|
105
55
|
const displayedStepIndex = ref(runtime.currentStepIndex.value);
|
|
@@ -114,9 +64,6 @@ watch(
|
|
|
114
64
|
});
|
|
115
65
|
}
|
|
116
66
|
);
|
|
117
|
-
const parentPath = computed(
|
|
118
|
-
() => runtime.currentStepRoot.value ? [runtime.currentStepRoot.value] : []
|
|
119
|
-
);
|
|
120
67
|
const displayedStep = computed(
|
|
121
68
|
() => isSteppedSchema(schemaRef.value) ? getSchemaSteps(schemaRef.value)[displayedStepIndex.value] : void 0
|
|
122
69
|
);
|
|
@@ -163,60 +110,14 @@ const viewportClass = computed(
|
|
|
163
110
|
);
|
|
164
111
|
const footerClass = computed(
|
|
165
112
|
() => mergeFormUiClass(
|
|
166
|
-
isOverlayShell.value ? "flex shrink-0 items-center justify-between gap-3 border-t border-default bg-default px-[22px] pt-3.5 pb-[18px]" : "flex items-center justify-between gap-3
|
|
113
|
+
isOverlayShell.value ? "flex shrink-0 items-center justify-between gap-3 border-t border-default bg-default px-[22px] pt-3.5 pb-[18px]" : "flex items-center justify-between gap-3",
|
|
167
114
|
formUi.ui.value.root?.ui?.footer
|
|
168
115
|
)
|
|
169
116
|
);
|
|
170
|
-
const actions = useFormActions({
|
|
171
|
-
|
|
172
|
-
() =>
|
|
173
|
-
(resource) => "pending" in resource && resource.pending && isUndefined(resource.value)
|
|
174
|
-
)
|
|
175
|
-
);
|
|
176
|
-
const contextLoading = computed(
|
|
177
|
-
() => Object.values(runtime.context).some((resource) => "loading" in resource && resource.loading)
|
|
178
|
-
);
|
|
179
|
-
const contextError = computed(() => {
|
|
180
|
-
for (const resource of Object.values(runtime.context)) {
|
|
181
|
-
if (!("error" in resource) || !resource.error) {
|
|
182
|
-
continue;
|
|
183
|
-
}
|
|
184
|
-
if (resource.error instanceof Error) {
|
|
185
|
-
return resource.error.message;
|
|
186
|
-
}
|
|
187
|
-
if (isString(resource.error)) {
|
|
188
|
-
return resource.error;
|
|
189
|
-
}
|
|
190
|
-
return t("form.states.contextError.description");
|
|
191
|
-
}
|
|
192
|
-
return void 0;
|
|
117
|
+
const actions = useFormActions({
|
|
118
|
+
runtime,
|
|
119
|
+
slot: () => shell.value === "inline" ? "left" : "right"
|
|
193
120
|
});
|
|
194
|
-
async function submit() {
|
|
195
|
-
if (props.form) {
|
|
196
|
-
const result2 = await props.form.submitHandler();
|
|
197
|
-
if (result2.success) {
|
|
198
|
-
emit("submit", runtime.output.value, result2);
|
|
199
|
-
}
|
|
200
|
-
return;
|
|
201
|
-
}
|
|
202
|
-
const result = await runtime.submitHandler();
|
|
203
|
-
if (result.success) {
|
|
204
|
-
emit("submit", runtime.output.value, result);
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
async function refreshContext() {
|
|
208
|
-
await Promise.all(
|
|
209
|
-
Object.values(runtime.context).flatMap(
|
|
210
|
-
(resource) => "refresh" in resource ? [resource.refresh()] : []
|
|
211
|
-
)
|
|
212
|
-
);
|
|
213
|
-
}
|
|
214
|
-
function cancel() {
|
|
215
|
-
if (shouldConfirmDirtyNavigation() && !window.confirm(getDirtyNavigationMessage())) {
|
|
216
|
-
return;
|
|
217
|
-
}
|
|
218
|
-
emit("cancel", runtime.output.value);
|
|
219
|
-
}
|
|
220
121
|
defineExpose({
|
|
221
122
|
actionPending: runtime.actionPending,
|
|
222
123
|
dirtyPaths: runtime.dirtyPaths,
|
|
@@ -268,13 +169,6 @@ function headerDisplayed(display, currentShell) {
|
|
|
268
169
|
function isRenderShell(value) {
|
|
269
170
|
return value === "inline" || value === "drawer" || value === "modal" || value === "fullscreen";
|
|
270
171
|
}
|
|
271
|
-
function getSchemaUi(schema) {
|
|
272
|
-
if (!isRecord(schema)) {
|
|
273
|
-
return void 0;
|
|
274
|
-
}
|
|
275
|
-
const value = Object.getOwnPropertyDescriptor(schema, "ui")?.value;
|
|
276
|
-
return isRecord(value) ? value : void 0;
|
|
277
|
-
}
|
|
278
172
|
function getSchemaShowStepper(schema) {
|
|
279
173
|
if (!isRecord(schema)) {
|
|
280
174
|
return true;
|
|
@@ -282,69 +176,6 @@ function getSchemaShowStepper(schema) {
|
|
|
282
176
|
const value = Object.getOwnPropertyDescriptor(schema, "showStepper")?.value;
|
|
283
177
|
return value !== false;
|
|
284
178
|
}
|
|
285
|
-
function getSchemaSyncInput(schema) {
|
|
286
|
-
const controls = getSchemaControls(schema);
|
|
287
|
-
const value = controls ? Object.getOwnPropertyDescriptor(controls, "syncInput")?.value : void 0;
|
|
288
|
-
if (isBoolean(value)) {
|
|
289
|
-
return value;
|
|
290
|
-
}
|
|
291
|
-
return stringArray(value);
|
|
292
|
-
}
|
|
293
|
-
function getSchemaValidationMode(schema) {
|
|
294
|
-
const controls = getSchemaControls(schema);
|
|
295
|
-
const value = controls ? Object.getOwnPropertyDescriptor(controls, "validate")?.value : void 0;
|
|
296
|
-
return value === false || value === "required" || value === "validators" ? value : true;
|
|
297
|
-
}
|
|
298
|
-
function getSchemaControls(schema) {
|
|
299
|
-
if (!isRecord(schema)) {
|
|
300
|
-
return;
|
|
301
|
-
}
|
|
302
|
-
const controls = Object.getOwnPropertyDescriptor(schema, "controls")?.value;
|
|
303
|
-
return isRecord(controls) ? controls : void 0;
|
|
304
|
-
}
|
|
305
|
-
function getSchemaAutoFocus(schema) {
|
|
306
|
-
const controls = getSchemaControls(schema);
|
|
307
|
-
const value = controls ? Object.getOwnPropertyDescriptor(controls, "autoFocus")?.value : void 0;
|
|
308
|
-
return isString(value) || isBoolean(value) ? value : false;
|
|
309
|
-
}
|
|
310
|
-
function dirtyNavigationConfig() {
|
|
311
|
-
const controls = getSchemaControls(schemaRef.value);
|
|
312
|
-
return controls ? Object.getOwnPropertyDescriptor(controls, "confirmNavOnDirty")?.value : void 0;
|
|
313
|
-
}
|
|
314
|
-
function shouldConfirmDirtyNavigation() {
|
|
315
|
-
if (!runtime.isDirty.value) {
|
|
316
|
-
return false;
|
|
317
|
-
}
|
|
318
|
-
const config = dirtyNavigationConfig();
|
|
319
|
-
if (!config) {
|
|
320
|
-
return false;
|
|
321
|
-
}
|
|
322
|
-
if (!isRecord(config)) {
|
|
323
|
-
return config === true;
|
|
324
|
-
}
|
|
325
|
-
const ignored = stringArray(config.ignorePaths);
|
|
326
|
-
return runtime.dirtyPaths.value.some(
|
|
327
|
-
(path) => !ignored.some((ignoredPath) => path === ignoredPath || path.startsWith(`${ignoredPath}.`))
|
|
328
|
-
);
|
|
329
|
-
}
|
|
330
|
-
function getDirtyNavigationMessage() {
|
|
331
|
-
const config = dirtyNavigationConfig();
|
|
332
|
-
if (!isRecord(config)) {
|
|
333
|
-
return "You have unsaved changes. Close this form?";
|
|
334
|
-
}
|
|
335
|
-
const message = Object.getOwnPropertyDescriptor(config, "message")?.value;
|
|
336
|
-
return resolveFormText(message) ?? "You have unsaved changes. Close this form?";
|
|
337
|
-
}
|
|
338
|
-
async function focusFirstRenderedField() {
|
|
339
|
-
const paths = runtime.currentFields.value.map(
|
|
340
|
-
(field) => `${parentPath.value.join(".")}${parentPath.value.length ? "." : ""}${field.key}`
|
|
341
|
-
);
|
|
342
|
-
for (const path of paths) {
|
|
343
|
-
if (await runtime.focusField(path)) {
|
|
344
|
-
return;
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
179
|
</script>
|
|
349
180
|
|
|
350
181
|
<template>
|