@shwfed/config 2.10.8 → 2.10.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/mcp.mjs +1143 -1024
- package/dist/module.json +1 -1
- package/dist/preview/assets/{FieldGroup.vue_vue_type_script_setup_true_lang-BX_UfcPb.js → FieldGroup.vue_vue_type_script_setup_true_lang-CysVgnB5.js} +1 -1
- package/dist/preview/assets/{badge-obDKnV3E.js → badge-DdxT1J-1.js} +1 -1
- package/dist/preview/assets/{config-CYdIN2D7.js → config-073z__NM.js} +1 -1
- package/dist/preview/assets/{config-DxmfhxW9.js → config-91HQEKhM.js} +1 -1
- package/dist/preview/assets/{config-xdKDKKAa.js → config-B8k8y1J1.js} +1 -1
- package/dist/preview/assets/{config-BKVK2els.js → config-BK8WZ3pm.js} +1 -1
- package/dist/preview/assets/{config-jBRCpIX5.js → config-BX05eMo3.js} +1 -1
- package/dist/preview/assets/{config-DbdgS5Ng.js → config-BXP8aJwW.js} +1 -1
- package/dist/preview/assets/{config-CaaIte9f.js → config-BhPAyftm.js} +1 -1
- package/dist/preview/assets/{config-BYhrPimZ.js → config-BzHBSkht.js} +1 -1
- package/dist/preview/assets/{config-9weuJKPA.js → config-C3eoRHUo.js} +1 -1
- package/dist/preview/assets/{config-DSD3RZZt.js → config-CJ-NzxkH.js} +1 -1
- package/dist/preview/assets/{config-C6IfQR2K.js → config-CYRj2ZVL.js} +1 -1
- package/dist/preview/assets/{config-CnpY7wA_.js → config-DLNjjMZY.js} +1 -1
- package/dist/preview/assets/{config-DGJLbdm3.js → config-DudxzmzF.js} +1 -1
- package/dist/preview/assets/{config-B27gvYuN.js → config-cwlK3BMD.js} +1 -1
- package/dist/preview/assets/{definition.vue_vue_type_script_setup_true_lang-C97mjLAr.js → definition.vue_vue_type_script_setup_true_lang-l59C6Dgs.js} +1 -1
- package/dist/preview/assets/index-BL58N7_5.js +763 -0
- package/dist/preview/assets/index-CA4hsfRv.js +1 -0
- package/dist/preview/assets/index-CyVzfRGQ.css +1 -0
- package/dist/preview/assets/{index-BWc0rZ2y.js → index-uAwC9Itb.js} +1 -1
- package/dist/preview/assets/{item-BRGONTEu.js → item-C79mwh5T.js} +1 -1
- package/dist/preview/assets/{runtime-Ci3L--AW.js → runtime-1_EaFcPI.js} +1 -1
- package/dist/preview/assets/{runtime-D-9NZJ0Z.js → runtime-2yzxOLnF.js} +1 -1
- package/dist/preview/assets/{runtime-DZtGKJgS.js → runtime-8Fe67mkZ.js} +1 -1
- package/dist/preview/assets/{runtime-BoiTEUZt.js → runtime-8oME8Env.js} +1 -1
- package/dist/preview/assets/{runtime-Czg0F_NN.js → runtime-CCMixJjP.js} +1 -1
- package/dist/preview/assets/{runtime-BGRgWBLF.js → runtime-CD1Q4rZ3.js} +1 -1
- package/dist/preview/assets/{runtime-DcQjFFJx.js → runtime-Cb-qIo5p.js} +1 -1
- package/dist/preview/assets/{runtime-CHOWqPGP.js → runtime-CvgAq3mp.js} +1 -1
- package/dist/preview/assets/{runtime-DqhT5NCm.js → runtime-DkWCpjKe.js} +1 -1
- package/dist/preview/assets/{runtime-CJVZpawP.js → runtime-mYNyG7UH.js} +1 -1
- package/dist/preview/assets/{schema-meta-xFd44RnL.js → schema-meta-BlTKRs15.js} +1 -1
- package/dist/preview/index.html +2 -2
- package/dist/runtime/components/form/fields/2026-04-24/com.shwfed.form.field.combobox.single/config.d.vue.ts +16 -16
- package/dist/runtime/components/form/fields/2026-04-24/com.shwfed.form.field.combobox.single/config.vue.d.ts +16 -16
- package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.daterange/config.d.vue.ts +4 -4
- package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.daterange/config.vue.d.ts +4 -4
- package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.datetimerange/config.d.vue.ts +6 -6
- package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.datetimerange/config.vue.d.ts +6 -6
- package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.timerange/config.d.vue.ts +2 -2
- package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.timerange/config.vue.d.ts +2 -2
- package/dist/runtime/components/form/fields/2026-05-13/com.shwfed.form.field.combobox.single.remote/config.d.vue.ts +16 -16
- package/dist/runtime/components/form/fields/2026-05-13/com.shwfed.form.field.combobox.single.remote/config.vue.d.ts +16 -16
- package/dist/runtime/components/form/fields/2026-05-13/com.shwfed.form.field.list/config.d.vue.ts +2 -0
- package/dist/runtime/components/form/fields/2026-05-13/com.shwfed.form.field.list/config.vue +32 -1
- package/dist/runtime/components/form/fields/2026-05-13/com.shwfed.form.field.list/config.vue.d.ts +2 -0
- package/dist/runtime/components/form/fields/2026-05-13/com.shwfed.form.field.list/runtime.vue +2 -0
- package/dist/runtime/components/form/fields/2026-05-13/com.shwfed.form.field.list/schema.d.ts +2 -0
- package/dist/runtime/components/form/fields/2026-05-13/com.shwfed.form.field.list/schema.js +4 -0
- package/dist/runtime/components/form/fields/2026-05-17/com.shwfed.form.field.checkbox.group/config.vue +202 -112
- package/dist/runtime/components/form/fields/2026-05-17/com.shwfed.form.field.radio.group/config.vue +202 -112
- package/dist/runtime/components/form/fields/2026-05-23/com.shwfed.form.field.tree.multi/config.d.vue.ts +22 -22
- package/dist/runtime/components/form/fields/2026-05-23/com.shwfed.form.field.tree.multi/config.vue.d.ts +22 -22
- package/dist/runtime/components/form/fields/2026-05-24/com.shwfed.form.field.monthrange/config.d.vue.ts +4 -4
- package/dist/runtime/components/form/fields/2026-05-24/com.shwfed.form.field.monthrange/config.vue.d.ts +4 -4
- package/dist/runtime/components/form/fields/2026-05-25/com.shwfed.form.field.combobox.multi/config.d.vue.ts +16 -16
- package/dist/runtime/components/form/fields/2026-05-25/com.shwfed.form.field.combobox.multi/config.vue.d.ts +16 -16
- package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.multi/config.d.vue.ts +22 -22
- package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.multi/config.vue.d.ts +22 -22
- package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.single/config.d.vue.ts +22 -22
- package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.single/config.vue.d.ts +22 -22
- package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.multi/config.d.vue.ts +22 -22
- package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.multi/config.vue.d.ts +22 -22
- package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.single/config.d.vue.ts +22 -22
- package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.single/config.vue.d.ts +22 -22
- package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.multi/config.d.vue.ts +22 -22
- package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.multi/config.vue.d.ts +22 -22
- package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.single/config.d.vue.ts +22 -22
- package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.single/config.vue.d.ts +22 -22
- package/dist/runtime/components/form/fields/2026-06-14/com.shwfed.form.field.combobox.multi/config.vue +223 -132
- package/dist/runtime/components/form/fields/2026-06-14/com.shwfed.form.field.combobox.single/config.vue +223 -132
- package/dist/runtime/components/form/fields/2026-06-20/com.shwfed.form.field.tabs/config.d.vue.ts +59 -0
- package/dist/runtime/components/form/fields/2026-06-20/com.shwfed.form.field.tabs/config.vue +345 -0
- package/dist/runtime/components/form/fields/2026-06-20/com.shwfed.form.field.tabs/config.vue.d.ts +59 -0
- package/dist/runtime/components/form/fields/2026-06-20/com.shwfed.form.field.tabs/runtime.d.vue.ts +8 -0
- package/dist/runtime/components/form/fields/2026-06-20/com.shwfed.form.field.tabs/runtime.vue +113 -0
- package/dist/runtime/components/form/fields/2026-06-20/com.shwfed.form.field.tabs/runtime.vue.d.ts +8 -0
- package/dist/runtime/components/form/fields/2026-06-20/com.shwfed.form.field.tabs/schema.d.ts +79 -0
- package/dist/runtime/components/form/fields/2026-06-20/com.shwfed.form.field.tabs/schema.js +86 -0
- package/dist/runtime/components/form/unit-config.d.vue.ts +27 -0
- package/dist/runtime/components/form/unit-config.vue +117 -73
- package/dist/runtime/components/form/unit-config.vue.d.ts +27 -0
- package/dist/runtime/components/table/columns/2026-05-24/com.shwfed.table.column.combobox-single.remote.options-remote/config.d.vue.ts +2 -2
- package/dist/runtime/components/table/columns/2026-05-24/com.shwfed.table.column.combobox-single.remote.options-remote/config.vue.d.ts +2 -2
- package/dist/runtime/components/table/columns/2026-05-24/com.shwfed.table.column.combobox-single.remote.options-static/config.d.vue.ts +2 -2
- package/dist/runtime/components/table/columns/2026-05-24/com.shwfed.table.column.combobox-single.remote.options-static/config.vue.d.ts +2 -2
- package/dist/runtime/components/table/columns/2026-05-25/com.shwfed.table.column.combobox-multi.remote.options-remote/config.d.vue.ts +2 -2
- package/dist/runtime/components/table/columns/2026-05-25/com.shwfed.table.column.combobox-multi.remote.options-remote/config.vue.d.ts +2 -2
- package/dist/runtime/components/table/columns/2026-05-25/com.shwfed.table.column.combobox-multi.remote.options-static/config.d.vue.ts +2 -2
- package/dist/runtime/components/table/columns/2026-05-25/com.shwfed.table.column.combobox-multi.remote.options-static/config.vue.d.ts +2 -2
- package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-multi.remote/config.d.vue.ts +2 -2
- package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-multi.remote/config.vue.d.ts +2 -2
- package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-single.remote/config.d.vue.ts +2 -2
- package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-single.remote/config.vue.d.ts +2 -2
- package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-multi/config.d.vue.ts +2 -2
- package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-multi/config.vue.d.ts +2 -2
- package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-single/config.d.vue.ts +2 -2
- package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-single/config.vue.d.ts +2 -2
- package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.combobox-multi/config.d.vue.ts +2 -2
- package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.combobox-multi/config.vue.d.ts +2 -2
- package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.combobox-single/config.d.vue.ts +2 -2
- package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.combobox-single/config.vue.d.ts +2 -2
- package/dist/runtime/components/ui/date-picker/DatePickerInput.d.vue.ts +1 -1
- package/dist/runtime/components/ui/date-picker/DatePickerInput.vue.d.ts +1 -1
- package/dist/runtime/components/ui/date-picker/DatePickerTimeInput.d.vue.ts +1 -1
- package/dist/runtime/components/ui/date-picker/DatePickerTimeInput.vue.d.ts +1 -1
- package/dist/runtime/components/ui/date-range-picker/DateRangePickerInput.d.vue.ts +1 -1
- package/dist/runtime/components/ui/date-range-picker/DateRangePickerInput.vue.d.ts +1 -1
- package/dist/runtime/components/ui/date-range-picker/DateRangePickerTimeInput.d.vue.ts +2 -2
- package/dist/runtime/components/ui/date-range-picker/DateRangePickerTimeInput.vue.d.ts +2 -2
- package/dist/runtime/components/ui/markdown/Markdown.vue +19 -16
- package/dist/runtime/utils/markdown.d.ts +5 -2
- package/dist/runtime/utils/markdown.js +22 -1
- package/package.json +1 -1
- package/dist/preview/assets/index-ADrQrdaQ.js +0 -1
- package/dist/preview/assets/index-Cj7bRG7B.css +0 -1
- package/dist/preview/assets/index-DFmBrVzd.js +0 -763
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { Icon } from "@iconify/vue";
|
|
3
|
+
import { computed, inject, onBeforeUnmount, onMounted, ref, watch } from "vue";
|
|
4
|
+
import { useI18n } from "vue-i18n";
|
|
5
|
+
import { reidItems } from "../../../../../share/clipboard";
|
|
6
|
+
import { getLocalizedText } from "../../../../../share/locale";
|
|
7
|
+
import {
|
|
8
|
+
useTreeDnd
|
|
9
|
+
} from "../../../../../composables/useTreeDnd";
|
|
10
|
+
import { Button } from "../../../../ui/button";
|
|
11
|
+
import { Field, FieldLabel } from "../../../../ui/field";
|
|
12
|
+
import { InputGroup, InputGroupInput } from "../../../../ui/input-group";
|
|
13
|
+
import { Locale as LocaleField } from "../../../../ui/locale";
|
|
14
|
+
import { Markdown } from "../../../../ui/markdown";
|
|
15
|
+
import { Textarea } from "../../../../ui/textarea";
|
|
16
|
+
import { Tooltip, TooltipContent, TooltipTrigger } from "../../../../ui/tooltip";
|
|
17
|
+
import { FORM_FIELD_LAYOUT_KEY } from "../../../field-layout";
|
|
18
|
+
import {
|
|
19
|
+
getStructFieldDescription,
|
|
20
|
+
getStructFieldTitle
|
|
21
|
+
} from "../../../schema";
|
|
22
|
+
import ShwfedFormUnitConfig, {
|
|
23
|
+
} from "../../../unit-config.vue";
|
|
24
|
+
import { schema, TabMeta } from "./schema";
|
|
25
|
+
defineOptions({ name: "ShwfedTabsFieldConfig" });
|
|
26
|
+
const value = defineModel({ type: null, ...{ required: true } });
|
|
27
|
+
const { locale } = useI18n();
|
|
28
|
+
const fieldSchema = schema(() => {
|
|
29
|
+
});
|
|
30
|
+
const fieldTitle = (f) => getStructFieldTitle(fieldSchema, f) ?? f;
|
|
31
|
+
const fieldDescription = (f) => getStructFieldDescription(fieldSchema, f);
|
|
32
|
+
const tabFieldTitle = (f) => getStructFieldTitle(TabMeta, f) ?? f;
|
|
33
|
+
const tabFieldDescription = (f) => getStructFieldDescription(TabMeta, f);
|
|
34
|
+
const layout = inject(FORM_FIELD_LAYOUT_KEY, null);
|
|
35
|
+
onMounted(() => {
|
|
36
|
+
if (layout) layout.fullPane.value = true;
|
|
37
|
+
});
|
|
38
|
+
onBeforeUnmount(() => {
|
|
39
|
+
if (layout) layout.fullPane.value = false;
|
|
40
|
+
});
|
|
41
|
+
const tabs = computed(() => value.value.tabs);
|
|
42
|
+
const activeTabId = ref(tabs.value[0]?.id ?? "");
|
|
43
|
+
function tabIndex(id) {
|
|
44
|
+
return value.value.tabs.findIndex((t) => t.id === id);
|
|
45
|
+
}
|
|
46
|
+
const activeTab = computed(
|
|
47
|
+
() => value.value.tabs.find((t) => t.id === activeTabId.value) ?? null
|
|
48
|
+
);
|
|
49
|
+
function tabLabel(t, index) {
|
|
50
|
+
return getLocalizedText(t.label, locale.value) ?? `\u6807\u7B7E ${index + 1}`;
|
|
51
|
+
}
|
|
52
|
+
watch(tabs, (next) => {
|
|
53
|
+
if (next.length === 0) activeTabId.value = "";
|
|
54
|
+
else if (!next.some((t) => t.id === activeTabId.value)) activeTabId.value = next[0].id;
|
|
55
|
+
}, { flush: "post" });
|
|
56
|
+
const activeTabUnitModel = computed({
|
|
57
|
+
get: () => value.value.tabs.find((t) => t.id === activeTabId.value)?.unit ?? { fields: [], layouts: [{ name: "\u9ED8\u8BA4", layout: { columns: 1, placements: {} } }] },
|
|
58
|
+
set: (next) => {
|
|
59
|
+
const arr = value.value.tabs.map(
|
|
60
|
+
(t) => t.id === activeTabId.value ? { ...t, unit: next } : t
|
|
61
|
+
);
|
|
62
|
+
value.value = { ...value.value, tabs: arr };
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
const EXTRAS = [
|
|
66
|
+
{ id: "field", label: "\u901A\u7528\u914D\u7F6E", icon: "fluent:settings-20-regular" }
|
|
67
|
+
];
|
|
68
|
+
const selection = ref({ kind: "layout" });
|
|
69
|
+
function selectTab(id) {
|
|
70
|
+
activeTabId.value = id;
|
|
71
|
+
selection.value = { kind: "layout" };
|
|
72
|
+
}
|
|
73
|
+
function updateTabLabel(id, v) {
|
|
74
|
+
const arr = value.value.tabs.map(
|
|
75
|
+
(t) => t.id === id ? { ...t, label: v } : t
|
|
76
|
+
);
|
|
77
|
+
value.value = { ...value.value, tabs: arr };
|
|
78
|
+
}
|
|
79
|
+
function updateDisplayName(v) {
|
|
80
|
+
const s = v.trim();
|
|
81
|
+
value.value = { ...value.value, displayName: s.length > 0 ? s : void 0 };
|
|
82
|
+
}
|
|
83
|
+
function updateStyle(v) {
|
|
84
|
+
const next = { ...value.value };
|
|
85
|
+
if (v.trim() === "") delete next.style;
|
|
86
|
+
else next.style = v;
|
|
87
|
+
value.value = next;
|
|
88
|
+
}
|
|
89
|
+
function makeId() {
|
|
90
|
+
if (typeof crypto !== "undefined" && "randomUUID" in crypto) return crypto.randomUUID();
|
|
91
|
+
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
|
|
92
|
+
const r = Math.random() * 16 | 0;
|
|
93
|
+
return (c === "x" ? r : r & 3 | 8).toString(16);
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
function emptyUnit() {
|
|
97
|
+
return {
|
|
98
|
+
fields: [],
|
|
99
|
+
layouts: [{ name: "\u9ED8\u8BA4", layout: { columns: 1, placements: {} } }]
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
function addTab() {
|
|
103
|
+
const id = makeId();
|
|
104
|
+
const index = value.value.tabs.length + 1;
|
|
105
|
+
const next = {
|
|
106
|
+
id,
|
|
107
|
+
label: [{ locale: "zh", message: `\u6807\u7B7E ${index}` }],
|
|
108
|
+
unit: emptyUnit()
|
|
109
|
+
};
|
|
110
|
+
value.value = { ...value.value, tabs: [...value.value.tabs, next] };
|
|
111
|
+
selectTab(id);
|
|
112
|
+
}
|
|
113
|
+
function duplicateTab(id) {
|
|
114
|
+
const i = tabIndex(id);
|
|
115
|
+
if (i < 0) return;
|
|
116
|
+
const src = value.value.tabs[i];
|
|
117
|
+
const dupUnit = reidItems([src.unit])[0];
|
|
118
|
+
const dup = { id: makeId(), label: src.label, unit: dupUnit };
|
|
119
|
+
const arr = [...value.value.tabs];
|
|
120
|
+
arr.splice(i + 1, 0, dup);
|
|
121
|
+
value.value = { ...value.value, tabs: arr };
|
|
122
|
+
selectTab(dup.id);
|
|
123
|
+
}
|
|
124
|
+
function deleteTab(id) {
|
|
125
|
+
if (value.value.tabs.length <= 1) return;
|
|
126
|
+
const i = tabIndex(id);
|
|
127
|
+
if (i < 0) return;
|
|
128
|
+
const arr = value.value.tabs.filter((_, idx) => idx !== i);
|
|
129
|
+
value.value = { ...value.value, tabs: arr };
|
|
130
|
+
if (activeTabId.value === id) {
|
|
131
|
+
selectTab(arr[Math.max(0, i - 1)]?.id ?? "");
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
function moveTab(from, to) {
|
|
135
|
+
if (from === to) return;
|
|
136
|
+
if (from < 0 || to < 0) return;
|
|
137
|
+
if (from >= value.value.tabs.length || to >= value.value.tabs.length) return;
|
|
138
|
+
const next = [...value.value.tabs];
|
|
139
|
+
const [item] = next.splice(from, 1);
|
|
140
|
+
if (!item) return;
|
|
141
|
+
next.splice(to, 0, item);
|
|
142
|
+
value.value = { ...value.value, tabs: next };
|
|
143
|
+
}
|
|
144
|
+
const ROW_KIND = "tabs-field-row";
|
|
145
|
+
function rowId(i) {
|
|
146
|
+
return `tab-${i}`;
|
|
147
|
+
}
|
|
148
|
+
function onRowDrop(e) {
|
|
149
|
+
if (e.source.kind !== ROW_KIND || e.target.kind !== ROW_KIND) return;
|
|
150
|
+
const from = value.value.tabs.findIndex((_, i) => rowId(i) === e.source.id);
|
|
151
|
+
const to = value.value.tabs.findIndex((_, i) => rowId(i) === e.target.id);
|
|
152
|
+
if (from < 0 || to < 0) return;
|
|
153
|
+
if (e.instruction === "reorder-above") moveTab(from, from < to ? to - 1 : to);
|
|
154
|
+
else if (e.instruction === "reorder-below") moveTab(from, from <= to ? to : to + 1);
|
|
155
|
+
}
|
|
156
|
+
const dnd = useTreeDnd({ onRowDrop });
|
|
157
|
+
const pickDragHandle = (el) => el.querySelector(".drag-handle");
|
|
158
|
+
function rowConfig(i) {
|
|
159
|
+
return {
|
|
160
|
+
kind: ROW_KIND,
|
|
161
|
+
canDrop: (src) => src.kind === ROW_KIND,
|
|
162
|
+
blockInstructions: (src) => {
|
|
163
|
+
const blocked = ["make-child", "reparent"];
|
|
164
|
+
if (src.id === rowId(i)) blocked.push("reorder-above", "reorder-below");
|
|
165
|
+
return blocked;
|
|
166
|
+
},
|
|
167
|
+
dragHandle: pickDragHandle
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
</script>
|
|
171
|
+
|
|
172
|
+
<template>
|
|
173
|
+
<ShwfedFormUnitConfig
|
|
174
|
+
v-model="activeTabUnitModel"
|
|
175
|
+
v-model:selection="selection"
|
|
176
|
+
:scope-key="activeTabId"
|
|
177
|
+
:extras="EXTRAS"
|
|
178
|
+
>
|
|
179
|
+
<!-- Tab list — injected as the rail's top half, above the active tab's
|
|
180
|
+
layouts, so the rail reads as two parallel lists (matching the
|
|
181
|
+
block-tabs config). -->
|
|
182
|
+
<template #rail-extra>
|
|
183
|
+
<div class="flex flex-col gap-0.5">
|
|
184
|
+
<div
|
|
185
|
+
v-for="(t, i) in value.tabs"
|
|
186
|
+
:key="t.id"
|
|
187
|
+
:ref="dnd.rowRef(rowId(i), rowConfig(i))"
|
|
188
|
+
class="row group pl-2"
|
|
189
|
+
:class="[
|
|
190
|
+
activeTabId === t.id ? 'bg-[color-mix(in_srgb,var(--primary)_10%,white)] text-(--primary)' : 'text-zinc-700 hover:bg-zinc-50'
|
|
191
|
+
]"
|
|
192
|
+
:data-instruction="dnd.instructionFor(rowId(i)) ?? void 0"
|
|
193
|
+
@click="selectTab(t.id)"
|
|
194
|
+
>
|
|
195
|
+
<Icon
|
|
196
|
+
icon="fluent:re-order-dots-vertical-20-regular"
|
|
197
|
+
class="drag-handle size-4 shrink-0 cursor-grab text-zinc-400"
|
|
198
|
+
/>
|
|
199
|
+
<span class="flex-1 truncate">{{ tabLabel(t, i) }}</span>
|
|
200
|
+
<span
|
|
201
|
+
class="ml-auto flex items-center gap-0.5 opacity-0 transition-opacity group-hover:opacity-100"
|
|
202
|
+
@click.stop
|
|
203
|
+
>
|
|
204
|
+
<Tooltip :delay-duration="180">
|
|
205
|
+
<TooltipTrigger as-child>
|
|
206
|
+
<button
|
|
207
|
+
type="button"
|
|
208
|
+
class="inline-flex size-6 items-center justify-center rounded text-zinc-400 hover:bg-zinc-100 hover:text-zinc-700"
|
|
209
|
+
@click.stop="duplicateTab(t.id)"
|
|
210
|
+
>
|
|
211
|
+
<Icon
|
|
212
|
+
icon="fluent:copy-20-regular"
|
|
213
|
+
class="size-3.5"
|
|
214
|
+
/>
|
|
215
|
+
</button>
|
|
216
|
+
</TooltipTrigger>
|
|
217
|
+
<TooltipContent side="right">
|
|
218
|
+
复制标签页
|
|
219
|
+
</TooltipContent>
|
|
220
|
+
</Tooltip>
|
|
221
|
+
<Tooltip :delay-duration="180">
|
|
222
|
+
<TooltipTrigger as-child>
|
|
223
|
+
<button
|
|
224
|
+
type="button"
|
|
225
|
+
class="inline-flex size-6 items-center justify-center rounded text-zinc-300 hover:bg-red-50 hover:text-red-500 disabled:cursor-not-allowed disabled:opacity-30 disabled:hover:bg-transparent disabled:hover:text-zinc-300"
|
|
226
|
+
:disabled="value.tabs.length <= 1"
|
|
227
|
+
@click.stop="deleteTab(t.id)"
|
|
228
|
+
>
|
|
229
|
+
<Icon
|
|
230
|
+
icon="fluent:delete-20-regular"
|
|
231
|
+
class="size-3.5"
|
|
232
|
+
/>
|
|
233
|
+
</button>
|
|
234
|
+
</TooltipTrigger>
|
|
235
|
+
<TooltipContent side="right">
|
|
236
|
+
{{ value.tabs.length <= 1 ? "\u81F3\u5C11\u9700\u8981\u4E00\u4E2A\u6807\u7B7E\u9875" : "\u5220\u9664\u6807\u7B7E\u9875" }}
|
|
237
|
+
</TooltipContent>
|
|
238
|
+
</Tooltip>
|
|
239
|
+
</span>
|
|
240
|
+
</div>
|
|
241
|
+
</div>
|
|
242
|
+
</template>
|
|
243
|
+
|
|
244
|
+
<!-- 新增标签页 — pinned at the foot of the tab-list half. -->
|
|
245
|
+
<template #rail-extra-foot>
|
|
246
|
+
<Button
|
|
247
|
+
variant="ghost"
|
|
248
|
+
size="sm"
|
|
249
|
+
class="w-full justify-start"
|
|
250
|
+
@click="addTab()"
|
|
251
|
+
>
|
|
252
|
+
<Icon
|
|
253
|
+
icon="fluent:add-20-regular"
|
|
254
|
+
class="size-4"
|
|
255
|
+
/>
|
|
256
|
+
<span>新增标签页</span>
|
|
257
|
+
</Button>
|
|
258
|
+
</template>
|
|
259
|
+
|
|
260
|
+
<!-- Active tab's label — above the layout canvas, mirroring the block's
|
|
261
|
+
pane header (标签名 → 名称 → canvas). -->
|
|
262
|
+
<template #pane-header>
|
|
263
|
+
<Field
|
|
264
|
+
v-if="activeTab"
|
|
265
|
+
orientation="vertical"
|
|
266
|
+
>
|
|
267
|
+
<FieldLabel class="text-xs text-zinc-500">
|
|
268
|
+
<template
|
|
269
|
+
v-if="tabFieldDescription('label')"
|
|
270
|
+
#tooltip
|
|
271
|
+
>
|
|
272
|
+
<Markdown
|
|
273
|
+
:source="tabFieldDescription('label')"
|
|
274
|
+
block
|
|
275
|
+
class="prose prose-sm prose-zinc"
|
|
276
|
+
/>
|
|
277
|
+
</template>
|
|
278
|
+
{{ tabFieldTitle("label") }}
|
|
279
|
+
</FieldLabel>
|
|
280
|
+
<LocaleField
|
|
281
|
+
:model-value="activeTab.label"
|
|
282
|
+
:translate-hint="tabFieldTitle('label')"
|
|
283
|
+
@update:model-value="(v) => updateTabLabel(activeTab.id, v)"
|
|
284
|
+
/>
|
|
285
|
+
</Field>
|
|
286
|
+
</template>
|
|
287
|
+
|
|
288
|
+
<!-- 通用配置: field-level props (editor-only name + container style). -->
|
|
289
|
+
<template #extras-pane="{ id }">
|
|
290
|
+
<div
|
|
291
|
+
v-if="id === 'field'"
|
|
292
|
+
class="flex flex-col gap-2"
|
|
293
|
+
>
|
|
294
|
+
<Field orientation="vertical">
|
|
295
|
+
<FieldLabel class="text-xs text-zinc-500">
|
|
296
|
+
<template
|
|
297
|
+
v-if="fieldDescription('displayName')"
|
|
298
|
+
#tooltip
|
|
299
|
+
>
|
|
300
|
+
<Markdown
|
|
301
|
+
:source="fieldDescription('displayName')"
|
|
302
|
+
block
|
|
303
|
+
class="prose prose-sm prose-zinc"
|
|
304
|
+
/>
|
|
305
|
+
</template>
|
|
306
|
+
{{ fieldTitle("displayName") }}
|
|
307
|
+
</FieldLabel>
|
|
308
|
+
<InputGroup>
|
|
309
|
+
<InputGroupInput
|
|
310
|
+
:model-value="value.displayName ?? ''"
|
|
311
|
+
placeholder="例:基本信息"
|
|
312
|
+
@update:model-value="(v) => updateDisplayName(String(v ?? ''))"
|
|
313
|
+
/>
|
|
314
|
+
</InputGroup>
|
|
315
|
+
</Field>
|
|
316
|
+
|
|
317
|
+
<Field orientation="vertical">
|
|
318
|
+
<FieldLabel class="text-xs text-zinc-500">
|
|
319
|
+
<template
|
|
320
|
+
v-if="fieldDescription('style')"
|
|
321
|
+
#tooltip
|
|
322
|
+
>
|
|
323
|
+
<Markdown
|
|
324
|
+
:source="fieldDescription('style')"
|
|
325
|
+
block
|
|
326
|
+
class="prose prose-sm prose-zinc"
|
|
327
|
+
/>
|
|
328
|
+
</template>
|
|
329
|
+
{{ fieldTitle("style") }}
|
|
330
|
+
</FieldLabel>
|
|
331
|
+
<Textarea
|
|
332
|
+
:model-value="value.style ?? ''"
|
|
333
|
+
placeholder="CSS 样式字符串"
|
|
334
|
+
class="min-h-20 font-mono text-xs"
|
|
335
|
+
@update:model-value="(v) => updateStyle(String(v))"
|
|
336
|
+
/>
|
|
337
|
+
</Field>
|
|
338
|
+
</div>
|
|
339
|
+
</template>
|
|
340
|
+
</ShwfedFormUnitConfig>
|
|
341
|
+
</template>
|
|
342
|
+
|
|
343
|
+
<style scoped>
|
|
344
|
+
.row{align-items:center;border-radius:.25rem;cursor:pointer;display:flex;font-size:.875rem;gap:.375rem;padding-block:.375rem;padding-right:.5rem;position:relative;transition:background-color .1s ease;-webkit-user-select:none;-moz-user-select:none;user-select:none}[data-instruction=reorder-above]:before,[data-instruction=reorder-below]:after{background:var(--primary,#2563eb);content:"";height:2px;left:.5rem;pointer-events:none;position:absolute;right:.5rem;z-index:1}[data-instruction=reorder-above]:before{top:-1px}[data-instruction=reorder-below]:after{bottom:-1px}
|
|
345
|
+
</style>
|
package/dist/runtime/components/form/fields/2026-06-20/com.shwfed.form.field.tabs/config.vue.d.ts
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { type Value } from './schema.js';
|
|
2
|
+
type __VLS_ModelProps = {
|
|
3
|
+
modelValue: Value;
|
|
4
|
+
};
|
|
5
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
6
|
+
"update:modelValue": (value: {
|
|
7
|
+
readonly type: "com.shwfed.form.field.tabs";
|
|
8
|
+
readonly style?: string | undefined;
|
|
9
|
+
readonly id: string;
|
|
10
|
+
readonly displayName?: string | undefined;
|
|
11
|
+
readonly compatibilityDate: "2026-06-20";
|
|
12
|
+
readonly tabs: readonly {
|
|
13
|
+
readonly label: readonly [{
|
|
14
|
+
readonly locale: "zh";
|
|
15
|
+
readonly message: string;
|
|
16
|
+
}, ...{
|
|
17
|
+
readonly locale: "en" | "ja" | "ko";
|
|
18
|
+
readonly message: string;
|
|
19
|
+
}[]];
|
|
20
|
+
readonly id: string;
|
|
21
|
+
readonly unit: Readonly<{
|
|
22
|
+
fields: ReadonlyArray<import("../../../schema.js").FieldValue>;
|
|
23
|
+
layouts: readonly Readonly<{
|
|
24
|
+
name: string;
|
|
25
|
+
media?: string;
|
|
26
|
+
layout: import("../../../schema.js").LayoutValue;
|
|
27
|
+
}>[];
|
|
28
|
+
}>;
|
|
29
|
+
}[];
|
|
30
|
+
}) => any;
|
|
31
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_ModelProps> & Readonly<{
|
|
32
|
+
"onUpdate:modelValue"?: ((value: {
|
|
33
|
+
readonly type: "com.shwfed.form.field.tabs";
|
|
34
|
+
readonly style?: string | undefined;
|
|
35
|
+
readonly id: string;
|
|
36
|
+
readonly displayName?: string | undefined;
|
|
37
|
+
readonly compatibilityDate: "2026-06-20";
|
|
38
|
+
readonly tabs: readonly {
|
|
39
|
+
readonly label: readonly [{
|
|
40
|
+
readonly locale: "zh";
|
|
41
|
+
readonly message: string;
|
|
42
|
+
}, ...{
|
|
43
|
+
readonly locale: "en" | "ja" | "ko";
|
|
44
|
+
readonly message: string;
|
|
45
|
+
}[]];
|
|
46
|
+
readonly id: string;
|
|
47
|
+
readonly unit: Readonly<{
|
|
48
|
+
fields: ReadonlyArray<import("../../../schema.js").FieldValue>;
|
|
49
|
+
layouts: readonly Readonly<{
|
|
50
|
+
name: string;
|
|
51
|
+
media?: string;
|
|
52
|
+
layout: import("../../../schema.js").LayoutValue;
|
|
53
|
+
}>[];
|
|
54
|
+
}>;
|
|
55
|
+
}[];
|
|
56
|
+
}) => any) | undefined;
|
|
57
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
58
|
+
declare const _default: typeof __VLS_export;
|
|
59
|
+
export default _default;
|
package/dist/runtime/components/form/fields/2026-06-20/com.shwfed.form.field.tabs/runtime.d.vue.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Value } from './schema.js';
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
fieldId: string;
|
|
4
|
+
config: Value;
|
|
5
|
+
};
|
|
6
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
7
|
+
declare const _default: typeof __VLS_export;
|
|
8
|
+
export default _default;
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { Effect } from "effect";
|
|
3
|
+
import { computed } from "vue";
|
|
4
|
+
import { useI18n } from "vue-i18n";
|
|
5
|
+
import { cel as _rawCel } from "../../../../../utils/cel";
|
|
6
|
+
import { celBindings, injectCELContext } from "../../../../../utils/cel-context";
|
|
7
|
+
import { getLocalizedText } from "../../../../../share/locale";
|
|
8
|
+
import { useActiveTabId } from "../../../../../share/use-active-tab-id";
|
|
9
|
+
import { Tabs, TabsContent, TabsList, TabsTrigger } from "../../../../ui/tabs";
|
|
10
|
+
import FormUnitRenderer from "../../../FormUnitRenderer.vue";
|
|
11
|
+
import { useValidationProvider } from "../../../utils/validation";
|
|
12
|
+
defineOptions({ name: "ShwfedTabsFieldRuntime" });
|
|
13
|
+
const props = defineProps({
|
|
14
|
+
fieldId: { type: String, required: true },
|
|
15
|
+
config: { type: null, required: true }
|
|
16
|
+
});
|
|
17
|
+
const { locale } = useI18n();
|
|
18
|
+
const inherited = injectCELContext();
|
|
19
|
+
const $cel = (expression, context) => _rawCel(expression, { ...celBindings(inherited), ...context });
|
|
20
|
+
function evaluateMedia(expression) {
|
|
21
|
+
return Effect.runSync($cel(expression));
|
|
22
|
+
}
|
|
23
|
+
function isHidden(field) {
|
|
24
|
+
const hidden = field.hidden;
|
|
25
|
+
if (!hidden) return false;
|
|
26
|
+
try {
|
|
27
|
+
return Effect.runSync($cel(hidden));
|
|
28
|
+
} catch (err) {
|
|
29
|
+
console.error(`[shwfed-form] tabs: failed to evaluate hidden for ${field.id}:`, err);
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
const tabIds = computed(() => props.config.tabs.map((t) => t.id));
|
|
34
|
+
const active = useActiveTabId(props.fieldId, tabIds);
|
|
35
|
+
function tabLabel(tab, index) {
|
|
36
|
+
return getLocalizedText(tab.label, locale.value) ?? `\u6807\u7B7E ${index + 1}`;
|
|
37
|
+
}
|
|
38
|
+
const validation = useValidationProvider();
|
|
39
|
+
function collectFieldIds(fields) {
|
|
40
|
+
const ids = [];
|
|
41
|
+
for (const field of fields) {
|
|
42
|
+
ids.push(field.id);
|
|
43
|
+
const unit = field.unit;
|
|
44
|
+
if (unit?.fields) ids.push(...collectFieldIds(unit.fields));
|
|
45
|
+
const nestedTabs = field.tabs;
|
|
46
|
+
if (nestedTabs) {
|
|
47
|
+
for (const t of nestedTabs) {
|
|
48
|
+
if (t.unit?.fields) ids.push(...collectFieldIds(t.unit.fields));
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return ids;
|
|
53
|
+
}
|
|
54
|
+
function tabCounts(tab) {
|
|
55
|
+
if (!validation?.revealed.value) return { errors: 0, warnings: 0 };
|
|
56
|
+
const results = validation.resultsFor(collectFieldIds(tab.unit.fields));
|
|
57
|
+
return {
|
|
58
|
+
errors: results.filter((r) => r.severity === "error").length,
|
|
59
|
+
warnings: results.filter((r) => r.severity === "warning").length
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
</script>
|
|
63
|
+
|
|
64
|
+
<template>
|
|
65
|
+
<Tabs
|
|
66
|
+
:model-value="active"
|
|
67
|
+
:style="config.style"
|
|
68
|
+
@update:model-value="(v) => {
|
|
69
|
+
if (typeof v === 'string') active = v;
|
|
70
|
+
}"
|
|
71
|
+
>
|
|
72
|
+
<TabsList>
|
|
73
|
+
<TabsTrigger
|
|
74
|
+
v-for="(t, i) in config.tabs"
|
|
75
|
+
:key="t.id"
|
|
76
|
+
:value="t.id"
|
|
77
|
+
class="max-[800px]:flex-1 max-[800px]:justify-center"
|
|
78
|
+
>
|
|
79
|
+
<span>{{ tabLabel(t, i) }}</span>
|
|
80
|
+
<span
|
|
81
|
+
v-if="tabCounts(t).errors > 0"
|
|
82
|
+
data-slot="tabs-error-count"
|
|
83
|
+
class="ml-1 inline-flex min-w-4 items-center justify-center rounded-full bg-red-100 px-1 text-[10px] font-medium text-red-600"
|
|
84
|
+
>{{ tabCounts(t).errors }}</span>
|
|
85
|
+
<span
|
|
86
|
+
v-else-if="tabCounts(t).warnings > 0"
|
|
87
|
+
data-slot="tabs-warning-count"
|
|
88
|
+
class="ml-1 inline-flex min-w-4 items-center justify-center rounded-full bg-amber-100 px-1 text-[10px] font-medium text-amber-600"
|
|
89
|
+
>{{ tabCounts(t).warnings }}</span>
|
|
90
|
+
</TabsTrigger>
|
|
91
|
+
</TabsList>
|
|
92
|
+
|
|
93
|
+
<!-- `force-mount` keeps every tab's fields mounted; reka-ui forces
|
|
94
|
+
`present` true under force-mount and therefore never sets `hidden`, so
|
|
95
|
+
we hide the inactive panes ourselves with `data-[state=inactive]:hidden`
|
|
96
|
+
(display:none, NOT unmounted). Load-bearing: derived / formula fields
|
|
97
|
+
keep computing, commit-bus drafts stay live, and form state for
|
|
98
|
+
inactive tabs is never dropped on switch. -->
|
|
99
|
+
<TabsContent
|
|
100
|
+
v-for="t in config.tabs"
|
|
101
|
+
:key="t.id"
|
|
102
|
+
:value="t.id"
|
|
103
|
+
force-mount
|
|
104
|
+
class="outline-none data-[state=inactive]:hidden"
|
|
105
|
+
>
|
|
106
|
+
<FormUnitRenderer
|
|
107
|
+
:unit="t.unit"
|
|
108
|
+
:evaluate-media="evaluateMedia"
|
|
109
|
+
:is-hidden="isHidden"
|
|
110
|
+
/>
|
|
111
|
+
</TabsContent>
|
|
112
|
+
</Tabs>
|
|
113
|
+
</template>
|
package/dist/runtime/components/form/fields/2026-06-20/com.shwfed.form.field.tabs/runtime.vue.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Value } from './schema.js';
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
fieldId: string;
|
|
4
|
+
config: Value;
|
|
5
|
+
};
|
|
6
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
7
|
+
declare const _default: typeof __VLS_export;
|
|
8
|
+
export default _default;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { Schema } from 'effect';
|
|
2
|
+
import type { Environment } from '../../../../../vendor/cel-js/lib/index.js';
|
|
3
|
+
export declare const type: "com.shwfed.form.field.tabs";
|
|
4
|
+
export declare const compatibilityDate: "2026-06-20";
|
|
5
|
+
export declare const metadata: {
|
|
6
|
+
readonly name: "标签页";
|
|
7
|
+
readonly icon: "fluent:tabs-20-regular";
|
|
8
|
+
readonly w: {
|
|
9
|
+
readonly initial: 12;
|
|
10
|
+
readonly min: 4;
|
|
11
|
+
readonly max: number;
|
|
12
|
+
};
|
|
13
|
+
readonly h: {
|
|
14
|
+
readonly initial: 6;
|
|
15
|
+
readonly min: 2;
|
|
16
|
+
readonly max: number;
|
|
17
|
+
readonly grow: true;
|
|
18
|
+
};
|
|
19
|
+
readonly inlineConfig: false;
|
|
20
|
+
};
|
|
21
|
+
export declare const TabMeta: Schema.Struct<{
|
|
22
|
+
label: Schema.TupleType<readonly [Schema.Struct<{
|
|
23
|
+
locale: Schema.Literal<["zh"]>;
|
|
24
|
+
message: Schema.SchemaClass<string, string, never>;
|
|
25
|
+
}>], [Schema.Struct<{
|
|
26
|
+
locale: Schema.Literal<["ja", "en", "ko"]>;
|
|
27
|
+
message: Schema.SchemaClass<string, string, never>;
|
|
28
|
+
}>]>;
|
|
29
|
+
}>;
|
|
30
|
+
/**
|
|
31
|
+
* A tabbed grouping. Pure view — children of each tab stay flat in the form
|
|
32
|
+
* state (the tabs introduce no subtree), and the active-tab selection lives
|
|
33
|
+
* only in the runtime component / sessionStorage (not persisted to the value).
|
|
34
|
+
*
|
|
35
|
+
* Deliberately does **not** include `commonFieldFields` — `hidden` /
|
|
36
|
+
* `required` / `binding` are field-flavored concepts that don't fit a
|
|
37
|
+
* structural grouping. We carry only an `id` (so the parent layout can
|
|
38
|
+
* reference the field), an editor-only `displayName`, an optional container
|
|
39
|
+
* `style`, and the `tabs` array — each tab a label + a nested `unit`.
|
|
40
|
+
*/
|
|
41
|
+
export declare function schema(configure: (env: Environment) => void): Schema.Struct<{
|
|
42
|
+
type: Schema.Literal<["com.shwfed.form.field.tabs"]>;
|
|
43
|
+
compatibilityDate: Schema.Literal<["2026-06-20"]>;
|
|
44
|
+
id: Schema.refine<string, typeof Schema.String>;
|
|
45
|
+
displayName: Schema.optional<Schema.SchemaClass<string, string, never>>;
|
|
46
|
+
style: Schema.optional<Schema.SchemaClass<string, string, never>>;
|
|
47
|
+
tabs: Schema.refine<readonly {
|
|
48
|
+
readonly label: readonly [{
|
|
49
|
+
readonly locale: "zh";
|
|
50
|
+
readonly message: string;
|
|
51
|
+
}, ...{
|
|
52
|
+
readonly locale: "en" | "ja" | "ko";
|
|
53
|
+
readonly message: string;
|
|
54
|
+
}[]];
|
|
55
|
+
readonly id: string;
|
|
56
|
+
readonly unit: Readonly<{
|
|
57
|
+
fields: ReadonlyArray<import("../../../schema.js").FieldValue>;
|
|
58
|
+
layouts: ReadonlyArray<import("../../../schema.js").LayoutSetValue>;
|
|
59
|
+
}>;
|
|
60
|
+
}[], Schema.filter<Schema.Array$<Schema.Struct<{
|
|
61
|
+
unit: Schema.suspend<Readonly<{
|
|
62
|
+
fields: ReadonlyArray<import("../../../schema.js").FieldValue>;
|
|
63
|
+
layouts: ReadonlyArray<import("../../../schema.js").LayoutSetValue>;
|
|
64
|
+
}>, Readonly<{
|
|
65
|
+
fields: ReadonlyArray<import("../../../schema.js").FieldValue>;
|
|
66
|
+
layouts: ReadonlyArray<import("../../../schema.js").LayoutSetValue>;
|
|
67
|
+
}>, never>;
|
|
68
|
+
label: Schema.TupleType<readonly [Schema.Struct<{
|
|
69
|
+
locale: Schema.Literal<["zh"]>;
|
|
70
|
+
message: Schema.SchemaClass<string, string, never>;
|
|
71
|
+
}>], [Schema.Struct<{
|
|
72
|
+
locale: Schema.Literal<["ja", "en", "ko"]>;
|
|
73
|
+
message: Schema.SchemaClass<string, string, never>;
|
|
74
|
+
}>]>;
|
|
75
|
+
id: Schema.refine<string, typeof Schema.String>;
|
|
76
|
+
}>>>>;
|
|
77
|
+
}>;
|
|
78
|
+
export type Value = Schema.Schema.Type<ReturnType<typeof schema>>;
|
|
79
|
+
export declare function defaults(): Partial<Value>;
|