@shwfed/config 3.0.4 → 3.0.6

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.
Files changed (61) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/runtime/components/actions/buttons/2026-04-21/com.shwfed.actions.button.navigation/runtime.vue +4 -10
  3. package/dist/runtime/components/actions/buttons/2026-05-21/com.shwfed.actions.button.http.download/schema.d.ts +1 -1
  4. package/dist/runtime/components/actions/buttons/2026-05-21/com.shwfed.actions.button.http.download/schema.js +2 -2
  5. package/dist/runtime/components/actions/buttons/2026-07-13/com.shwfed.actions.button.state.write/runtime.vue +1 -1
  6. package/dist/runtime/components/actions/buttons/2026-07-13/com.shwfed.actions.button.state.write/schema.d.ts +4 -2
  7. package/dist/runtime/components/actions/buttons/2026-07-13/com.shwfed.actions.button.state.write/schema.js +1 -1
  8. package/dist/runtime/components/actions/utils/steps.d.ts +1 -1
  9. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.table/config.d.vue.ts +6 -6
  10. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.table/config.vue.d.ts +6 -6
  11. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.table/runtime.d.vue.ts +6 -6
  12. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.table/runtime.vue.d.ts +6 -6
  13. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.table/schema.d.ts +3 -3
  14. package/dist/runtime/components/config/index.vue +25 -0
  15. package/dist/runtime/components/config/prune-dialog.d.vue.ts +14 -0
  16. package/dist/runtime/components/config/prune-dialog.vue +72 -0
  17. package/dist/runtime/components/config/prune-dialog.vue.d.ts +14 -0
  18. package/dist/runtime/components/config/schema.js +2 -2
  19. package/dist/runtime/components/config/use-editor.d.ts +9 -0
  20. package/dist/runtime/components/config/use-editor.js +37 -9
  21. package/dist/runtime/components/config/utils/linkage.d.ts +8 -0
  22. package/dist/runtime/components/config/utils/linkage.js +7 -2
  23. package/dist/runtime/components/config/utils/prune.d.ts +68 -0
  24. package/dist/runtime/components/config/utils/prune.js +92 -0
  25. package/dist/runtime/components/form/fields/2026-04-22/com.shwfed.form.field.text/config.d.vue.ts +22 -22
  26. package/dist/runtime/components/form/fields/2026-04-22/com.shwfed.form.field.text/config.vue.d.ts +22 -22
  27. package/dist/runtime/components/form/fields/2026-04-28/com.shwfed.form.field.number/config.d.vue.ts +22 -22
  28. package/dist/runtime/components/form/fields/2026-04-28/com.shwfed.form.field.number/config.vue.d.ts +22 -22
  29. package/dist/runtime/components/form/fields/2026-07-13/com.shwfed.form.field.dynamic/config.d.vue.ts +31 -0
  30. package/dist/runtime/components/form/fields/2026-07-13/com.shwfed.form.field.dynamic/config.vue +191 -0
  31. package/dist/runtime/components/form/fields/2026-07-13/com.shwfed.form.field.dynamic/config.vue.d.ts +31 -0
  32. package/dist/runtime/components/form/fields/2026-07-13/com.shwfed.form.field.dynamic/expand.d.ts +49 -0
  33. package/dist/runtime/components/form/fields/2026-07-13/com.shwfed.form.field.dynamic/expand.js +87 -0
  34. package/dist/runtime/components/form/fields/2026-07-13/com.shwfed.form.field.dynamic/runtime.d.vue.ts +8 -0
  35. package/dist/runtime/components/form/fields/2026-07-13/com.shwfed.form.field.dynamic/runtime.vue +72 -0
  36. package/dist/runtime/components/form/fields/2026-07-13/com.shwfed.form.field.dynamic/runtime.vue.d.ts +8 -0
  37. package/dist/runtime/components/form/fields/2026-07-13/com.shwfed.form.field.dynamic/schema.d.ts +59 -0
  38. package/dist/runtime/components/form/fields/2026-07-13/com.shwfed.form.field.dynamic/schema.js +139 -0
  39. package/dist/runtime/components/form/utils/form-vars.d.ts +5 -15
  40. package/dist/runtime/components/form/utils/form-vars.js +12 -6
  41. package/dist/runtime/components/operations/2026-06-11/com.shwfed.operation.http.request.json/schema.js +2 -2
  42. package/dist/runtime/components/operations/2026-06-15/com.shwfed.operation.http.download/schema.js +2 -2
  43. package/dist/runtime/components/operations/2026-06-15/com.shwfed.operation.navigation/runtime.js +5 -11
  44. package/dist/runtime/components/operations/2026-06-15/com.shwfed.operation.navigation/schema.js +1 -1
  45. package/dist/runtime/components/operations/utils/resolve.d.ts +1 -1
  46. package/dist/runtime/components/operations/utils/step-vars.d.ts +4 -2
  47. package/dist/runtime/components/table/columns/2026-04-14/com.shwfed.table.column.select/runtime.vue +1 -21
  48. package/dist/runtime/components/table/columns/2026-04-14/com.shwfed.table.column.select/schema.d.ts +2 -0
  49. package/dist/runtime/components/table/columns/2026-04-14/com.shwfed.table.column.select/schema.js +16 -1
  50. package/dist/runtime/components/table/index.vue +15 -0
  51. package/dist/runtime/components/table/schema.d.ts +6 -6
  52. package/dist/runtime/components/table/utils/resolve.d.ts +26 -0
  53. package/dist/runtime/components/table/utils/resolve.js +2 -1
  54. package/dist/runtime/components/ui/expression-editor/picker-entries.js +1 -1
  55. package/dist/runtime/components/ui/expression-editor/step-chip-extension.js +1 -1
  56. package/dist/runtime/components/ui/expression-editor/step-refs.js +1 -1
  57. package/dist/runtime/share/event-bus.js +2 -2
  58. package/dist/runtime/share/navigation.d.ts +1 -0
  59. package/dist/runtime/share/navigation.js +4 -0
  60. package/dist/runtime/utils/cel-context.d.ts +2 -2
  61. package/package.json +1 -1
@@ -0,0 +1,68 @@
1
+ import { type DanglingLinkage } from './linkage.js';
2
+ /** Which pool an item came out of — drives the noun in user-facing copy. */
3
+ export type PruneKind = 'block' | 'field';
4
+ export declare function pruneKindNoun(kind: PruneKind): string;
5
+ export type UnplacedItem = Readonly<{
6
+ kind: PruneKind;
7
+ id: string;
8
+ /**
9
+ * Property path from the ORIGINAL config root to the removed item
10
+ * (`['slot','blocks',2]`). Fed to `describePath` against that same root.
11
+ */
12
+ path: ReadonlyArray<PropertyKey>;
13
+ /**
14
+ * Every uuid defined anywhere in this item's subtree — the item's own id plus
15
+ * its trigger rows, nested blocks, nested fields, … Dropping the item
16
+ * un-defines all of them at once, so this is the set a surviving reference
17
+ * must not point into.
18
+ */
19
+ ids: ReadonlySet<string>;
20
+ }>;
21
+ /** A pruned item's label, pre-rendered for the confirmation dialog. */
22
+ export type PruneSummary = Readonly<{
23
+ kind: PruneKind;
24
+ /** Breadcrumb to the item in the pre-prune config (`标签页 › 表格`). */
25
+ label: string;
26
+ }>;
27
+ export type PruneConflict = Readonly<{
28
+ /** The surviving reference left pointing at nothing. */
29
+ ref: DanglingLinkage;
30
+ /** The item whose removal stranded it. */
31
+ owner: UnplacedItem;
32
+ }>;
33
+ /**
34
+ * Drop every item that no layout in its own pool places, at every depth.
35
+ * Returns the rewritten config plus the removals, outermost-first.
36
+ */
37
+ export declare function pruneUnplaced<T>(config: T): {
38
+ config: T;
39
+ removed: UnplacedItem[];
40
+ };
41
+ /**
42
+ * References held by SURVIVORS that point into a removed subtree. Non-empty
43
+ * means the prune would strand a linkage, and the save must be refused rather
44
+ * than quietly persisting a config whose trigger targets nothing.
45
+ *
46
+ * Runs the existing dangling-linkage walker over the PRUNED tree and keeps only
47
+ * the danglers the prune itself caused — a linkage that was already dangling
48
+ * before the prune is not our problem and stays with `findDanglingLinkages`.
49
+ */
50
+ export declare function findPruneConflicts(pruned: unknown, removed: ReadonlyArray<UnplacedItem>): PruneConflict[];
51
+ /**
52
+ * Pre-render each removal as a breadcrumb for the confirmation dialog.
53
+ * `root` must be the pre-prune config the paths index into.
54
+ */
55
+ export declare function summarizePrune(removed: ReadonlyArray<UnplacedItem>, root: unknown, blockLabelAt: (index: number) => string | undefined): PruneSummary[];
56
+ /**
57
+ * Save-footer message for a non-empty conflict list. Names both ends — the item
58
+ * about to be dropped and the surviving reference that still needs it — because
59
+ * the raw dangling message ("引用了已失效的资源") would point at the reference
60
+ * and leave the designer hunting for a block that looks perfectly fine sitting
61
+ * in the unplaced tray.
62
+ */
63
+ export declare function formatPruneConflicts(conflicts: ReadonlyArray<PruneConflict>, ctx: {
64
+ prunedRoot: unknown;
65
+ originalRoot: unknown;
66
+ prunedBlockLabelAt: (index: number) => string | undefined;
67
+ originalBlockLabelAt: (index: number) => string | undefined;
68
+ }): string;
@@ -0,0 +1,92 @@
1
+ import { definedIds, findDanglingLinkages, LINKAGE_KIND_LABEL } from "./linkage.js";
2
+ import { describePath } from "./validation-error.js";
3
+ const KIND_NOUN = {
4
+ block: "\u5757",
5
+ field: "\u5B57\u6BB5"
6
+ };
7
+ export function pruneKindNoun(kind) {
8
+ return KIND_NOUN[kind];
9
+ }
10
+ function isObject(v) {
11
+ return v !== null && typeof v === "object" && !Array.isArray(v);
12
+ }
13
+ const POOLS = [
14
+ { key: "blocks", kind: "block" },
15
+ { key: "fields", kind: "field" }
16
+ ];
17
+ function poolOf(node) {
18
+ if (!Array.isArray(node.layouts)) return void 0;
19
+ return POOLS.find((p) => Array.isArray(node[p.key]));
20
+ }
21
+ function placedIds(layouts) {
22
+ const out = /* @__PURE__ */ new Set();
23
+ for (const set of layouts) {
24
+ if (!isObject(set) || !isObject(set.layout)) continue;
25
+ const placements = set.layout.placements;
26
+ if (isObject(placements)) {
27
+ for (const id of Object.keys(placements)) out.add(id);
28
+ }
29
+ }
30
+ return out;
31
+ }
32
+ function walk(node, path, removed) {
33
+ if (Array.isArray(node)) return node.map((v, i) => walk(v, [...path, i], removed));
34
+ if (!isObject(node)) return node;
35
+ const pool = poolOf(node);
36
+ const out = {};
37
+ for (const [key, value] of Object.entries(node)) {
38
+ if (pool && key === pool.key) {
39
+ const placed = placedIds(node.layouts);
40
+ const kept = [];
41
+ for (const [i, item] of value.entries()) {
42
+ const id = isObject(item) && typeof item.id === "string" ? item.id : void 0;
43
+ if (id !== void 0 && !placed.has(id)) {
44
+ removed.push({ kind: pool.kind, id, path: [...path, key, i], ids: definedIds(item) });
45
+ continue;
46
+ }
47
+ kept.push(walk(item, [...path, key, i], removed));
48
+ }
49
+ out[key] = kept;
50
+ continue;
51
+ }
52
+ out[key] = walk(value, [...path, key], removed);
53
+ }
54
+ return out;
55
+ }
56
+ export function pruneUnplaced(config) {
57
+ const removed = [];
58
+ const next = walk(config, [], removed);
59
+ return { config: next, removed };
60
+ }
61
+ export function findPruneConflicts(pruned, removed) {
62
+ if (removed.length === 0) return [];
63
+ const owner = /* @__PURE__ */ new Map();
64
+ for (const item of removed) {
65
+ for (const id of item.ids) {
66
+ if (!owner.has(id)) owner.set(id, item);
67
+ }
68
+ }
69
+ const out = [];
70
+ for (const ref of findDanglingLinkages(pruned)) {
71
+ const o = owner.get(ref.id);
72
+ if (o) out.push({ ref, owner: o });
73
+ }
74
+ return out;
75
+ }
76
+ export function summarizePrune(removed, root, blockLabelAt) {
77
+ return removed.map((item) => ({
78
+ kind: item.kind,
79
+ label: describePath(item.path, root, blockLabelAt).join(" \u203A ") || pruneKindNoun(item.kind)
80
+ }));
81
+ }
82
+ export function formatPruneConflicts(conflicts, ctx) {
83
+ const first = conflicts[0];
84
+ if (!first) return "";
85
+ const ownerSegs = describePath(first.owner.path, ctx.originalRoot, ctx.originalBlockLabelAt);
86
+ const owner = ownerSegs.length > 0 ? ownerSegs.join(" \u203A ") : pruneKindNoun(first.owner.kind);
87
+ const refSegs = describePath(first.ref.path, ctx.prunedRoot, ctx.prunedBlockLabelAt);
88
+ const kind = LINKAGE_KIND_LABEL[first.ref.kind];
89
+ const where = refSegs.length > 0 ? `\u300C${refSegs.join(" \u203A ")}\u300D\u7684${kind}` : kind;
90
+ const suffix = conflicts.length > 1 ? `\uFF08\u8FD8\u6709 ${conflicts.length - 1} \u4E2A\uFF09` : "";
91
+ return `${pruneKindNoun(first.owner.kind)}\u300C${owner}\u300D\u672A\u653E\u5165\u4EFB\u4F55\u5E03\u5C40\uFF0C\u4FDD\u5B58\u65F6\u4F1A\u88AB\u6E05\u7406\uFF0C\u4F46${where}\u4ECD\u5728\u5F15\u7528\u5B83\u3002\u8BF7\u5148\u5C06\u5B83\u653E\u5165\u5E03\u5C40\uFF0C\u6216\u79FB\u9664\u8BE5\u5F15\u7528${suffix}`;
92
+ }
@@ -39,6 +39,17 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
39
39
  readonly mode: "formula" | "prefill";
40
40
  readonly expression: string;
41
41
  } | undefined;
42
+ readonly validations?: readonly {
43
+ readonly message: readonly [{
44
+ readonly locale: "zh";
45
+ readonly message: string;
46
+ }, ...{
47
+ readonly locale: "en" | "ja" | "ko";
48
+ readonly message: string;
49
+ }[]];
50
+ readonly warning?: boolean | undefined;
51
+ readonly when: string;
52
+ }[] | undefined;
42
53
  readonly addon?: {
43
54
  readonly size: "default" | "sm" | "xs";
44
55
  readonly style?: string | undefined;
@@ -106,17 +117,6 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
106
117
  readonly variant?: "default" | "link" | "destructive" | "primary" | "ghost" | undefined;
107
118
  }[];
108
119
  } | undefined;
109
- readonly validations?: readonly {
110
- readonly message: readonly [{
111
- readonly locale: "zh";
112
- readonly message: string;
113
- }, ...{
114
- readonly locale: "en" | "ja" | "ko";
115
- readonly message: string;
116
- }[]];
117
- readonly warning?: boolean | undefined;
118
- readonly when: string;
119
- }[] | undefined;
120
120
  }) => any;
121
121
  }, string, import("vue").PublicProps, Readonly<__VLS_ModelProps> & Readonly<{
122
122
  "onUpdate:modelValue"?: ((value: {
@@ -155,6 +155,17 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
155
155
  readonly mode: "formula" | "prefill";
156
156
  readonly expression: string;
157
157
  } | undefined;
158
+ readonly validations?: readonly {
159
+ readonly message: readonly [{
160
+ readonly locale: "zh";
161
+ readonly message: string;
162
+ }, ...{
163
+ readonly locale: "en" | "ja" | "ko";
164
+ readonly message: string;
165
+ }[]];
166
+ readonly warning?: boolean | undefined;
167
+ readonly when: string;
168
+ }[] | undefined;
158
169
  readonly addon?: {
159
170
  readonly size: "default" | "sm" | "xs";
160
171
  readonly style?: string | undefined;
@@ -222,17 +233,6 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
222
233
  readonly variant?: "default" | "link" | "destructive" | "primary" | "ghost" | undefined;
223
234
  }[];
224
235
  } | undefined;
225
- readonly validations?: readonly {
226
- readonly message: readonly [{
227
- readonly locale: "zh";
228
- readonly message: string;
229
- }, ...{
230
- readonly locale: "en" | "ja" | "ko";
231
- readonly message: string;
232
- }[]];
233
- readonly warning?: boolean | undefined;
234
- readonly when: string;
235
- }[] | undefined;
236
236
  }) => any) | undefined;
237
237
  }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
238
238
  declare const _default: typeof __VLS_export;
@@ -39,6 +39,17 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
39
39
  readonly mode: "formula" | "prefill";
40
40
  readonly expression: string;
41
41
  } | undefined;
42
+ readonly validations?: readonly {
43
+ readonly message: readonly [{
44
+ readonly locale: "zh";
45
+ readonly message: string;
46
+ }, ...{
47
+ readonly locale: "en" | "ja" | "ko";
48
+ readonly message: string;
49
+ }[]];
50
+ readonly warning?: boolean | undefined;
51
+ readonly when: string;
52
+ }[] | undefined;
42
53
  readonly addon?: {
43
54
  readonly size: "default" | "sm" | "xs";
44
55
  readonly style?: string | undefined;
@@ -106,17 +117,6 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
106
117
  readonly variant?: "default" | "link" | "destructive" | "primary" | "ghost" | undefined;
107
118
  }[];
108
119
  } | undefined;
109
- readonly validations?: readonly {
110
- readonly message: readonly [{
111
- readonly locale: "zh";
112
- readonly message: string;
113
- }, ...{
114
- readonly locale: "en" | "ja" | "ko";
115
- readonly message: string;
116
- }[]];
117
- readonly warning?: boolean | undefined;
118
- readonly when: string;
119
- }[] | undefined;
120
120
  }) => any;
121
121
  }, string, import("vue").PublicProps, Readonly<__VLS_ModelProps> & Readonly<{
122
122
  "onUpdate:modelValue"?: ((value: {
@@ -155,6 +155,17 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
155
155
  readonly mode: "formula" | "prefill";
156
156
  readonly expression: string;
157
157
  } | undefined;
158
+ readonly validations?: readonly {
159
+ readonly message: readonly [{
160
+ readonly locale: "zh";
161
+ readonly message: string;
162
+ }, ...{
163
+ readonly locale: "en" | "ja" | "ko";
164
+ readonly message: string;
165
+ }[]];
166
+ readonly warning?: boolean | undefined;
167
+ readonly when: string;
168
+ }[] | undefined;
158
169
  readonly addon?: {
159
170
  readonly size: "default" | "sm" | "xs";
160
171
  readonly style?: string | undefined;
@@ -222,17 +233,6 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
222
233
  readonly variant?: "default" | "link" | "destructive" | "primary" | "ghost" | undefined;
223
234
  }[];
224
235
  } | undefined;
225
- readonly validations?: readonly {
226
- readonly message: readonly [{
227
- readonly locale: "zh";
228
- readonly message: string;
229
- }, ...{
230
- readonly locale: "en" | "ja" | "ko";
231
- readonly message: string;
232
- }[]];
233
- readonly warning?: boolean | undefined;
234
- readonly when: string;
235
- }[] | undefined;
236
236
  }) => any) | undefined;
237
237
  }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
238
238
  declare const _default: typeof __VLS_export;
@@ -42,6 +42,17 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
42
42
  readonly mode: "formula" | "prefill";
43
43
  readonly expression: string;
44
44
  } | undefined;
45
+ readonly validations?: readonly {
46
+ readonly message: readonly [{
47
+ readonly locale: "zh";
48
+ readonly message: string;
49
+ }, ...{
50
+ readonly locale: "en" | "ja" | "ko";
51
+ readonly message: string;
52
+ }[]];
53
+ readonly warning?: boolean | undefined;
54
+ readonly when: string;
55
+ }[] | undefined;
45
56
  readonly addon?: {
46
57
  readonly size: "default" | "sm" | "xs";
47
58
  readonly style?: string | undefined;
@@ -109,17 +120,6 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
109
120
  readonly variant?: "default" | "link" | "destructive" | "primary" | "ghost" | undefined;
110
121
  }[];
111
122
  } | undefined;
112
- readonly validations?: readonly {
113
- readonly message: readonly [{
114
- readonly locale: "zh";
115
- readonly message: string;
116
- }, ...{
117
- readonly locale: "en" | "ja" | "ko";
118
- readonly message: string;
119
- }[]];
120
- readonly warning?: boolean | undefined;
121
- readonly when: string;
122
- }[] | undefined;
123
123
  readonly precision?: number | undefined;
124
124
  readonly roundingMode?: "round" | "floor" | "ceil" | undefined;
125
125
  readonly valueAsString?: boolean | undefined;
@@ -165,6 +165,17 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
165
165
  readonly mode: "formula" | "prefill";
166
166
  readonly expression: string;
167
167
  } | undefined;
168
+ readonly validations?: readonly {
169
+ readonly message: readonly [{
170
+ readonly locale: "zh";
171
+ readonly message: string;
172
+ }, ...{
173
+ readonly locale: "en" | "ja" | "ko";
174
+ readonly message: string;
175
+ }[]];
176
+ readonly warning?: boolean | undefined;
177
+ readonly when: string;
178
+ }[] | undefined;
168
179
  readonly addon?: {
169
180
  readonly size: "default" | "sm" | "xs";
170
181
  readonly style?: string | undefined;
@@ -232,17 +243,6 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
232
243
  readonly variant?: "default" | "link" | "destructive" | "primary" | "ghost" | undefined;
233
244
  }[];
234
245
  } | undefined;
235
- readonly validations?: readonly {
236
- readonly message: readonly [{
237
- readonly locale: "zh";
238
- readonly message: string;
239
- }, ...{
240
- readonly locale: "en" | "ja" | "ko";
241
- readonly message: string;
242
- }[]];
243
- readonly warning?: boolean | undefined;
244
- readonly when: string;
245
- }[] | undefined;
246
246
  readonly precision?: number | undefined;
247
247
  readonly roundingMode?: "round" | "floor" | "ceil" | undefined;
248
248
  readonly valueAsString?: boolean | undefined;
@@ -42,6 +42,17 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
42
42
  readonly mode: "formula" | "prefill";
43
43
  readonly expression: string;
44
44
  } | undefined;
45
+ readonly validations?: readonly {
46
+ readonly message: readonly [{
47
+ readonly locale: "zh";
48
+ readonly message: string;
49
+ }, ...{
50
+ readonly locale: "en" | "ja" | "ko";
51
+ readonly message: string;
52
+ }[]];
53
+ readonly warning?: boolean | undefined;
54
+ readonly when: string;
55
+ }[] | undefined;
45
56
  readonly addon?: {
46
57
  readonly size: "default" | "sm" | "xs";
47
58
  readonly style?: string | undefined;
@@ -109,17 +120,6 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
109
120
  readonly variant?: "default" | "link" | "destructive" | "primary" | "ghost" | undefined;
110
121
  }[];
111
122
  } | undefined;
112
- readonly validations?: readonly {
113
- readonly message: readonly [{
114
- readonly locale: "zh";
115
- readonly message: string;
116
- }, ...{
117
- readonly locale: "en" | "ja" | "ko";
118
- readonly message: string;
119
- }[]];
120
- readonly warning?: boolean | undefined;
121
- readonly when: string;
122
- }[] | undefined;
123
123
  readonly precision?: number | undefined;
124
124
  readonly roundingMode?: "round" | "floor" | "ceil" | undefined;
125
125
  readonly valueAsString?: boolean | undefined;
@@ -165,6 +165,17 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
165
165
  readonly mode: "formula" | "prefill";
166
166
  readonly expression: string;
167
167
  } | undefined;
168
+ readonly validations?: readonly {
169
+ readonly message: readonly [{
170
+ readonly locale: "zh";
171
+ readonly message: string;
172
+ }, ...{
173
+ readonly locale: "en" | "ja" | "ko";
174
+ readonly message: string;
175
+ }[]];
176
+ readonly warning?: boolean | undefined;
177
+ readonly when: string;
178
+ }[] | undefined;
168
179
  readonly addon?: {
169
180
  readonly size: "default" | "sm" | "xs";
170
181
  readonly style?: string | undefined;
@@ -232,17 +243,6 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
232
243
  readonly variant?: "default" | "link" | "destructive" | "primary" | "ghost" | undefined;
233
244
  }[];
234
245
  } | undefined;
235
- readonly validations?: readonly {
236
- readonly message: readonly [{
237
- readonly locale: "zh";
238
- readonly message: string;
239
- }, ...{
240
- readonly locale: "en" | "ja" | "ko";
241
- readonly message: string;
242
- }[]];
243
- readonly warning?: boolean | undefined;
244
- readonly when: string;
245
- }[] | undefined;
246
246
  readonly precision?: number | undefined;
247
247
  readonly roundingMode?: "round" | "floor" | "ceil" | undefined;
248
248
  readonly valueAsString?: boolean | undefined;
@@ -0,0 +1,31 @@
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.dynamic";
8
+ readonly id: string;
9
+ readonly hidden?: string | undefined;
10
+ readonly displayName?: string | undefined;
11
+ readonly transform: string;
12
+ readonly columns?: number | undefined;
13
+ readonly compatibilityDate: "2026-07-13";
14
+ readonly orientation?: "vertical" | "floating" | undefined;
15
+ readonly request: string;
16
+ }) => any;
17
+ }, string, import("vue").PublicProps, Readonly<__VLS_ModelProps> & Readonly<{
18
+ "onUpdate:modelValue"?: ((value: {
19
+ readonly type: "com.shwfed.form.field.dynamic";
20
+ readonly id: string;
21
+ readonly hidden?: string | undefined;
22
+ readonly displayName?: string | undefined;
23
+ readonly transform: string;
24
+ readonly columns?: number | undefined;
25
+ readonly compatibilityDate: "2026-07-13";
26
+ readonly orientation?: "vertical" | "floating" | undefined;
27
+ readonly request: string;
28
+ }) => any) | undefined;
29
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
30
+ declare const _default: typeof __VLS_export;
31
+ export default _default;
@@ -0,0 +1,191 @@
1
+ <script setup>
2
+ import { Field, FieldLabel } from "../../../../ui/field";
3
+ import { ExpressionEditor } from "../../../../ui/expression-editor";
4
+ import { InputGroup, InputGroupInput } from "../../../../ui/input-group";
5
+ import { Markdown } from "../../../../ui/markdown";
6
+ import {
7
+ Select,
8
+ SelectContent,
9
+ SelectItem,
10
+ SelectTrigger,
11
+ SelectValue
12
+ } from "../../../../ui/select";
13
+ import { getStructFieldDescription, getStructFieldTitle } from "../../../schema";
14
+ import { DEFAULT_FIELD_ORIENTATION, FIELD_ORIENTATION_OPTIONS } from "../../../utils/common";
15
+ import { schema } from "./schema";
16
+ defineOptions({ name: "ShwfedDynamicFieldConfig" });
17
+ const value = defineModel({ type: null, ...{ required: true } });
18
+ const fieldSchema = schema(() => {
19
+ });
20
+ const fieldTitle = (f) => getStructFieldTitle(fieldSchema, f) ?? f;
21
+ const fieldDescription = (f) => getStructFieldDescription(fieldSchema, f);
22
+ const TRANSFORM_VARS = {
23
+ json: { type: "optional<dyn>", label: "HTTP \u54CD\u5E94\u4F53" }
24
+ };
25
+ </script>
26
+
27
+ <template>
28
+ <div class="flex flex-col gap-3">
29
+ <Field orientation="vertical">
30
+ <FieldLabel class="text-xs text-zinc-500">
31
+ <template
32
+ v-if="fieldDescription('displayName')"
33
+ #tooltip
34
+ >
35
+ <Markdown
36
+ :source="fieldDescription('displayName')"
37
+ block
38
+ class="prose prose-sm prose-zinc"
39
+ />
40
+ </template>
41
+ {{ fieldTitle("displayName") }}
42
+ </FieldLabel>
43
+ <InputGroup>
44
+ <InputGroupInput
45
+ :model-value="value.displayName ?? ''"
46
+ placeholder="例:渠道自定义字段"
47
+ @update:model-value="(v) => {
48
+ const s = String(v ?? '');
49
+ value = { ...value, displayName: s.length > 0 ? s : void 0 };
50
+ }"
51
+ />
52
+ </InputGroup>
53
+ </Field>
54
+
55
+ <Field orientation="vertical">
56
+ <FieldLabel class="text-xs text-zinc-500">
57
+ <template
58
+ v-if="fieldDescription('request')"
59
+ #tooltip
60
+ >
61
+ <Markdown
62
+ :source="fieldDescription('request')"
63
+ block
64
+ class="prose prose-sm prose-zinc"
65
+ />
66
+ </template>
67
+ {{ fieldTitle("request") }}
68
+ </FieldLabel>
69
+ <ExpressionEditor
70
+ :model-value="value.request ?? ''"
71
+ placeholder="如 http.get('/api/fields').query('channel', 'other_inv')"
72
+ result-type="HttpRequest"
73
+ multiline
74
+ class="min-h-20"
75
+ @update:model-value="(v) => value = { ...value, request: v }"
76
+ />
77
+ </Field>
78
+
79
+ <Field orientation="vertical">
80
+ <FieldLabel class="text-xs text-zinc-500">
81
+ <template
82
+ v-if="fieldDescription('transform')"
83
+ #tooltip
84
+ >
85
+ <Markdown
86
+ :source="fieldDescription('transform')"
87
+ block
88
+ class="prose prose-sm prose-zinc"
89
+ />
90
+ </template>
91
+ {{ fieldTitle("transform") }}
92
+ </FieldLabel>
93
+ <ExpressionEditor
94
+ :model-value="value.transform ?? ''"
95
+ placeholder="如 json.orValue([]).map(f, { 'binding': f.parameter_name, 'label': f.name, 'kind': 'text', 'required': f.is_mandatory })"
96
+ result-type="list"
97
+ multiline
98
+ class="min-h-32"
99
+ :extra-vars="TRANSFORM_VARS"
100
+ @update:model-value="(v) => value = { ...value, transform: v }"
101
+ />
102
+ </Field>
103
+
104
+ <div class="grid grid-cols-2 gap-3">
105
+ <Field orientation="vertical">
106
+ <FieldLabel class="text-xs text-zinc-500">
107
+ <template
108
+ v-if="fieldDescription('columns')"
109
+ #tooltip
110
+ >
111
+ <Markdown
112
+ :source="fieldDescription('columns')"
113
+ block
114
+ class="prose prose-sm prose-zinc"
115
+ />
116
+ </template>
117
+ {{ fieldTitle("columns") }}
118
+ </FieldLabel>
119
+ <InputGroup>
120
+ <InputGroupInput
121
+ :model-value="value.columns ?? ''"
122
+ type="number"
123
+ min="1"
124
+ step="1"
125
+ placeholder="1"
126
+ @update:model-value="(v) => {
127
+ const n = Math.floor(Number(v));
128
+ value = Number.isFinite(n) && n > 0 ? { ...value, columns: n } : (() => {
129
+ const { columns: _o, ...rest } = value;
130
+ return rest;
131
+ })();
132
+ }"
133
+ />
134
+ </InputGroup>
135
+ </Field>
136
+
137
+ <Field orientation="vertical">
138
+ <FieldLabel class="text-xs text-zinc-500">
139
+ <template
140
+ v-if="fieldDescription('orientation')"
141
+ #tooltip
142
+ >
143
+ <Markdown
144
+ :source="fieldDescription('orientation')"
145
+ block
146
+ class="prose prose-sm prose-zinc"
147
+ />
148
+ </template>
149
+ {{ fieldTitle("orientation") }}
150
+ </FieldLabel>
151
+ <Select
152
+ :model-value="value.orientation ?? DEFAULT_FIELD_ORIENTATION"
153
+ @update:model-value="(v) => value = { ...value, orientation: v }"
154
+ >
155
+ <SelectTrigger class="w-full">
156
+ <SelectValue />
157
+ </SelectTrigger>
158
+ <SelectContent>
159
+ <SelectItem
160
+ v-for="opt in FIELD_ORIENTATION_OPTIONS"
161
+ :key="opt.value"
162
+ :value="opt.value"
163
+ >
164
+ {{ opt.label }}
165
+ </SelectItem>
166
+ </SelectContent>
167
+ </Select>
168
+ </Field>
169
+ </div>
170
+
171
+ <Field orientation="vertical">
172
+ <FieldLabel class="text-xs text-zinc-500">
173
+ <template #tooltip>
174
+ <Markdown
175
+ :source="fieldDescription('hidden') ?? '\u8FD4\u56DE `true` \u65F6\u6574\u4E2A\u52A8\u6001\u533A\u57DF\u5728\u6240\u6709\u5E03\u5C40\u4E2D\u90FD\u4E0D\u6E32\u67D3'"
176
+ block
177
+ class="prose prose-sm prose-zinc"
178
+ />
179
+ </template>
180
+ {{ fieldTitle("hidden") }}
181
+ </FieldLabel>
182
+ <ExpressionEditor
183
+ :model-value="value.hidden ?? ''"
184
+ placeholder="例:form.channel == ''"
185
+ result-type="bool"
186
+ class="min-h-10"
187
+ @update:model-value="(v) => value = { ...value, hidden: v.length > 0 ? v : void 0 }"
188
+ />
189
+ </Field>
190
+ </div>
191
+ </template>