@alfakit/vue 0.1.0 → 0.1.2
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/CHANGELOG.md +17 -0
- package/dist/components/actions/ActionButton.js.map +1 -1
- package/dist/components/actions/ActionButton.vue.d.ts.map +1 -1
- package/dist/components/actions/ActionButton.vue_vue_type_script_setup_true_lang.js +160 -159
- package/dist/components/actions/ActionButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/actions/ActionModal.js.map +1 -1
- package/dist/components/actions/ActionModal.vue.d.ts.map +1 -1
- package/dist/components/actions/ActionModal.vue_vue_type_script_setup_true_lang.js +214 -214
- package/dist/components/actions/ActionModal.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/cms/CmsLinkButton.vue.d.ts +1 -1
- package/dist/components/fields/ColorPickerField.js.map +1 -1
- package/dist/components/fields/ColorPickerField.vue.d.ts.map +1 -1
- package/dist/components/fields/ColorPickerField.vue_vue_type_script_setup_true_lang.js +1 -0
- package/dist/components/fields/ColorPickerField.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/fields/ComboboxSelect.js.map +1 -1
- package/dist/components/fields/ComboboxSelect.vue.d.ts.map +1 -1
- package/dist/components/fields/ComboboxSelect.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/fields/ComboboxSelect.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/fields/FileUploadField.js.map +1 -1
- package/dist/components/fields/FileUploadField.vue.d.ts.map +1 -1
- package/dist/components/fields/FileUploadField.vue_vue_type_script_setup_true_lang.js +183 -183
- package/dist/components/fields/FileUploadField.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/fields/OneTimeCodeInputField.js.map +1 -1
- package/dist/components/fields/OneTimeCodeInputField.vue_vue_type_script_setup_true_lang.js +1 -2
- package/dist/components/fields/OneTimeCodeInputField.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/fields/SelectField.js.map +1 -1
- package/dist/components/fields/SelectField.vue.d.ts.map +1 -1
- package/dist/components/fields/SelectField.vue_vue_type_script_setup_true_lang.js +2 -2
- package/dist/components/fields/SelectField.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/fields/TableColumnHeaders.js.map +1 -1
- package/dist/components/fields/TableColumnHeaders.vue.d.ts.map +1 -1
- package/dist/components/fields/TableColumnHeaders.vue_vue_type_script_setup_true_lang.js +6 -3
- package/dist/components/fields/TableColumnHeaders.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/file-manager/FileManagerView.js.map +1 -1
- package/dist/components/file-manager/FileManagerView.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/file-manager/FileManagerView.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/form/FormBlock.js.map +1 -1
- package/dist/components/form/FormBlock.vue.d.ts.map +1 -1
- package/dist/components/form/FormBlock.vue_vue_type_script_setup_true_lang.js +81 -77
- package/dist/components/form/FormBlock.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/form/form-context.js +25 -25
- package/dist/components/form/form-context.js.map +1 -1
- package/dist/components/layout/FusedGroupComponent.js.map +1 -1
- package/dist/components/layout/FusedGroupComponent.vue.d.ts.map +1 -1
- package/dist/components/layout/FusedGroupComponent.vue_vue_type_script_setup_true_lang.js +1 -0
- package/dist/components/layout/FusedGroupComponent.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/layout/TabsComponent.js.map +1 -1
- package/dist/components/layout/TabsComponent.vue.d.ts.map +1 -1
- package/dist/components/layout/TabsComponent.vue_vue_type_script_setup_true_lang.js +76 -55
- package/dist/components/layout/TabsComponent.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/notifications/NotificationsMenu.js.map +1 -1
- package/dist/components/notifications/NotificationsMenu.vue.d.ts.map +1 -1
- package/dist/components/notifications/NotificationsMenu.vue_vue_type_script_setup_true_lang.js +44 -42
- package/dist/components/notifications/NotificationsMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/panel/GlobalSearch.js.map +1 -1
- package/dist/components/panel/GlobalSearch.vue.d.ts.map +1 -1
- package/dist/components/panel/GlobalSearch.vue_vue_type_script_setup_true_lang.js +1 -0
- package/dist/components/panel/GlobalSearch.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/panel/ShortcutKeys.js.map +1 -1
- package/dist/components/panel/ShortcutKeys.vue.d.ts.map +1 -1
- package/dist/components/panel/ShortcutKeys.vue_vue_type_script_setup_true_lang.js +4 -1
- package/dist/components/panel/ShortcutKeys.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/panel/TenantMenu.js.map +1 -1
- package/dist/components/panel/TenantMenu.vue_vue_type_script_setup_true_lang.js +2 -2
- package/dist/components/panel/TenantMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/table/GroupHeaderRow.js.map +1 -1
- package/dist/components/table/GroupHeaderRow.vue.d.ts.map +1 -1
- package/dist/components/table/GroupHeaderRow.vue_vue_type_script_setup_true_lang.js +55 -34
- package/dist/components/table/GroupHeaderRow.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/table/SelectCell.js.map +1 -1
- package/dist/components/table/SelectCell.vue.d.ts.map +1 -1
- package/dist/components/table/SelectCell.vue_vue_type_script_setup_true_lang.js +24 -19
- package/dist/components/table/SelectCell.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/table/TextInputCell.js.map +1 -1
- package/dist/components/table/TextInputCell.vue.d.ts.map +1 -1
- package/dist/components/table/TextInputCell.vue_vue_type_script_setup_true_lang.js +38 -33
- package/dist/components/table/TextInputCell.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components.css +347 -0
- package/dist/eject-manifest.json +2 -2
- package/dist/lib/Icon.js.map +1 -1
- package/dist/lib/Icon.vue.d.ts.map +1 -1
- package/dist/lib/Icon.vue_vue_type_script_setup_true_lang.js +18 -19
- package/dist/lib/Icon.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/lib/hydration.d.ts +9 -0
- package/dist/lib/hydration.d.ts.map +1 -0
- package/dist/lib/hydration.js +17 -0
- package/dist/lib/hydration.js.map +1 -0
- package/dist/lib/icons.d.ts +3 -5
- package/dist/lib/icons.d.ts.map +1 -1
- package/dist/lib/icons.js +19 -22
- package/dist/lib/icons.js.map +1 -1
- package/dist/lib/lazy.d.ts +1 -1
- package/dist/lib/lazy.d.ts.map +1 -1
- package/dist/lib/lazy.js +12 -11
- package/dist/lib/lazy.js.map +1 -1
- package/dist/standalone/AlfakitToaster.js.map +1 -1
- package/dist/standalone/AlfakitToaster.vue.d.ts.map +1 -1
- package/dist/standalone/AlfakitToaster.vue_vue_type_script_setup_true_lang.js +23 -15
- package/dist/standalone/AlfakitToaster.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/standalone.css +47 -0
- package/dist/starter-kit/widgets/SearchTrigger.js.map +1 -1
- package/dist/starter-kit/widgets/SearchTrigger.vue.d.ts.map +1 -1
- package/dist/starter-kit/widgets/SearchTrigger.vue_vue_type_script_setup_true_lang.js +1 -0
- package/dist/starter-kit/widgets/SearchTrigger.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/starter-kit/widgets/TenantChooser.js.map +1 -1
- package/dist/starter-kit/widgets/TenantChooser.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/starter-kit/widgets/TenantChooser.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/themes.css +2 -334
- package/package.json +3 -3
- package/src/components/actions/ActionButton.vue +14 -6
- package/src/components/actions/ActionModal.vue +3 -1
- package/src/components/fields/ColorPickerField.vue +1 -0
- package/src/components/fields/ComboboxSelect.vue +1 -1
- package/src/components/fields/FileUploadField.vue +14 -11
- package/src/components/fields/OneTimeCodeInputField.vue +1 -1
- package/src/components/fields/SelectField.vue +4 -2
- package/src/components/fields/TableColumnHeaders.vue +6 -1
- package/src/components/file-manager/FileManagerView.vue +1 -1
- package/src/components/form/FormBlock.vue +24 -0
- package/src/components/form/form-context.ts +2 -2
- package/src/components/layout/FusedGroupComponent.vue +1 -0
- package/src/components/layout/TabsComponent.vue +61 -5
- package/src/components/notifications/NotificationsMenu.vue +11 -0
- package/src/components/panel/GlobalSearch.vue +1 -0
- package/src/components/panel/ShortcutKeys.vue +1 -0
- package/src/components/panel/TenantMenu.vue +2 -2
- package/src/components/table/GroupHeaderRow.vue +27 -0
- package/src/components/table/SelectCell.vue +5 -2
- package/src/components/table/TextInputCell.vue +11 -5
- package/src/lib/Icon.vue +6 -5
- package/src/lib/hydration.ts +35 -0
- package/src/lib/icons.ts +6 -11
- package/src/lib/lazy.ts +5 -6
- package/src/standalone/AlfakitToaster.vue +12 -2
- package/src/starter-kit/widgets/SearchTrigger.vue +1 -0
- package/src/starter-kit/widgets/TenantChooser.vue +1 -1
|
@@ -1,102 +1,106 @@
|
|
|
1
|
-
import { useActionRunner as e, useAlfakitProps as t, usePageSchema as
|
|
2
|
-
import { useStore as
|
|
3
|
-
import
|
|
4
|
-
import { provideForm as
|
|
5
|
-
import
|
|
6
|
-
import { showToast as
|
|
7
|
-
import { FormStore as
|
|
8
|
-
import { router as
|
|
9
|
-
import { computed as
|
|
1
|
+
import { useActionRunner as e, useAlfakitProps as t, usePageSchema as ee, usePanel as n, useT as r } from "../../context.js";
|
|
2
|
+
import { useStore as i } from "../../composables/use-store.js";
|
|
3
|
+
import te from "../actions/ActionList.js";
|
|
4
|
+
import { provideForm as ne } from "./form-context.js";
|
|
5
|
+
import re from "../schema/SchemaRenderer.js";
|
|
6
|
+
import { showToast as ie } from "../notifications/flash-toasts.js";
|
|
7
|
+
import { FormStore as ae, applyFormRefresh as oe, formActionsVisible as a, formIdentity as o, formRefreshFor as s, isImplicitSubmit as c, isLeavingVisit as l, pageFlash as u, pageFormName as d, registerConflictForm as f, registerFormSubmitter as p, registerPageForm as m, resolvePartialProps as h, shouldResyncForm as se, wizardProgressStore as g } from "@alfakit/core";
|
|
8
|
+
import { router as _ } from "@inertiajs/vue3";
|
|
9
|
+
import { computed as v, createCommentVNode as ce, createElementBlock as y, createElementVNode as le, createVNode as b, defineComponent as x, onBeforeUnmount as S, onMounted as C, onScopeDispose as ue, openBlock as w, unref as T, watch as E, withModifiers as D } from "vue";
|
|
10
10
|
//#region src/components/form/FormBlock.vue?vue&type=script&setup=true&lang.ts
|
|
11
|
-
var
|
|
11
|
+
var O = ["disabled"], k = {
|
|
12
12
|
key: 0,
|
|
13
13
|
"data-slot": "form-actions",
|
|
14
14
|
class: "border-t pt-6"
|
|
15
|
-
},
|
|
15
|
+
}, A = /*@__PURE__*/ x({
|
|
16
16
|
__name: "FormBlock",
|
|
17
17
|
props: { block: {} },
|
|
18
|
-
setup(
|
|
19
|
-
let
|
|
20
|
-
token:
|
|
21
|
-
component:
|
|
22
|
-
refreshUrl:
|
|
23
|
-
optionsUrl:
|
|
24
|
-
validateUrl:
|
|
25
|
-
onNotifications: (e) => e.forEach((e) =>
|
|
18
|
+
setup(x) {
|
|
19
|
+
let A = x, j = n(), M = ee(), N = t(), P = e(), F = r(), I = v(() => M.value?.token ?? ""), L = new ae(A.block, {
|
|
20
|
+
token: I.value,
|
|
21
|
+
component: A.block.component,
|
|
22
|
+
refreshUrl: j.value.endpoints.schemaRefresh,
|
|
23
|
+
optionsUrl: j.value.endpoints.schemaOptions,
|
|
24
|
+
validateUrl: j.value.endpoints.schemaValidate,
|
|
25
|
+
onNotifications: (e) => e.forEach((e) => ie(e)),
|
|
26
26
|
onRefreshed: () => {
|
|
27
|
-
|
|
27
|
+
A.block.liveFilters && _.reload({ only: h(["page"]) });
|
|
28
28
|
}
|
|
29
29
|
});
|
|
30
|
-
|
|
31
|
-
let
|
|
32
|
-
|
|
33
|
-
let e =
|
|
34
|
-
e && (
|
|
30
|
+
ne(L);
|
|
31
|
+
let R;
|
|
32
|
+
C(() => {
|
|
33
|
+
let e = d(A.block.component);
|
|
34
|
+
e && (R = m(e, L));
|
|
35
35
|
});
|
|
36
|
-
let
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
}),
|
|
40
|
-
let
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
}),
|
|
44
|
-
|
|
45
|
-
}),
|
|
46
|
-
let
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
}),
|
|
50
|
-
let
|
|
51
|
-
token:
|
|
36
|
+
let z;
|
|
37
|
+
C(() => {
|
|
38
|
+
A.block.component === "form" && (z = f(L));
|
|
39
|
+
}), S(() => z?.());
|
|
40
|
+
let B;
|
|
41
|
+
C(() => {
|
|
42
|
+
B = p(A.block.component, (e, t) => Z(e, t));
|
|
43
|
+
}), S(() => {
|
|
44
|
+
R?.(), B?.();
|
|
45
|
+
}), E(() => o(M.value, A.block), () => L.fill(A.block)), E(I, (e) => L.setToken(e));
|
|
46
|
+
let V = null, H = !1, U = !1, W = null;
|
|
47
|
+
E(() => A.block, (e) => {
|
|
48
|
+
H && (H = !1, L.fill(e)), U && (U = !1, L.isDirty || L.fill(e));
|
|
49
|
+
}), E(() => N.value.errors, (e) => L.setErrors(e ?? {}), { immediate: !0 });
|
|
50
|
+
let G = i(L.store), K = v(() => ({
|
|
51
|
+
token: I.value,
|
|
52
52
|
component: "page"
|
|
53
|
-
})),
|
|
53
|
+
})), q = !1, J = v(() => A.block.actions.map((e) => ({
|
|
54
54
|
...e,
|
|
55
55
|
hasModal: !1
|
|
56
|
-
}))),
|
|
57
|
-
if (e.url && !e.hasAction) return
|
|
58
|
-
|
|
59
|
-
},
|
|
56
|
+
}))), Y = v(() => J.value[0]), de = i(g(L)), X = v(() => a(A.block, de.value)), Z = async (e, t) => {
|
|
57
|
+
if (e.url && !e.hasAction) return P.trigger(e, t);
|
|
58
|
+
q = !0, V = A.block, L.setProcessing(!0), P.execute(e, t, L.state.values);
|
|
59
|
+
}, Q = null, fe = _.on("start", (e) => {
|
|
60
60
|
let t = e.detail.visit;
|
|
61
|
-
|
|
62
|
-
}),
|
|
63
|
-
let t =
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
61
|
+
q && !Q && t.method !== "get" && (Q = t.id), t.method !== "get" && (W = A.block);
|
|
62
|
+
}), pe = _.on("success", (e) => {
|
|
63
|
+
let t = Q;
|
|
64
|
+
if (!t && se(u(e.detail.page), L)) {
|
|
65
|
+
A.block === W ? U = !0 : L.fill(A.block);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
t && (e.detail.visitId ?? t) === t && u(e.detail.page).alfakitAction?.status !== "halted" && (A.block === V ? H = !0 : L.fill(A.block));
|
|
69
|
+
}), me = _.on("success", (e) => {
|
|
70
|
+
let t = s(u(e.detail.page), A.block.component);
|
|
71
|
+
t && oe(L, t);
|
|
72
|
+
}), he = _.on("finish", (e) => {
|
|
73
|
+
Q && e.detail.visit.id !== Q || (L.setProcessing(!1), q = !1, Q = null);
|
|
74
|
+
}), ge = _.on("before", (e) => {
|
|
75
|
+
j.value.unsavedChangesAlerts && L.isDirty && !q && l(e.detail.visit) && !window.confirm(F("unsaved_changes", {}, "You have unsaved changes. Leave anyway?")) && e.preventDefault();
|
|
72
76
|
});
|
|
73
|
-
|
|
74
|
-
|
|
77
|
+
ue(() => {
|
|
78
|
+
fe(), pe(), me(), he(), ge(), L.destroy();
|
|
75
79
|
});
|
|
76
|
-
let
|
|
77
|
-
|
|
78
|
-
},
|
|
79
|
-
|
|
80
|
+
let $ = () => {
|
|
81
|
+
Y.value && X.value && Z(Y.value, K.value);
|
|
82
|
+
}, _e = (e) => {
|
|
83
|
+
Y.value && X.value && c(e, e.currentTarget) && (e.preventDefault(), Z(Y.value, K.value));
|
|
80
84
|
};
|
|
81
|
-
return (e, t) => (
|
|
85
|
+
return (e, t) => (w(), y("form", {
|
|
82
86
|
"data-slot": "form-block",
|
|
83
87
|
class: "flex flex-col gap-6",
|
|
84
|
-
onSubmit:
|
|
85
|
-
onKeydown:
|
|
86
|
-
}, [
|
|
87
|
-
disabled:
|
|
88
|
+
onSubmit: D($, ["prevent"]),
|
|
89
|
+
onKeydown: _e
|
|
90
|
+
}, [le("fieldset", {
|
|
91
|
+
disabled: T(G).processing || A.block.operation === "view",
|
|
88
92
|
class: "contents"
|
|
89
|
-
}, [
|
|
90
|
-
components:
|
|
91
|
-
columns:
|
|
92
|
-
}, null, 8, ["components", "columns"])], 8,
|
|
93
|
-
actions:
|
|
94
|
-
context:
|
|
95
|
-
"on-trigger":
|
|
96
|
-
}, null, 8, ["actions", "context"])])) :
|
|
93
|
+
}, [b(re, {
|
|
94
|
+
components: T(G).components,
|
|
95
|
+
columns: T(G).columns
|
|
96
|
+
}, null, 8, ["components", "columns"])], 8, O), J.value.length > 0 && X.value ? (w(), y("div", k, [b(te, {
|
|
97
|
+
actions: J.value,
|
|
98
|
+
context: K.value,
|
|
99
|
+
"on-trigger": Z
|
|
100
|
+
}, null, 8, ["actions", "context"])])) : ce("", !0)], 32));
|
|
97
101
|
}
|
|
98
102
|
});
|
|
99
103
|
//#endregion
|
|
100
|
-
export {
|
|
104
|
+
export { A as default };
|
|
101
105
|
|
|
102
106
|
//# sourceMappingURL=FormBlock.vue_vue_type_script_setup_true_lang.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FormBlock.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createElementBlock","_withModifiers","_createElementVNode","_unref","_createVNode","SchemaRenderer","ActionList","_createCommentVNode","ActionList_default","SchemaRenderer_default","_hoisted_1","_hoisted_2","FormBlock_vue_vue_type_script_setup_true_lang_default","props","__props","panel","usePanel","page","usePageSchema","pageProps","useAlfakitProps","runner","useActionRunner","t","useT","token","computed","store","FormStore","notifications","showToast","n","router","resolvePartialProps","unregisterPageForm","name","pageFormName","registerPageForm","unregisterConflictForm","onMounted","registerConflictForm","onBeforeUnmount","unregisterSubmitter","registerFormSubmitter","trigger","action","ctx","watch","formIdentity","value","submittedBlock","refillPending","block","errors","state","useStore","context","submitting","actions","primary","progress","wizardProgressStore","showActions","formActionsVisible","submitVisit","offStart","visit","event","offSuccess","id","pageFlash","offRefresh","refresh","formRefreshFor","applyFormRefresh","offFinish","offBefore","isLeavingVisit","onSubmit","onKeydown","isImplicitSubmit","openBlock","createElementBlock","withModifiers","createElementVNode","unref","createVNode","createCommentVNode"],"sources":["../../../src/components/form/FormBlock.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { ActionContext, ActionSchema, FormBlock as FormBlockSchema } from '@alfakit/core'\nimport {\n FormStore,\n applyFormRefresh,\n formActionsVisible,\n formIdentity,\n formRefreshFor,\n isImplicitSubmit,\n isLeavingVisit,\n pageFlash,\n pageFormName,\n registerConflictForm,\n registerFormSubmitter,\n registerPageForm,\n resolvePartialProps,\n wizardProgressStore,\n} from '@alfakit/core'\nimport { router } from '@inertiajs/vue3'\nimport { computed, onBeforeUnmount, onMounted, onScopeDispose, watch } from 'vue'\nimport { useStore } from '../../composables/use-store'\nimport { useActionRunner, useAlfakitProps, usePageSchema, usePanel, useT } from '../../context'\nimport ActionList from '../actions/ActionList.vue'\nimport SchemaRenderer from '../schema/SchemaRenderer.vue'\nimport { showToast } from '../notifications/flash-toasts'\nimport { provideForm } from './form-context'\n\n/**\n * A page form: its state lives in a FormStore, and its buttons are actions that post the\n * current values through the action endpoint.\n */\nconst props = defineProps<{ block: FormBlockSchema }>()\n\nconst panel = usePanel()\nconst page = usePageSchema()\nconst pageProps = useAlfakitProps()\nconst runner = useActionRunner()\nconst t = useT()\nconst token = computed(() => page.value?.token ?? '')\n\nconst store = new FormStore(props.block, {\n token: token.value,\n component: props.block.component,\n refreshUrl: panel.value.endpoints.schemaRefresh,\n optionsUrl: panel.value.endpoints.schemaOptions,\n validateUrl: panel.value.endpoints.schemaValidate,\n // A halted wizard step shows what its hook sent.\n onNotifications: (notifications) => notifications.forEach((n) => showToast(n)),\n // Live dashboard filters are applied by the refresh; the widgets reload to follow.\n onRefreshed: () => {\n if (props.block.liveFilters) router.reload({ only: resolvePartialProps(['page']) })\n },\n})\n\nprovideForm(store)\n\n// Named forms of custom pages (`<PageForm name>`) publish their store for page method calls\n// (browser only: mounted hooks never run during a server render).\nlet unregisterPageForm: (() => void) | undefined\n\nonMounted(() => {\n const name = pageFormName(props.block.component)\n\n if (name) unregisterPageForm = registerPageForm(name, store)\n})\n\n// Edit pages: the conflict banner diffs and merges the main form (`detectConflicts()`).\nlet unregisterConflictForm: (() => void) | undefined\n\nonMounted(() => {\n if (props.block.component === 'form') unregisterConflictForm = registerConflictForm(store)\n})\n\nonBeforeUnmount(() => unregisterConflictForm?.())\n\n// Buttons elsewhere with `formId('form')` (a header \"Save\") submit through this form.\nlet unregisterSubmitter: (() => void) | undefined\n\nonMounted(() => {\n unregisterSubmitter = registerFormSubmitter(props.block.component, (action, ctx) =>\n trigger(action, ctx),\n )\n})\n\nonBeforeUnmount(() => {\n unregisterPageForm?.()\n unregisterSubmitter?.()\n})\n\n// The store survives reloads of the same form (table sorting/paging, polling,\n// relation-manager actions all deliver a new `block` object); only a different form\n// identity starts from server state again. The token is re-issued per response, so it\n// is swapped in place instead of being part of the identity.\nwatch(\n () => formIdentity(page.value, props.block),\n () => store.fill(props.block),\n)\n\nwatch(token, (value) => store.setToken(value))\n\n// After this form's own successful submit, refill from the server's new state. The new\n// block may arrive before or after Inertia's `success` event, so handle both orders.\nlet submittedBlock: FormBlockSchema | null = null\nlet refillPending = false\n\nwatch(\n () => props.block,\n (block) => {\n if (refillPending) {\n refillPending = false\n store.fill(block)\n }\n },\n)\n\nwatch(\n () => pageProps.value.errors,\n (errors) => store.setErrors((errors as Record<string, string>) ?? {}),\n { immediate: true },\n)\n\nconst state = useStore(store.store)\nconst context = computed<ActionContext>(() => ({ token: token.value, component: 'page' }))\nlet submitting = false\n\nconst actions = computed<ActionSchema[]>(() =>\n props.block.actions.map((action) => ({ ...action, hasModal: false })),\n)\nconst primary = computed(() => actions.value[0])\n\n// Wizard forms (`HasWizard` pages) show their buttons on the last step only.\nconst progress = useStore(wizardProgressStore(store))\nconst showActions = computed(() => formActionsVisible(props.block, progress.value))\n\nconst trigger = async (action: ActionSchema, ctx: ActionContext) => {\n if (action.url && !action.hasAction) {\n return runner.trigger(action, ctx)\n }\n\n submitting = true\n submittedBlock = props.block\n store.setProcessing(true)\n runner.execute(action, ctx, store.state.values)\n}\n\n// Track this form's own submit visit so unrelated reloads finishing meanwhile (polling,\n// relation-manager paging) neither end its processing state nor count as its success.\nlet submitVisit: string | null = null\n\nconst offStart = router.on('start', (event) => {\n const visit = event.detail.visit\n\n if (submitting && !submitVisit && visit.method !== 'get') {\n submitVisit = visit.id\n }\n})\n\nconst offSuccess = router.on('success', (event) => {\n const id = submitVisit\n\n if (!id || (event.detail.visitId ?? id) !== id) return\n\n // A halted action (rate limit, `halt()`) saved nothing: keep what the user typed.\n if (pageFlash(event.detail.page).alfakitAction?.status === 'halted') return\n\n if (props.block !== submittedBlock) {\n store.fill(props.block)\n } else {\n refillPending = true\n }\n})\n\n// `refreshFormData([...])`: an action changed the record; copy those fields in.\nconst offRefresh = router.on('success', (event) => {\n const refresh = formRefreshFor(pageFlash(event.detail.page), props.block.component)\n\n if (refresh) applyFormRefresh(store, refresh)\n})\n\nconst offFinish = router.on('finish', (event) => {\n if (submitVisit && event.detail.visit.id !== submitVisit) return\n\n store.setProcessing(false)\n submitting = false\n submitVisit = null\n})\n\nconst offBefore = router.on('before', (event) => {\n if (!panel.value.unsavedChangesAlerts) {\n return\n }\n\n if (\n store.isDirty &&\n !submitting &&\n isLeavingVisit(event.detail.visit) &&\n !window.confirm(t('unsaved_changes', {}, 'You have unsaved changes. Leave anyway?'))\n ) {\n event.preventDefault()\n }\n})\n\nonScopeDispose(() => {\n offStart()\n offSuccess()\n offRefresh()\n offFinish()\n offBefore()\n store.destroy()\n})\n\nconst onSubmit = () => {\n if (primary.value && showActions.value) {\n void trigger(primary.value, context.value)\n }\n}\n\n// Enter in a text field runs the primary action (actions are type=\"button\").\nconst onKeydown = (event: KeyboardEvent) => {\n if (\n primary.value &&\n showActions.value &&\n isImplicitSubmit(event, event.currentTarget as HTMLFormElement)\n ) {\n event.preventDefault()\n void trigger(primary.value, context.value)\n }\n}\n</script>\n\n<template>\n <form\n data-slot=\"form-block\"\n class=\"flex flex-col gap-6\"\n @submit.prevent=\"onSubmit\"\n @keydown=\"onKeydown\"\n >\n <fieldset :disabled=\"state.processing || props.block.operation === 'view'\" class=\"contents\">\n <SchemaRenderer :components=\"state.components\" :columns=\"state.columns\" />\n </fieldset>\n <div v-if=\"actions.length > 0 && showActions\" data-slot=\"form-actions\" class=\"border-t pt-6\">\n <ActionList :actions=\"actions\" :context=\"context\" :on-trigger=\"trigger\" />\n </div>\n </form>\n</template>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"FormBlock.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createElementBlock","_withModifiers","_createElementVNode","_unref","_createVNode","SchemaRenderer","ActionList","_createCommentVNode","ActionList_default","SchemaRenderer_default","_hoisted_1","_hoisted_2","FormBlock_vue_vue_type_script_setup_true_lang_default","props","__props","panel","usePanel","page","usePageSchema","pageProps","useAlfakitProps","runner","useActionRunner","t","useT","token","computed","store","FormStore","notifications","showToast","n","router","resolvePartialProps","unregisterPageForm","name","pageFormName","registerPageForm","unregisterConflictForm","onMounted","registerConflictForm","onBeforeUnmount","unregisterSubmitter","registerFormSubmitter","trigger","action","ctx","watch","formIdentity","value","submittedBlock","refillPending","resyncPending","visitBlock","block","errors","state","useStore","context","submitting","actions","primary","progress","wizardProgressStore","showActions","formActionsVisible","submitVisit","offStart","visit","event","offSuccess","id","shouldResyncForm","pageFlash","offRefresh","refresh","formRefreshFor","applyFormRefresh","offFinish","offBefore","isLeavingVisit","onSubmit","onKeydown","isImplicitSubmit","openBlock","createElementBlock","withModifiers","createElementVNode","unref","createVNode","createCommentVNode"],"sources":["../../../src/components/form/FormBlock.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { ActionContext, ActionSchema, FormBlock as FormBlockSchema } from '@alfakit/core'\nimport {\n FormStore,\n applyFormRefresh,\n formActionsVisible,\n formIdentity,\n formRefreshFor,\n isImplicitSubmit,\n isLeavingVisit,\n pageFlash,\n pageFormName,\n registerConflictForm,\n registerFormSubmitter,\n registerPageForm,\n resolvePartialProps,\n shouldResyncForm,\n wizardProgressStore,\n} from '@alfakit/core'\nimport { router } from '@inertiajs/vue3'\nimport { computed, onBeforeUnmount, onMounted, onScopeDispose, watch } from 'vue'\nimport { useStore } from '../../composables/use-store'\nimport { useActionRunner, useAlfakitProps, usePageSchema, usePanel, useT } from '../../context'\nimport ActionList from '../actions/ActionList.vue'\nimport SchemaRenderer from '../schema/SchemaRenderer.vue'\nimport { showToast } from '../notifications/flash-toasts'\nimport { provideForm } from './form-context'\n\n/**\n * A page form: its state lives in a FormStore, and its buttons are actions that post the\n * current values through the action endpoint.\n */\nconst props = defineProps<{ block: FormBlockSchema }>()\n\nconst panel = usePanel()\nconst page = usePageSchema()\nconst pageProps = useAlfakitProps()\nconst runner = useActionRunner()\nconst t = useT()\nconst token = computed(() => page.value?.token ?? '')\n\nconst store = new FormStore(props.block, {\n token: token.value,\n component: props.block.component,\n refreshUrl: panel.value.endpoints.schemaRefresh,\n optionsUrl: panel.value.endpoints.schemaOptions,\n validateUrl: panel.value.endpoints.schemaValidate,\n // A halted wizard step shows what its hook sent.\n onNotifications: (notifications) => notifications.forEach((n) => showToast(n)),\n // Live dashboard filters are applied by the refresh; the widgets reload to follow.\n onRefreshed: () => {\n if (props.block.liveFilters) router.reload({ only: resolvePartialProps(['page']) })\n },\n})\n\nprovideForm(store)\n\n// Named forms of custom pages (`<PageForm name>`) publish their store for page method calls\n// (browser only: mounted hooks never run during a server render).\nlet unregisterPageForm: (() => void) | undefined\n\nonMounted(() => {\n const name = pageFormName(props.block.component)\n\n if (name) unregisterPageForm = registerPageForm(name, store)\n})\n\n// Edit pages: the conflict banner diffs and merges the main form (`detectConflicts()`).\nlet unregisterConflictForm: (() => void) | undefined\n\nonMounted(() => {\n if (props.block.component === 'form') unregisterConflictForm = registerConflictForm(store)\n})\n\nonBeforeUnmount(() => unregisterConflictForm?.())\n\n// Buttons elsewhere with `formId('form')` (a header \"Save\") submit through this form.\nlet unregisterSubmitter: (() => void) | undefined\n\nonMounted(() => {\n unregisterSubmitter = registerFormSubmitter(props.block.component, (action, ctx) =>\n trigger(action, ctx),\n )\n})\n\nonBeforeUnmount(() => {\n unregisterPageForm?.()\n unregisterSubmitter?.()\n})\n\n// The store survives reloads of the same form (table sorting/paging, polling,\n// relation-manager actions all deliver a new `block` object); only a different form\n// identity starts from server state again. The token is re-issued per response, so it\n// is swapped in place instead of being part of the identity.\nwatch(\n () => formIdentity(page.value, props.block),\n () => store.fill(props.block),\n)\n\nwatch(token, (value) => store.setToken(value))\n\n// After this form's own successful submit, refill from the server's new state. The new\n// block may arrive before or after Inertia's `success` event, so handle both orders.\nlet submittedBlock: FormBlockSchema | null = null\nlet refillPending = false\n// Another action succeeded and its new block has not arrived yet.\nlet resyncPending = false\n// The block when the latest non-GET visit started, to tell whether its response arrived.\nlet visitBlock: FormBlockSchema | null = null\n\nwatch(\n () => props.block,\n (block) => {\n if (refillPending) {\n refillPending = false\n store.fill(block)\n }\n\n if (resyncPending) {\n resyncPending = false\n\n if (!store.isDirty) store.fill(block)\n }\n },\n)\n\nwatch(\n () => pageProps.value.errors,\n (errors) => store.setErrors((errors as Record<string, string>) ?? {}),\n { immediate: true },\n)\n\nconst state = useStore(store.store)\nconst context = computed<ActionContext>(() => ({ token: token.value, component: 'page' }))\nlet submitting = false\n\nconst actions = computed<ActionSchema[]>(() =>\n props.block.actions.map((action) => ({ ...action, hasModal: false })),\n)\nconst primary = computed(() => actions.value[0])\n\n// Wizard forms (`HasWizard` pages) show their buttons on the last step only.\nconst progress = useStore(wizardProgressStore(store))\nconst showActions = computed(() => formActionsVisible(props.block, progress.value))\n\nconst trigger = async (action: ActionSchema, ctx: ActionContext) => {\n if (action.url && !action.hasAction) {\n return runner.trigger(action, ctx)\n }\n\n submitting = true\n submittedBlock = props.block\n store.setProcessing(true)\n runner.execute(action, ctx, store.state.values)\n}\n\n// Track this form's own submit visit so unrelated reloads finishing meanwhile (polling,\n// relation-manager paging) neither end its processing state nor count as its success.\nlet submitVisit: string | null = null\n\nconst offStart = router.on('start', (event) => {\n const visit = event.detail.visit\n\n if (submitting && !submitVisit && visit.method !== 'get') {\n submitVisit = visit.id\n }\n\n if (visit.method !== 'get') visitBlock = props.block\n})\n\nconst offSuccess = router.on('success', (event) => {\n const id = submitVisit\n\n // Another action changed the record: show the server's new form unless it holds edits.\n if (!id && shouldResyncForm(pageFlash(event.detail.page), store)) {\n if (props.block !== visitBlock) {\n store.fill(props.block)\n } else {\n resyncPending = true\n }\n\n return\n }\n\n if (!id || (event.detail.visitId ?? id) !== id) return\n\n // A halted action (rate limit, `halt()`) saved nothing: keep what the user typed.\n if (pageFlash(event.detail.page).alfakitAction?.status === 'halted') return\n\n if (props.block !== submittedBlock) {\n store.fill(props.block)\n } else {\n refillPending = true\n }\n})\n\n// `refreshFormData([...])`: an action changed the record; copy those fields in.\nconst offRefresh = router.on('success', (event) => {\n const refresh = formRefreshFor(pageFlash(event.detail.page), props.block.component)\n\n if (refresh) applyFormRefresh(store, refresh)\n})\n\nconst offFinish = router.on('finish', (event) => {\n if (submitVisit && event.detail.visit.id !== submitVisit) return\n\n store.setProcessing(false)\n submitting = false\n submitVisit = null\n})\n\nconst offBefore = router.on('before', (event) => {\n if (!panel.value.unsavedChangesAlerts) {\n return\n }\n\n if (\n store.isDirty &&\n !submitting &&\n isLeavingVisit(event.detail.visit) &&\n !window.confirm(t('unsaved_changes', {}, 'You have unsaved changes. Leave anyway?'))\n ) {\n event.preventDefault()\n }\n})\n\nonScopeDispose(() => {\n offStart()\n offSuccess()\n offRefresh()\n offFinish()\n offBefore()\n store.destroy()\n})\n\nconst onSubmit = () => {\n if (primary.value && showActions.value) {\n void trigger(primary.value, context.value)\n }\n}\n\n// Enter in a text field runs the primary action (actions are type=\"button\").\nconst onKeydown = (event: KeyboardEvent) => {\n if (\n primary.value &&\n showActions.value &&\n isImplicitSubmit(event, event.currentTarget as HTMLFormElement)\n ) {\n event.preventDefault()\n void trigger(primary.value, context.value)\n }\n}\n</script>\n\n<template>\n <form\n data-slot=\"form-block\"\n class=\"flex flex-col gap-6\"\n @submit.prevent=\"onSubmit\"\n @keydown=\"onKeydown\"\n >\n <fieldset :disabled=\"state.processing || props.block.operation === 'view'\" class=\"contents\">\n <SchemaRenderer :components=\"state.components\" :columns=\"state.columns\" />\n </fieldset>\n <div v-if=\"actions.length > 0 && showActions\" data-slot=\"form-actions\" class=\"border-t pt-6\">\n <ActionList :actions=\"actions\" :context=\"context\" :on-trigger=\"trigger\" />\n </div>\n </form>\n</template>\n"],"mappings":"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"}
|
|
@@ -1,43 +1,43 @@
|
|
|
1
1
|
import { useStore as e } from "../../composables/use-store.js";
|
|
2
|
-
import { fieldAria as t } from "@alfakit/core";
|
|
3
|
-
import { computed as
|
|
2
|
+
import { fieldAria as t, fieldDomId as n } from "@alfakit/core";
|
|
3
|
+
import { computed as r, inject as i, provide as a, toValue as o } from "vue";
|
|
4
4
|
//#region src/components/form/form-context.ts
|
|
5
|
-
var
|
|
6
|
-
function
|
|
7
|
-
|
|
5
|
+
var s = Symbol("alfakit.form");
|
|
6
|
+
function c(e) {
|
|
7
|
+
a(s, e);
|
|
8
8
|
}
|
|
9
|
-
function
|
|
10
|
-
let e =
|
|
9
|
+
function l() {
|
|
10
|
+
let e = i(s, null);
|
|
11
11
|
if (!e) throw Error("Form fields must be rendered inside provideForm().");
|
|
12
12
|
return e;
|
|
13
13
|
}
|
|
14
|
-
function l() {
|
|
15
|
-
return r(o, null);
|
|
16
|
-
}
|
|
17
14
|
function u() {
|
|
18
|
-
return
|
|
15
|
+
return i(s, null);
|
|
16
|
+
}
|
|
17
|
+
function d() {
|
|
18
|
+
return e(l().store);
|
|
19
19
|
}
|
|
20
|
-
function
|
|
21
|
-
let
|
|
22
|
-
let e =
|
|
23
|
-
for (let t of
|
|
20
|
+
function f(i) {
|
|
21
|
+
let a = l(), s = e(a.store), c = o(i).statePath, u = r(() => {
|
|
22
|
+
let e = s.value.values;
|
|
23
|
+
for (let t of c.split(".")) {
|
|
24
24
|
if (typeof e != "object" || !e) return;
|
|
25
25
|
e = e[t];
|
|
26
26
|
}
|
|
27
27
|
return e;
|
|
28
|
-
}),
|
|
28
|
+
}), d = r(() => s.value.errors[c]?.[0]), f = r(() => !!o(i).disabled), p = r(() => !!o(i).readOnly), m = o(i).id ?? n(a.idPrefix, c);
|
|
29
29
|
return {
|
|
30
|
-
value:
|
|
31
|
-
setValue: (e) =>
|
|
32
|
-
blur: () =>
|
|
33
|
-
error:
|
|
34
|
-
id:
|
|
35
|
-
disabled:
|
|
36
|
-
readOnly:
|
|
37
|
-
aria:
|
|
30
|
+
value: u,
|
|
31
|
+
setValue: (e) => a.setValue(c, e),
|
|
32
|
+
blur: () => a.blur(c),
|
|
33
|
+
error: d,
|
|
34
|
+
id: m,
|
|
35
|
+
disabled: f,
|
|
36
|
+
readOnly: p,
|
|
37
|
+
aria: r(() => t(m, o(i), d.value))
|
|
38
38
|
};
|
|
39
39
|
}
|
|
40
40
|
//#endregion
|
|
41
|
-
export {
|
|
41
|
+
export { s as FORM_STORE_KEY, c as provideForm, f as useField, d as useFormState, l as useFormStore, u as useOptionalFormStore };
|
|
42
42
|
|
|
43
43
|
//# sourceMappingURL=form-context.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"form-context.js","names":["FORM_STORE_KEY","provideForm","store","useFormStore","inject","useOptionalFormStore","useFormState","useStore","useField","state","path","toValue","field","value","computed","current","segment","error","disabled","readOnly","id","next","fieldAria"],"sources":["../../../src/components/form/form-context.ts"],"sourcesContent":["import type { BaseField, FieldAriaAttributes, FormState, FormStore } from '@alfakit/core'\nimport { fieldAria } from '@alfakit/core'\nimport {\n computed,\n inject,\n provide,\n toValue,\n type ComputedRef,\n type InjectionKey,\n type MaybeRefOrGetter,\n type ShallowRef,\n} from 'vue'\nimport { useStore } from '../../composables/use-store'\n\nexport const FORM_STORE_KEY: InjectionKey<FormStore> = Symbol('alfakit.form')\n\nexport function provideForm(store: FormStore): void {\n provide(FORM_STORE_KEY, store)\n}\n\nexport function useFormStore(): FormStore {\n const store = inject(FORM_STORE_KEY, null)\n\n if (!store) {\n throw new Error('Form fields must be rendered inside provideForm().')\n }\n\n return store\n}\n\nexport function useOptionalFormStore(): FormStore | null {\n return inject(FORM_STORE_KEY, null)\n}\n\nexport function useFormState(): ShallowRef<FormState> {\n return useStore(useFormStore().store)\n}\n\nexport interface FieldBinding<T = unknown> {\n value: ComputedRef<T>\n setValue: (value: T) => void\n blur: () => void\n error: ComputedRef<string | undefined>\n id: string\n /** The field cannot be interacted with at all (`disabled()`). */\n disabled: ComputedRef<boolean>\n /** The field shows its value but the user cannot change it (`readOnly()`). */\n readOnly: ComputedRef<boolean>\n /** `aria-describedby` (hint, helper text, error), `aria-invalid` and `aria-required` for the control. */\n aria: ComputedRef<FieldAriaAttributes>\n}\n\n/** Bind a field schema to the form store. */\nexport function useField<T = unknown>(field: MaybeRefOrGetter<BaseField>): FieldBinding<T> {\n const store = useFormStore()\n const state = useStore(store.store)\n const path = toValue(field).statePath\n\n const value = computed(() => {\n let current: unknown = state.value.values\n\n for (const segment of path.split('.')) {\n if (current === null || current === undefined || typeof current !== 'object') {\n return undefined as T\n }\n\n current = (current as Record<string, unknown>)[segment]\n }\n\n return current as T\n })\n\n const error = computed(() => state.value.errors[path]?.[0])\n // Fields stay enabled during a live refresh: the store keeps edits made while the request\n // is in flight, so locking inputs would only swallow keystrokes.\n const disabled = computed(() => Boolean(toValue(field).disabled))\n const readOnly = computed(() => Boolean(toValue(field).readOnly))\n const id = toValue(field).id ??
|
|
1
|
+
{"version":3,"file":"form-context.js","names":["FORM_STORE_KEY","provideForm","store","useFormStore","inject","useOptionalFormStore","useFormState","useStore","useField","state","path","toValue","field","value","computed","current","segment","error","disabled","readOnly","id","fieldDomId","next","fieldAria"],"sources":["../../../src/components/form/form-context.ts"],"sourcesContent":["import type { BaseField, FieldAriaAttributes, FormState, FormStore } from '@alfakit/core'\nimport { fieldAria, fieldDomId } from '@alfakit/core'\nimport {\n computed,\n inject,\n provide,\n toValue,\n type ComputedRef,\n type InjectionKey,\n type MaybeRefOrGetter,\n type ShallowRef,\n} from 'vue'\nimport { useStore } from '../../composables/use-store'\n\nexport const FORM_STORE_KEY: InjectionKey<FormStore> = Symbol('alfakit.form')\n\nexport function provideForm(store: FormStore): void {\n provide(FORM_STORE_KEY, store)\n}\n\nexport function useFormStore(): FormStore {\n const store = inject(FORM_STORE_KEY, null)\n\n if (!store) {\n throw new Error('Form fields must be rendered inside provideForm().')\n }\n\n return store\n}\n\nexport function useOptionalFormStore(): FormStore | null {\n return inject(FORM_STORE_KEY, null)\n}\n\nexport function useFormState(): ShallowRef<FormState> {\n return useStore(useFormStore().store)\n}\n\nexport interface FieldBinding<T = unknown> {\n value: ComputedRef<T>\n setValue: (value: T) => void\n blur: () => void\n error: ComputedRef<string | undefined>\n id: string\n /** The field cannot be interacted with at all (`disabled()`). */\n disabled: ComputedRef<boolean>\n /** The field shows its value but the user cannot change it (`readOnly()`). */\n readOnly: ComputedRef<boolean>\n /** `aria-describedby` (hint, helper text, error), `aria-invalid` and `aria-required` for the control. */\n aria: ComputedRef<FieldAriaAttributes>\n}\n\n/** Bind a field schema to the form store. */\nexport function useField<T = unknown>(field: MaybeRefOrGetter<BaseField>): FieldBinding<T> {\n const store = useFormStore()\n const state = useStore(store.store)\n const path = toValue(field).statePath\n\n const value = computed(() => {\n let current: unknown = state.value.values\n\n for (const segment of path.split('.')) {\n if (current === null || current === undefined || typeof current !== 'object') {\n return undefined as T\n }\n\n current = (current as Record<string, unknown>)[segment]\n }\n\n return current as T\n })\n\n const error = computed(() => state.value.errors[path]?.[0])\n // Fields stay enabled during a live refresh: the store keeps edits made while the request\n // is in flight, so locking inputs would only swallow keystrokes.\n const disabled = computed(() => Boolean(toValue(field).disabled))\n const readOnly = computed(() => Boolean(toValue(field).readOnly))\n const id = toValue(field).id ?? fieldDomId(store.idPrefix, path)\n const aria = computed(() => fieldAria(id, toValue(field), error.value))\n\n return {\n value,\n setValue: (next: T) => store.setValue(path, next),\n blur: () => store.blur(path),\n error,\n id,\n disabled,\n readOnly,\n aria,\n }\n}\n"],"mappings":";;;;AAcA,IAAaA,IAA0C,OAAO,cAAc;AAE5E,SAAgBC,EAAY,GAAwB;CAClD,EAAQD,GAAgBE,CAAK;AAC/B;AAEA,SAAgBC,IAA0B;CACxC,IAAMD,IAAQE,EAAOJ,GAAgB,IAAI;CAEzC,IAAI,CAACE,GACH,MAAU,MAAM,oDAAoD;CAGtE,OAAOA;AACT;AAEA,SAAgBG,IAAyC;CACvD,OAAOD,EAAOJ,GAAgB,IAAI;AACpC;AAEA,SAAgBM,IAAsC;CACpD,OAAOC,EAASJ,EAAa,CAAC,CAAC,KAAK;AACtC;AAiBA,SAAgBK,EAAsB,GAAqD;CACzF,IAAMN,IAAQC,EAAa,GACrBM,IAAQF,EAASL,EAAM,KAAK,GAC5BQ,IAAOC,EAAQC,CAAK,CAAC,CAAC,WAEtBC,IAAQC,QAAe;EAC3B,IAAIC,IAAmBN,EAAM,MAAM;EAEnC,KAAK,IAAMO,KAAWN,EAAK,MAAM,GAAG,GAAG;GACrC,IAAiD,OAAOK,KAAY,aAAhEA,GACF;GAGF,IAAWA,EAAoCC;EACjD;EAEA,OAAOD;CACT,CAAC,GAEKE,IAAQH,QAAeL,EAAM,MAAM,OAAOC,EAAK,GAAG,EAAE,GAGpDQ,IAAWJ,QAAe,EAAQH,EAAQC,CAAK,CAAC,CAAC,QAAS,GAC1DO,IAAWL,QAAe,EAAQH,EAAQC,CAAK,CAAC,CAAC,QAAS,GAC1DQ,IAAKT,EAAQC,CAAK,CAAC,CAAC,MAAMS,EAAWnB,EAAM,UAAUQ,CAAI;CAG/D,OAAO;EACL;EACA,WAAW,MAAYR,EAAM,SAASQ,GAAMY,CAAI;EAChD,YAAYpB,EAAM,KAAKQ,CAAI;EAC3B;EACA;EACA;EACA;EACA,MAVWI,QAAeS,EAAUH,GAAIT,EAAQC,CAAK,GAAGK,EAAM,KAAK,CAUnE;CACF;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FusedGroupComponent.js","names":["_sfc_main","FusedGroupComponent_vue_vue_type_script_setup_true_lang_default","FusedGroupComponent_default"],"sources":["../../../src/components/layout/FusedGroupComponent.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { FusedGroupSchema } from '@alfakit/core'\nimport { collectFieldStatePaths, gridColumnsClasses } from '@alfakit/core'\nimport { computed, shallowRef, useId } from 'vue'\nimport { useStore } from '../../composables/use-store'\nimport { cn } from '../../lib/utils'\nimport { useOptionalFormStore } from '../form/form-context'\nimport { provideFusedGroup } from '../schema/fused-group'\nimport RenderComponent from '../schema/RenderComponent.vue'\n\n/**\n * Fields fused into one control: one border around them (styled by `themes.css`), the\n * group label above, and the fields' validation errors below.\n */\nconst props = defineProps<{ component: FusedGroupSchema }>()\n\nprovideFusedGroup()\n\nconst labelId = `${useId()}-label`\nconst store = useOptionalFormStore()\nconst state = store ? useStore(store.store) : shallowRef(null)\nconst paths = computed(() => collectFieldStatePaths(props.component.schema))\nconst errors = computed(() =>\n state.value\n ? paths.value\n .map((path) => state.value?.errors[path]?.[0])\n .filter((message): message is string => Boolean(message))\n : [],\n)\n</script>\n\n<template>\n <div\n data-slot=\"fused-group\"\n role=\"group\"\n :aria-labelledby=\"props.component.label ? labelId : undefined\"\n class=\"flex flex-col gap-1.5\"\n v-bind=\"props.component.extraAttributes\"\n >\n <span\n v-if=\"props.component.label\"\n :id=\"labelId\"\n class=\"text-sm leading-none font-medium select-none\"\n >\n {{ props.component.label }}\n </span>\n <div\n data-slot=\"fused-group-controls\"\n :data-invalid=\"errors.length ? '' : undefined\"\n :class=\"cn('grid', gridColumnsClasses(props.component.columns ?? { default: 1 }))\"\n >\n <RenderComponent\n v-for=\"child in props.component.schema ?? []\"\n :key=\"child.key\"\n :component=\"child\"\n />\n </div>\n <!-- The fields announce their own errors; this list is the visible copy. -->\n <div v-if=\"errors.length\" aria-hidden=\"true\" class=\"flex flex-col gap-0.5\">\n <p v-for=\"(message, index) in errors\" :key=\"index\" class=\"text-destructive text-xs\">\n {{ message }}\n </p>\n </div>\n </div>\n</template>\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"FusedGroupComponent.js","names":["_sfc_main","FusedGroupComponent_vue_vue_type_script_setup_true_lang_default","FusedGroupComponent_default"],"sources":["../../../src/components/layout/FusedGroupComponent.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { FusedGroupSchema } from '@alfakit/core'\nimport { collectFieldStatePaths, gridColumnsClasses } from '@alfakit/core'\nimport { computed, shallowRef, useId } from 'vue'\nimport { useStore } from '../../composables/use-store'\nimport { cn } from '../../lib/utils'\nimport { useOptionalFormStore } from '../form/form-context'\nimport { provideFusedGroup } from '../schema/fused-group'\nimport RenderComponent from '../schema/RenderComponent.vue'\n\n/**\n * Fields fused into one control: one border around them (styled by `themes.css`), the\n * group label above, and the fields' validation errors below.\n */\nconst props = defineProps<{ component: FusedGroupSchema }>()\n\nprovideFusedGroup()\n\nconst labelId = `${useId()}-label`\nconst store = useOptionalFormStore()\nconst state = store ? useStore(store.store) : shallowRef(null)\nconst paths = computed(() => collectFieldStatePaths(props.component.schema))\nconst errors = computed(() =>\n state.value\n ? paths.value\n .map((path) => state.value?.errors[path]?.[0])\n .filter((message): message is string => Boolean(message))\n : [],\n)\n</script>\n\n<template>\n <div\n data-slot=\"fused-group\"\n role=\"group\"\n :aria-labelledby=\"props.component.label ? labelId : undefined\"\n class=\"flex flex-col gap-1.5\"\n v-bind=\"props.component.extraAttributes\"\n >\n <span\n v-if=\"props.component.label\"\n :id=\"labelId\"\n data-slot=\"label\"\n class=\"text-sm leading-none font-medium select-none\"\n >\n {{ props.component.label }}\n </span>\n <div\n data-slot=\"fused-group-controls\"\n :data-invalid=\"errors.length ? '' : undefined\"\n :class=\"cn('grid', gridColumnsClasses(props.component.columns ?? { default: 1 }))\"\n >\n <RenderComponent\n v-for=\"child in props.component.schema ?? []\"\n :key=\"child.key\"\n :component=\"child\"\n />\n </div>\n <!-- The fields announce their own errors; this list is the visible copy. -->\n <div v-if=\"errors.length\" aria-hidden=\"true\" class=\"flex flex-col gap-0.5\">\n <p v-for=\"(message, index) in errors\" :key=\"index\" class=\"text-destructive text-xs\">\n {{ message }}\n </p>\n </div>\n </div>\n</template>\n"],"mappings":""}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FusedGroupComponent.vue.d.ts","sourceRoot":"","sources":["../../../src/components/layout/FusedGroupComponent.vue"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"FusedGroupComponent.vue.d.ts","sourceRoot":"","sources":["../../../src/components/layout/FusedGroupComponent.vue"],"names":[],"mappings":"AAoEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AASrD;;;GAGG;AACH,KAAK,WAAW,GAAG;IAAE,SAAS,EAAE,gBAAgB,CAAA;CAAE,CAAC;;AA0GnD,wBAMG"}
|
package/dist/components/layout/FusedGroupComponent.vue_vue_type_script_setup_true_lang.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FusedGroupComponent.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createElementBlock","_mergeProps","_toDisplayString","_createCommentVNode","_createElementVNode","_normalizeClass","_unref","_Fragment","_renderList","_createBlock","RenderComponent","RenderComponent_default","_hoisted_1","_hoisted_2","_hoisted_3","FusedGroupComponent_vue_vue_type_script_setup_true_lang_default","props","__props","labelId","useId","store","useOptionalFormStore","state","useStore","shallowRef","paths","computed","collectFieldStatePaths","errors","path","message","openBlock","createElementBlock","mergeProps","toDisplayString","createCommentVNode","createElementVNode","normalizeClass","unref","cn","gridColumnsClasses","Fragment","renderList","createBlock","child","index"],"sources":["../../../src/components/layout/FusedGroupComponent.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { FusedGroupSchema } from '@alfakit/core'\nimport { collectFieldStatePaths, gridColumnsClasses } from '@alfakit/core'\nimport { computed, shallowRef, useId } from 'vue'\nimport { useStore } from '../../composables/use-store'\nimport { cn } from '../../lib/utils'\nimport { useOptionalFormStore } from '../form/form-context'\nimport { provideFusedGroup } from '../schema/fused-group'\nimport RenderComponent from '../schema/RenderComponent.vue'\n\n/**\n * Fields fused into one control: one border around them (styled by `themes.css`), the\n * group label above, and the fields' validation errors below.\n */\nconst props = defineProps<{ component: FusedGroupSchema }>()\n\nprovideFusedGroup()\n\nconst labelId = `${useId()}-label`\nconst store = useOptionalFormStore()\nconst state = store ? useStore(store.store) : shallowRef(null)\nconst paths = computed(() => collectFieldStatePaths(props.component.schema))\nconst errors = computed(() =>\n state.value\n ? paths.value\n .map((path) => state.value?.errors[path]?.[0])\n .filter((message): message is string => Boolean(message))\n : [],\n)\n</script>\n\n<template>\n <div\n data-slot=\"fused-group\"\n role=\"group\"\n :aria-labelledby=\"props.component.label ? labelId : undefined\"\n class=\"flex flex-col gap-1.5\"\n v-bind=\"props.component.extraAttributes\"\n >\n <span\n v-if=\"props.component.label\"\n :id=\"labelId\"\n class=\"text-sm leading-none font-medium select-none\"\n >\n {{ props.component.label }}\n </span>\n <div\n data-slot=\"fused-group-controls\"\n :data-invalid=\"errors.length ? '' : undefined\"\n :class=\"cn('grid', gridColumnsClasses(props.component.columns ?? { default: 1 }))\"\n >\n <RenderComponent\n v-for=\"child in props.component.schema ?? []\"\n :key=\"child.key\"\n :component=\"child\"\n />\n </div>\n <!-- The fields announce their own errors; this list is the visible copy. -->\n <div v-if=\"errors.length\" aria-hidden=\"true\" class=\"flex flex-col gap-0.5\">\n <p v-for=\"(message, index) in errors\" :key=\"index\" class=\"text-destructive text-xs\">\n {{ message }}\n </p>\n </div>\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;EAcA,IAAMiB,IAAQC;EAEd,EAAkB;EAElB,IAAMC,IAAU,GAAGC,EAAM,EAAE,SACrBC,IAAQC,EAAqB,GAC7BC,IAAQF,IAAQG,EAASH,EAAM,KAAK,IAAII,EAAW,IAAI,GACvDC,IAAQC,QAAeC,EAAuBX,EAAM,UAAU,MAAM,CAAC,GACrEY,IAASF,QACbJ,EAAM,QACFG,EAAM,MACH,KAAK,MAASH,EAAM,OAAO,OAAOO,EAAK,GAAG,EAAE,CAAA,CAC5C,QAAQ,MAA+B,EAAQC,CAAQ,IAC1D,CAAC,CACP;oBAIE/B,EAAA,GAAAC,
|
|
1
|
+
{"version":3,"file":"FusedGroupComponent.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createElementBlock","_mergeProps","_toDisplayString","_createCommentVNode","_createElementVNode","_normalizeClass","_unref","_Fragment","_renderList","_createBlock","RenderComponent","RenderComponent_default","_hoisted_1","_hoisted_2","_hoisted_3","FusedGroupComponent_vue_vue_type_script_setup_true_lang_default","props","__props","labelId","useId","store","useOptionalFormStore","state","useStore","shallowRef","paths","computed","collectFieldStatePaths","errors","path","message","openBlock","createElementBlock","mergeProps","toDisplayString","createCommentVNode","createElementVNode","normalizeClass","unref","cn","gridColumnsClasses","Fragment","renderList","createBlock","child","index"],"sources":["../../../src/components/layout/FusedGroupComponent.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { FusedGroupSchema } from '@alfakit/core'\nimport { collectFieldStatePaths, gridColumnsClasses } from '@alfakit/core'\nimport { computed, shallowRef, useId } from 'vue'\nimport { useStore } from '../../composables/use-store'\nimport { cn } from '../../lib/utils'\nimport { useOptionalFormStore } from '../form/form-context'\nimport { provideFusedGroup } from '../schema/fused-group'\nimport RenderComponent from '../schema/RenderComponent.vue'\n\n/**\n * Fields fused into one control: one border around them (styled by `themes.css`), the\n * group label above, and the fields' validation errors below.\n */\nconst props = defineProps<{ component: FusedGroupSchema }>()\n\nprovideFusedGroup()\n\nconst labelId = `${useId()}-label`\nconst store = useOptionalFormStore()\nconst state = store ? useStore(store.store) : shallowRef(null)\nconst paths = computed(() => collectFieldStatePaths(props.component.schema))\nconst errors = computed(() =>\n state.value\n ? paths.value\n .map((path) => state.value?.errors[path]?.[0])\n .filter((message): message is string => Boolean(message))\n : [],\n)\n</script>\n\n<template>\n <div\n data-slot=\"fused-group\"\n role=\"group\"\n :aria-labelledby=\"props.component.label ? labelId : undefined\"\n class=\"flex flex-col gap-1.5\"\n v-bind=\"props.component.extraAttributes\"\n >\n <span\n v-if=\"props.component.label\"\n :id=\"labelId\"\n data-slot=\"label\"\n class=\"text-sm leading-none font-medium select-none\"\n >\n {{ props.component.label }}\n </span>\n <div\n data-slot=\"fused-group-controls\"\n :data-invalid=\"errors.length ? '' : undefined\"\n :class=\"cn('grid', gridColumnsClasses(props.component.columns ?? { default: 1 }))\"\n >\n <RenderComponent\n v-for=\"child in props.component.schema ?? []\"\n :key=\"child.key\"\n :component=\"child\"\n />\n </div>\n <!-- The fields announce their own errors; this list is the visible copy. -->\n <div v-if=\"errors.length\" aria-hidden=\"true\" class=\"flex flex-col gap-0.5\">\n <p v-for=\"(message, index) in errors\" :key=\"index\" class=\"text-destructive text-xs\">\n {{ message }}\n </p>\n </div>\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;EAcA,IAAMiB,IAAQC;EAEd,EAAkB;EAElB,IAAMC,IAAU,GAAGC,EAAM,EAAE,SACrBC,IAAQC,EAAqB,GAC7BC,IAAQF,IAAQG,EAASH,EAAM,KAAK,IAAII,EAAW,IAAI,GACvDC,IAAQC,QAAeC,EAAuBX,EAAM,UAAU,MAAM,CAAC,GACrEY,IAASF,QACbJ,EAAM,QACFG,EAAM,MACH,KAAK,MAASH,EAAM,OAAO,OAAOO,EAAK,GAAG,EAAE,CAAA,CAC5C,QAAQ,MAA+B,EAAQC,CAAQ,IAC1D,CAAC,CACP;oBAIE/B,EAAA,GAAAC,EAgCM,OAhCNC,EAgCM;GA/BJ,aAAU;GACV,MAAK;GACJ,mBAAiBe,EAAM,UAAU,QAAQE,IAAU,KAAA;GACpD,OAAM;EACE,GAAAF,EAAM,UAAU,eAAe,GAAA;GAG/BA,EAAM,UAAU,SADxBjB,EAAA,GAAAC,EAOO,QAAA;;IALJ,IAAIkB;IACL,aAAU;IACV,OAAM;GAEH,GAAAhB,EAAAc,EAAM,UAAU,KAAK,GAAA,CAAA,KAAAmB,EAAA,IAAA,EAAA;GAE1B/B,EAUM,OAAA;IATJ,aAAU;IACT,gBAAcwB,EAAA,MAAO,SAAM,KAAQ,KAAA;IACnC,OAAKvB,EAAEC,EAAAiC,CAAA,CAAE,CAAA,QAASjC,EAAAkC,CAAA,CAAkB,CAACxB,EAAM,UAAU,WAAO,EAAA,SAAA,EAAA,CAAA,CAAA,CAAA;GAE7DjB,GAAAA,EAAAA,EAAA,EAAA,GAAAC,EAIEO,GAAA,MAAAC,EAHgBQ,EAAM,UAAU,UAAM,CAAA,IAA/B,OADTjB,EAAA,GAAAU,EAIEC,GAAA;IAFC,KAAKkC,EAAM;IACX,WAAWA;;GAILhB,EAAA,MAAO,UAAlB7B,EAAA,GAAAC,EAIM,OAJNc,GAIM,EAHJf,EAAA,EAAA,GAAAC,EAEIO,GAAA,MAAAC,EAF0BoB,EAAA,QAAnB,GAAS,OAApB7B,EAAA,GAAAC,EAEI,KAAA;IAFmC,KAAK6C;IAAO,OAAM;GACpD,GAAA3C,EAAA4B,CAAO,GAAA,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TabsComponent.js","names":["_sfc_main","TabsComponent_vue_vue_type_script_setup_true_lang_default","TabsComponent_default"],"sources":["../../../src/components/layout/TabsComponent.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { TabsSchema } from '@alfakit/core'\nimport {
|
|
1
|
+
{"version":3,"file":"TabsComponent.js","names":["_sfc_main","TabsComponent_vue_vue_type_script_setup_true_lang_default","TabsComponent_default"],"sources":["../../../src/components/layout/TabsComponent.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { TabsSchema } from '@alfakit/core'\nimport {\n componentHasErrors,\n readPersisted,\n schemaGapClass,\n tabFromQuery,\n tabQueryValue,\n tabToReveal,\n writePersisted,\n} from '@alfakit/core'\nimport { usePage } from '@inertiajs/vue3'\nimport { computed, onMounted, ref, watch } from 'vue'\nimport { useStoreSelector } from '../../composables/use-store'\nimport { useT } from '../../context'\nimport { Icon } from '../../lib/icons'\nimport { cn } from '../../lib/utils'\nimport { useOptionalFormStore } from '../form/form-context'\nimport SchemaRenderer from '../schema/SchemaRenderer.vue'\nimport Tabs from '../ui/Tabs.vue'\nimport TabsContent from '../ui/TabsContent.vue'\nimport TabsList from '../ui/TabsList.vue'\nimport TabsTrigger from '../ui/TabsTrigger.vue'\nimport DeferredSchema from './DeferredSchema.vue'\nimport TabBadge from './TabBadge.vue'\n\nconst props = defineProps<{ component: TabsSchema }>()\nconst tabs = computed(() => props.component.schema ?? [])\n// The page URL (not `window.location`) so the server renders the same tab as the browser.\nconst page = usePage()\n// The tab's readable value (`?tab=billing-address`), or its key in links from older versions.\nconst fromQuery = props.component.queryStringKey\n ? tabFromQuery(\n tabs.value,\n new URL(page.url, 'http://localhost').searchParams.get(props.component.queryStringKey),\n )\n : null\nconst active = ref<string>(\n fromQuery ??\n tabs.value[Math.max(0, props.component.activeTab - 1)]?.key ??\n tabs.value[0]?.key ??\n '',\n)\n\n// `persistTab()`: restored after mounting (the server can't read browser storage); a tab\n// named in the query string wins.\nonMounted(() => {\n const persist = props.component.persistTab\n\n if (!persist || fromQuery) return\n\n const stored = readPersisted(persist.key, persist.storage)\n\n if (stored && tabs.value.some((tab) => tab.key === stored)) active.value = stored\n})\n\n// Tabs holding a field with a validation error are marked, and when a submit brings new\n// errors while the open tab has none, the first tab with an error opens.\nconst TAB_INVALID_CLASSES =\n 'text-destructive data-[state=active]:text-destructive dark:text-destructive dark:data-[state=active]:text-destructive'\nconst t = useT()\nconst store = useOptionalFormStore()\nconst errors = useStoreSelector(\n store?.store ?? {\n get: () => ({ errors: {} as Record<string, string[]> }),\n subscribe: () => () => {},\n },\n (state) => state.errors,\n)\nconst invalidTabs = computed(\n () =>\n new Set(\n tabs.value.filter((tab) => componentHasErrors(tab, errors.value)).map((tab) => tab.key),\n ),\n)\n\nwatch(\n errors,\n (next, previous) => {\n const reveal = tabToReveal(tabs.value, active.value, previous ?? {}, next)\n\n if (reveal !== null) active.value = reveal\n },\n { immediate: true },\n)\n\nfunction changeTab(value: string) {\n active.value = value\n\n const persist = props.component.persistTab\n\n if (persist) writePersisted(persist.key, value, persist.storage)\n}\n\nwatch(\n active,\n (value) => {\n if (!props.component.queryStringKey || typeof window === 'undefined') return\n\n const tab = tabs.value.find((item) => item.key === value)\n const url = new URL(window.location.href)\n url.searchParams.set(props.component.queryStringKey, tab ? tabQueryValue(tab) : value)\n window.history.replaceState(window.history.state, '', url)\n },\n { immediate: true },\n)\n</script>\n\n<template>\n <Tabs\n :data-surface=\"props.component.contained ? 'tabs' : undefined\"\n :model-value=\"active\"\n :orientation=\"props.component.vertical ? 'vertical' : 'horizontal'\"\n :class=\"\n cn(\n props.component.contained && 'bg-card rounded-xl border shadow-xs',\n props.component.vertical && 'flex-row',\n )\n \"\n v-bind=\"props.component.extraAttributes\"\n @update:model-value=\"changeTab(String($event))\"\n >\n <TabsList\n :data-scrollable=\"props.component.scrollable === false ? 'false' : undefined\"\n :class=\"\n cn(\n props.component.contained && 'm-2',\n props.component.vertical\n ? 'self-start'\n : props.component.scrollable === false\n ? 'h-auto max-w-full flex-wrap justify-start'\n : 'relative max-w-full overflow-x-auto',\n )\n \"\n >\n <TabsTrigger\n v-for=\"tab in tabs\"\n :key=\"tab.key\"\n :value=\"tab.key\"\n :data-invalid=\"invalidTabs.has(tab.key) || undefined\"\n :class=\"invalidTabs.has(tab.key) ? TAB_INVALID_CLASSES : undefined\"\n >\n <Icon v-if=\"tab.icon && tab.iconPosition !== 'after'\" :name=\"tab.icon\" />\n {{ tab.label }}\n <Icon v-if=\"tab.icon && tab.iconPosition === 'after'\" :name=\"tab.icon\" />\n <TabBadge :tab=\"tab\" />\n <template v-if=\"invalidTabs.has(tab.key)\">\n <span aria-hidden=\"true\" class=\"bg-destructive size-1.5 shrink-0 rounded-full\"></span>\n <span class=\"sr-only\">({{ t('translatable.has_errors') }})</span>\n </template>\n </TabsTrigger>\n </TabsList>\n <TabsContent\n v-for=\"tab in tabs\"\n :key=\"tab.key\"\n :value=\"tab.key\"\n force-mount\n :class=\"cn('data-[state=inactive]:hidden', props.component.contained ? 'p-6 pt-4' : 'pt-4')\"\n >\n <DeferredSchema v-slot=\"{ component: loaded }\" :component=\"tab\">\n <SchemaRenderer\n :components=\"loaded.schema ?? []\"\n :columns=\"loaded.columns\"\n :attributes=\"loaded.extraAttributes\"\n :class=\"schemaGapClass(loaded) || undefined\"\n />\n </DeferredSchema>\n </TabsContent>\n </Tabs>\n</template>\n"],"mappings":""}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TabsComponent.vue.d.ts","sourceRoot":"","sources":["../../../src/components/layout/TabsComponent.vue"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"TabsComponent.vue.d.ts","sourceRoot":"","sources":["../../../src/components/layout/TabsComponent.vue"],"names":[],"mappings":"AA4KA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAyB/C,KAAK,WAAW,GAAG;IAAE,SAAS,EAAE,UAAU,CAAA;CAAE,CAAC;;AA+S7C,wBAMG"}
|