@shwfed/config 2.3.28 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (146) hide show
  1. package/dist/mcp.mjs +3128 -1272
  2. package/dist/module.json +1 -1
  3. package/dist/preview/assets/{config-CQHS6cZe.js → config-BcQQl4v6.js} +1 -1
  4. package/dist/preview/assets/{config-fvkC2rB8.js → config-BdFIFUa_.js} +1 -1
  5. package/dist/preview/assets/{config-DDfTl9Cs.js → config-Bi9F-Jdh.js} +1 -1
  6. package/dist/preview/assets/{config-CJHPt8Gx.js → config-Bxkq2ZRm.js} +1 -1
  7. package/dist/preview/assets/{config-D0_1yZdF.js → config-C32yfrlg.js} +1 -1
  8. package/dist/preview/assets/{config--PcXQV_r.js → config-CHHX7vhb.js} +1 -1
  9. package/dist/preview/assets/{config-5KVDXgUF.js → config-CZ0f5xdI.js} +1 -1
  10. package/dist/preview/assets/{config-B5avpKJE.js → config-D9xGgFnF.js} +1 -1
  11. package/dist/preview/assets/{config-CNo3isHa.js → config-Ddh8pxIi.js} +1 -1
  12. package/dist/preview/assets/{definition.vue_vue_type_script_setup_true_lang-RM-qDh0R.js → definition.vue_vue_type_script_setup_true_lang-C_cjxvm1.js} +1 -1
  13. package/dist/preview/assets/{index-a2QwAots.css → index-BqOX70Hd.css} +1 -1
  14. package/dist/preview/assets/index-D-VR1i8D.js +659 -0
  15. package/dist/preview/assets/index-ihZGlPdX.js +1 -0
  16. package/dist/preview/assets/{runtime-BPjZQmcY.js → runtime-Bn8mqeDH.js} +1 -1
  17. package/dist/preview/assets/{runtime-DcrzodsN.js → runtime-Cc_Wk3o-.js} +1 -1
  18. package/dist/preview/assets/{runtime-BGTWf-O7.js → runtime-CttAjIgg.js} +1 -1
  19. package/dist/preview/assets/{runtime-Dy4ZmQ-n.js → runtime-Cx4f2UTl.js} +1 -1
  20. package/dist/preview/assets/{runtime-CCbyrqQT.js → runtime-D1dESjXR.js} +1 -1
  21. package/dist/preview/assets/{runtime-C_XX6a0C.js → runtime-DIEP1Xbh.js} +1 -1
  22. package/dist/preview/assets/{runtime-CtqwtTE_.js → runtime-DKceWuBx.js} +1 -1
  23. package/dist/preview/assets/{runtime-Dr_10emf.js → runtime-Dhid9O5c.js} +1 -1
  24. package/dist/preview/assets/{runtime-Bq3fmxeF.js → runtime-YMiqi6WY.js} +1 -1
  25. package/dist/preview/index.html +2 -2
  26. package/dist/runtime/components/block-layout-editor/index.d.vue.ts +10 -2
  27. package/dist/runtime/components/block-layout-editor/index.vue +44 -8
  28. package/dist/runtime/components/block-layout-editor/index.vue.d.ts +10 -2
  29. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.form/config.d.vue.ts +2 -0
  30. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.form/config.vue.d.ts +2 -0
  31. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.form/runtime.d.vue.ts +2 -0
  32. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.form/runtime.vue.d.ts +2 -0
  33. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.form/schema.d.ts +2 -0
  34. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.table/config.d.vue.ts +2 -0
  35. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.table/config.vue.d.ts +2 -0
  36. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.table/runtime.d.vue.ts +2 -0
  37. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.table/runtime.vue.d.ts +2 -0
  38. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.table/schema.d.ts +3 -0
  39. package/dist/runtime/components/config/config.vue +35 -0
  40. package/dist/runtime/components/config/use-editor.d.ts +11 -1
  41. package/dist/runtime/components/config/use-editor.js +27 -1
  42. package/dist/runtime/components/form/config.vue +32 -0
  43. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.multi/config.d.vue.ts +163 -0
  44. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.multi/config.vue +745 -0
  45. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.multi/config.vue.d.ts +163 -0
  46. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.multi/runtime.d.vue.ts +8 -0
  47. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.multi/runtime.vue +383 -0
  48. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.multi/runtime.vue.d.ts +8 -0
  49. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.multi/schema.d.ts +264 -0
  50. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.multi/schema.js +183 -0
  51. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.single/config.d.vue.ts +163 -0
  52. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.single/config.vue +745 -0
  53. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.single/config.vue.d.ts +163 -0
  54. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.single/runtime.d.vue.ts +8 -0
  55. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.single/runtime.vue +402 -0
  56. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.single/runtime.vue.d.ts +8 -0
  57. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.single/schema.d.ts +264 -0
  58. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.single/schema.js +209 -0
  59. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.multi/config.d.vue.ts +129 -0
  60. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.multi/config.vue +618 -0
  61. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.multi/config.vue.d.ts +129 -0
  62. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.multi/runtime.d.vue.ts +8 -0
  63. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.multi/runtime.vue +501 -0
  64. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.multi/runtime.vue.d.ts +8 -0
  65. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.multi/schema.d.ts +99 -0
  66. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.multi/schema.js +133 -0
  67. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.single/config.d.vue.ts +127 -0
  68. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.single/config.vue +550 -0
  69. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.single/config.vue.d.ts +127 -0
  70. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.single/runtime.d.vue.ts +8 -0
  71. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.single/runtime.vue +496 -0
  72. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.single/runtime.vue.d.ts +8 -0
  73. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.single/schema.d.ts +96 -0
  74. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.single/schema.js +125 -0
  75. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.multi/config.d.vue.ts +133 -0
  76. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.multi/config.vue +605 -0
  77. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.multi/config.vue.d.ts +133 -0
  78. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.multi/runtime.d.vue.ts +8 -0
  79. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.multi/runtime.vue +401 -0
  80. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.multi/runtime.vue.d.ts +8 -0
  81. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.multi/schema.d.ts +102 -0
  82. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.multi/schema.js +142 -0
  83. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.single/config.d.vue.ts +131 -0
  84. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.single/config.vue +560 -0
  85. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.single/config.vue.d.ts +131 -0
  86. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.single/runtime.d.vue.ts +8 -0
  87. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.single/runtime.vue +395 -0
  88. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.single/runtime.vue.d.ts +8 -0
  89. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.single/schema.d.ts +96 -0
  90. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.single/schema.js +118 -0
  91. package/dist/runtime/components/form/fields/2026-05-28/tree-combobox-shared.d.ts +35 -0
  92. package/dist/runtime/components/form/fields/2026-05-28/tree-combobox-shared.js +31 -0
  93. package/dist/runtime/components/form/index.vue +7 -5
  94. package/dist/runtime/components/form/schema.d.ts +4 -0
  95. package/dist/runtime/components/form/schema.js +4 -0
  96. package/dist/runtime/components/form/unit-config.vue +45 -1
  97. package/dist/runtime/components/table/columns/2026-04-14/com.shwfed.table.column.select/config.vue +0 -22
  98. package/dist/runtime/components/table/columns/2026-04-14/com.shwfed.table.column.select/header.vue +3 -15
  99. package/dist/runtime/components/table/columns/2026-04-14/com.shwfed.table.column.select/schema.d.ts +0 -1
  100. package/dist/runtime/components/table/columns/2026-04-14/com.shwfed.table.column.select/schema.js +0 -4
  101. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-multi/config.d.vue.ts +183 -0
  102. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-multi/config.vue +931 -0
  103. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-multi/config.vue.d.ts +183 -0
  104. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-multi/runtime.d.vue.ts +9 -0
  105. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-multi/runtime.vue +463 -0
  106. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-multi/runtime.vue.d.ts +9 -0
  107. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-multi/schema.d.ts +283 -0
  108. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-multi/schema.js +275 -0
  109. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-single/config.d.vue.ts +183 -0
  110. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-single/config.vue +931 -0
  111. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-single/config.vue.d.ts +183 -0
  112. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-single/runtime.d.vue.ts +9 -0
  113. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-single/runtime.vue +414 -0
  114. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-single/runtime.vue.d.ts +9 -0
  115. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-single/schema.d.ts +283 -0
  116. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-single/schema.js +275 -0
  117. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-multi/config.d.vue.ts +133 -0
  118. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-multi/config.vue +632 -0
  119. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-multi/config.vue.d.ts +133 -0
  120. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-multi/runtime.d.vue.ts +9 -0
  121. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-multi/runtime.vue +461 -0
  122. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-multi/runtime.vue.d.ts +9 -0
  123. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-multi/schema.d.ts +93 -0
  124. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-multi/schema.js +161 -0
  125. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-single/config.d.vue.ts +131 -0
  126. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-single/config.vue +563 -0
  127. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-single/config.vue.d.ts +131 -0
  128. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-single/runtime.d.vue.ts +9 -0
  129. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-single/runtime.vue +443 -0
  130. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-single/runtime.vue.d.ts +9 -0
  131. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-single/schema.d.ts +90 -0
  132. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-single/schema.js +153 -0
  133. package/dist/runtime/components/table/columns/2026-05-28/tree-combobox-shared.d.ts +35 -0
  134. package/dist/runtime/components/table/columns/2026-05-28/tree-combobox-shared.js +31 -0
  135. package/dist/runtime/components/table/config.vue +55 -82
  136. package/dist/runtime/components/table/schema.d.ts +4 -0
  137. package/dist/runtime/components/ui/command/CommandItem.d.vue.ts +7 -0
  138. package/dist/runtime/components/ui/command/CommandItem.vue +13 -4
  139. package/dist/runtime/components/ui/command/CommandItem.vue.d.ts +7 -0
  140. package/dist/runtime/share/clipboard.d.ts +26 -0
  141. package/dist/runtime/share/clipboard.js +82 -0
  142. package/dist/runtime/share/layout.d.ts +4 -0
  143. package/dist/runtime/share/layout.js +35 -0
  144. package/package.json +1 -1
  145. package/dist/preview/assets/index-DNd8J9Zv.js +0 -643
  146. package/dist/preview/assets/index-DrIMqXAa.js +0 -1
@@ -0,0 +1,745 @@
1
+ <script setup>
2
+ import { Icon } from "@iconify/vue";
3
+ import { computed } from "vue";
4
+ import { Button } from "../../../../ui/button";
5
+ import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "../../../../ui/dropdown-menu";
6
+ import { ExpressionEditor } from "../../../../ui/expression-editor";
7
+ import DerivedValueEditor from "../../../DerivedValueEditor.vue";
8
+ import { Field, FieldLabel } from "../../../../ui/field";
9
+ import { InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupNumberField } from "../../../../ui/input-group";
10
+ import { Locale as LocaleField } from "../../../../ui/locale";
11
+ import { Markdown } from "../../../../ui/markdown";
12
+ import {
13
+ Select,
14
+ SelectContent,
15
+ SelectItem,
16
+ SelectTrigger,
17
+ SelectValue
18
+ } from "../../../../ui/select";
19
+ import { Tabs, TabsContent, TabsList, TabsTrigger } from "../../../../ui/tabs";
20
+ import { Textarea } from "../../../../ui/textarea";
21
+ import { getStructFieldDescription, getStructFieldTitle } from "../../../schema";
22
+ import { DEFAULT_FIELD_ORIENTATION, FIELD_ORIENTATION_OPTIONS } from "../../../utils/common";
23
+ import { itemSchema, remoteOptionsSchema, schema } from "./schema";
24
+ defineOptions({ name: "ShwfedComboboxSingleFieldConfig" });
25
+ const value = defineModel({ type: null, ...{ required: true } });
26
+ const fieldSchema = schema(() => {
27
+ });
28
+ const fieldTitle = (f) => getStructFieldTitle(fieldSchema, f) ?? f;
29
+ const fieldDescription = (f) => getStructFieldDescription(fieldSchema, f);
30
+ const itemFieldSchema = itemSchema(() => {
31
+ });
32
+ const itemFieldTitle = (f) => getStructFieldTitle(itemFieldSchema, f) ?? f;
33
+ const itemFieldDescription = (f) => getStructFieldDescription(itemFieldSchema, f);
34
+ const remoteSchema = remoteOptionsSchema(() => {
35
+ });
36
+ const remoteFieldTitle = (f) => getStructFieldTitle(remoteSchema, f) ?? f;
37
+ const remoteFieldDescription = (f) => getStructFieldDescription(remoteSchema, f);
38
+ const OPTION_VARS = {
39
+ option: { type: "dyn", label: "\u5F53\u524D\u9009\u9879" }
40
+ };
41
+ const JSON_VARS = {
42
+ json: { type: "dyn", label: "HTTP \u54CD\u5E94\u4F53\uFF08\u5DF2\u89E3\u6790 JSON\uFF09" }
43
+ };
44
+ const pathText = computed({
45
+ get: () => value.value.binding ?? "",
46
+ set: (next) => {
47
+ const trimmed = next.trim();
48
+ if (trimmed.length === 0) {
49
+ const { binding: _omit, ...rest } = value.value;
50
+ value.value = rest;
51
+ } else {
52
+ value.value = { ...value.value, binding: trimmed };
53
+ }
54
+ }
55
+ });
56
+ const optionsKind = computed(() => value.value.options.kind);
57
+ function emptyStatic() {
58
+ return { kind: "static", items: [] };
59
+ }
60
+ function emptyRemote() {
61
+ return {
62
+ kind: "remote",
63
+ request: "",
64
+ options: "",
65
+ optionValue: "option",
66
+ optionLabel: [{ locale: "zh", message: "" }]
67
+ };
68
+ }
69
+ function setKind(kind) {
70
+ if (value.value.options.kind === kind) return;
71
+ value.value = {
72
+ ...value.value,
73
+ options: kind === "static" ? emptyStatic() : emptyRemote()
74
+ };
75
+ }
76
+ function patchStatic(patch) {
77
+ if (value.value.options.kind !== "static") return;
78
+ value.value = { ...value.value, options: { ...value.value.options, ...patch } };
79
+ }
80
+ function patchRemote(patch) {
81
+ if (value.value.options.kind !== "remote") return;
82
+ value.value = { ...value.value, options: { ...value.value.options, ...patch } };
83
+ }
84
+ const requestModel = computed({
85
+ get: () => value.value.options.kind === "remote" ? value.value.options.request ?? "" : "",
86
+ set: (v) => {
87
+ if (value.value.options.kind !== "remote") return;
88
+ if (v === "") {
89
+ const { request: _omit, ...rest } = value.value.options;
90
+ value.value = { ...value.value, options: rest };
91
+ } else {
92
+ patchRemote({ request: v });
93
+ }
94
+ }
95
+ });
96
+ const optionsExprModel = computed({
97
+ get: () => value.value.options.kind === "remote" ? value.value.options.options : "",
98
+ set: (v) => patchRemote({ options: v })
99
+ });
100
+ const optionValueModel = computed({
101
+ get: () => value.value.options.kind === "remote" ? value.value.options.optionValue : "option",
102
+ set: (v) => patchRemote({ optionValue: v })
103
+ });
104
+ const optionLabelModel = computed({
105
+ get: () => value.value.options.kind === "remote" ? value.value.options.optionLabel : [{ locale: "zh", message: "" }],
106
+ set: (v) => patchRemote({ optionLabel: v })
107
+ });
108
+ const optionKeywordsModel = computed({
109
+ get: () => value.value.options.kind === "remote" ? value.value.options.optionKeywords ?? "" : "",
110
+ set: (v) => {
111
+ if (value.value.options.kind !== "remote") return;
112
+ if (v === "") {
113
+ const { optionKeywords: _omit, ...rest } = value.value.options;
114
+ value.value = { ...value.value, options: rest };
115
+ } else {
116
+ patchRemote({ optionKeywords: v });
117
+ }
118
+ }
119
+ });
120
+ const items = computed(
121
+ () => value.value.options.kind === "static" ? value.value.options.items : []
122
+ );
123
+ function newId() {
124
+ return typeof crypto !== "undefined" && "randomUUID" in crypto ? crypto.randomUUID() : "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
125
+ const r = Math.random() * 16 | 0;
126
+ const v = c === "x" ? r : r & 3 | 8;
127
+ return v.toString(16);
128
+ });
129
+ }
130
+ function newItem() {
131
+ return {
132
+ id: newId(),
133
+ label: [{ locale: "zh", message: "" }],
134
+ value: { kind: "text", value: "" }
135
+ };
136
+ }
137
+ function patchItem(index, patch) {
138
+ if (value.value.options.kind !== "static") return;
139
+ const next = [...value.value.options.items];
140
+ const cur = next[index];
141
+ if (!cur) return;
142
+ next[index] = { ...cur, ...patch };
143
+ patchStatic({ items: next });
144
+ }
145
+ function addItem() {
146
+ if (value.value.options.kind !== "static") return;
147
+ patchStatic({ items: [...value.value.options.items, newItem()] });
148
+ }
149
+ function removeItem(index) {
150
+ if (value.value.options.kind !== "static") return;
151
+ const next = [...value.value.options.items];
152
+ next.splice(index, 1);
153
+ patchStatic({ items: next });
154
+ }
155
+ function setItemKind(index, kind) {
156
+ if (value.value.options.kind !== "static") return;
157
+ const cur = value.value.options.items[index];
158
+ if (!cur || cur.value.kind === kind) return;
159
+ patchItem(index, {
160
+ value: kind === "text" ? { kind: "text", value: "" } : { kind: "number", value: 0 }
161
+ });
162
+ }
163
+ function setItemTextValue(index, text) {
164
+ patchItem(index, { value: { kind: "text", value: text } });
165
+ }
166
+ function setItemNumberValue(index, n) {
167
+ patchItem(index, {
168
+ value: {
169
+ kind: "number",
170
+ value: typeof n === "number" && Number.isFinite(n) ? n : 0
171
+ }
172
+ });
173
+ }
174
+ function setItemLabel(index, label) {
175
+ patchItem(index, { label });
176
+ }
177
+ function setItemTooltip(index, tooltip) {
178
+ if (value.value.options.kind !== "static") return;
179
+ const isEmpty = !tooltip || tooltip.every((l) => l.message.trim().length === 0);
180
+ if (isEmpty) {
181
+ const cur = value.value.options.items[index];
182
+ if (!cur) return;
183
+ const { tooltip: _omit, ...rest } = cur;
184
+ const next = [...value.value.options.items];
185
+ next[index] = rest;
186
+ patchStatic({ items: next });
187
+ } else {
188
+ patchItem(index, { tooltip });
189
+ }
190
+ }
191
+ function keywordsText(item) {
192
+ return (item.keywords ?? []).join("\n");
193
+ }
194
+ function setItemKeywords(index, text) {
195
+ if (value.value.options.kind !== "static") return;
196
+ const terms = text.split("\n").map((s) => s.trim()).filter(Boolean);
197
+ if (terms.length === 0) {
198
+ const cur = value.value.options.items[index];
199
+ if (!cur) return;
200
+ const { keywords: _omit, ...rest } = cur;
201
+ const next = [...value.value.options.items];
202
+ next[index] = rest;
203
+ patchStatic({ items: next });
204
+ } else {
205
+ patchItem(index, { keywords: terms });
206
+ }
207
+ }
208
+ </script>
209
+
210
+ <template>
211
+ <div class="flex flex-col gap-3">
212
+ <div class="grid grid-cols-2 gap-3">
213
+ <Field orientation="vertical">
214
+ <FieldLabel class="text-xs text-zinc-500">
215
+ <template
216
+ v-if="fieldDescription('displayName')"
217
+ #tooltip
218
+ >
219
+ <Markdown
220
+ :source="fieldDescription('displayName')"
221
+ block
222
+ class="prose prose-sm prose-zinc"
223
+ />
224
+ </template>
225
+ {{ fieldTitle("displayName") }}
226
+ </FieldLabel>
227
+ <InputGroup>
228
+ <InputGroupInput
229
+ :model-value="value.displayName ?? ''"
230
+ placeholder="例:用户角色"
231
+ @update:model-value="(v) => {
232
+ const s = String(v ?? '');
233
+ value = { ...value, displayName: s.length > 0 ? s : void 0 };
234
+ }"
235
+ />
236
+ </InputGroup>
237
+ </Field>
238
+
239
+ <Field orientation="vertical">
240
+ <FieldLabel class="text-xs text-zinc-500">
241
+ <template #tooltip>
242
+ <Markdown
243
+ source="写入表单状态的嵌套键路径,使用 `.` 分隔,例如 `user.role`"
244
+ block
245
+ class="prose prose-sm prose-zinc"
246
+ />
247
+ </template>
248
+ {{ fieldTitle("binding") }}
249
+ </FieldLabel>
250
+ <InputGroup>
251
+ <InputGroupInput
252
+ v-model="pathText"
253
+ placeholder="例:user.role"
254
+ class="font-mono"
255
+ />
256
+ </InputGroup>
257
+ </Field>
258
+ </div>
259
+
260
+ <div class="grid grid-cols-3 gap-3">
261
+ <Field orientation="vertical">
262
+ <FieldLabel class="text-xs text-zinc-500">
263
+ <template
264
+ v-if="fieldDescription('label')"
265
+ #tooltip
266
+ >
267
+ <Markdown
268
+ :source="fieldDescription('label')"
269
+ block
270
+ class="prose prose-sm prose-zinc"
271
+ />
272
+ </template>
273
+ {{ fieldTitle("label") }}
274
+ </FieldLabel>
275
+ <LocaleField
276
+ translate-hint="form field label"
277
+ :model-value="value.label"
278
+ @update:model-value="(v) => value = { ...value, label: v }"
279
+ />
280
+ </Field>
281
+
282
+ <Field orientation="vertical">
283
+ <FieldLabel class="text-xs text-zinc-500">
284
+ <template
285
+ v-if="fieldDescription('placeholder')"
286
+ #tooltip
287
+ >
288
+ <Markdown
289
+ :source="fieldDescription('placeholder')"
290
+ block
291
+ class="prose prose-sm prose-zinc"
292
+ />
293
+ </template>
294
+ {{ fieldTitle("placeholder") }}
295
+ </FieldLabel>
296
+ <LocaleField
297
+ translate-hint="form field placeholder"
298
+ :model-value="value.placeholder"
299
+ @update:model-value="(v) => value = { ...value, placeholder: v }"
300
+ />
301
+ </Field>
302
+
303
+ <Field orientation="vertical">
304
+ <FieldLabel class="text-xs text-zinc-500">
305
+ <template
306
+ v-if="fieldDescription('tooltip')"
307
+ #tooltip
308
+ >
309
+ <Markdown
310
+ :source="fieldDescription('tooltip')"
311
+ block
312
+ class="prose prose-sm prose-zinc"
313
+ />
314
+ </template>
315
+ {{ fieldTitle("tooltip") }}
316
+ </FieldLabel>
317
+ <LocaleField
318
+ markdown
319
+ translate-hint="form field tooltip"
320
+ :model-value="value.tooltip"
321
+ @update:model-value="(v) => value = { ...value, tooltip: v }"
322
+ />
323
+ </Field>
324
+ </div>
325
+
326
+ <div class="grid grid-cols-3 gap-3">
327
+ <Field orientation="vertical">
328
+ <FieldLabel class="text-xs text-zinc-500">
329
+ <template
330
+ v-if="fieldDescription('orientation')"
331
+ #tooltip
332
+ >
333
+ <Markdown
334
+ :source="fieldDescription('orientation')"
335
+ block
336
+ class="prose prose-sm prose-zinc"
337
+ />
338
+ </template>
339
+ {{ fieldTitle("orientation") }}
340
+ </FieldLabel>
341
+ <Select
342
+ :model-value="value.orientation ?? DEFAULT_FIELD_ORIENTATION"
343
+ @update:model-value="(v) => value = { ...value, orientation: v }"
344
+ >
345
+ <SelectTrigger class="w-full">
346
+ <SelectValue />
347
+ </SelectTrigger>
348
+ <SelectContent>
349
+ <SelectItem
350
+ v-for="opt in FIELD_ORIENTATION_OPTIONS"
351
+ :key="opt.value"
352
+ :value="opt.value"
353
+ >
354
+ {{ opt.label }}
355
+ </SelectItem>
356
+ </SelectContent>
357
+ </Select>
358
+ </Field>
359
+ </div>
360
+
361
+ <Field orientation="vertical">
362
+ <FieldLabel class="text-xs text-zinc-500">
363
+ <template #tooltip>
364
+ <Markdown
365
+ source="选项可以是静态配置的固定列表,也可以由 CEL 表达式或远程接口产出"
366
+ block
367
+ class="prose prose-sm prose-zinc"
368
+ />
369
+ </template>
370
+ 选项来源
371
+ </FieldLabel>
372
+
373
+ <Tabs
374
+ :model-value="optionsKind"
375
+ @update:model-value="(v) => {
376
+ if (v === 'static' || v === 'remote') setKind(v);
377
+ }"
378
+ >
379
+ <TabsList>
380
+ <TabsTrigger value="static">
381
+ 静态
382
+ </TabsTrigger>
383
+ <TabsTrigger value="remote">
384
+ 远程
385
+ </TabsTrigger>
386
+ </TabsList>
387
+ <TabsContent
388
+ value="static"
389
+ class="outline-none"
390
+ >
391
+ <div class="flex flex-col gap-3 pt-3">
392
+ <div
393
+ v-for="(item, index) in items"
394
+ :key="item.id"
395
+ data-slot="combobox-single-item"
396
+ class="relative pt-8 grid grid-cols-2 gap-3 rounded border border-zinc-200 bg-zinc-50/40 p-3"
397
+ >
398
+ <InputGroupButton
399
+ variant="destructive"
400
+ size="icon-xs"
401
+ data-slot="combobox-single-item-delete"
402
+ aria-label="删除选项"
403
+ class="absolute right-2 top-2 z-10"
404
+ @click="removeItem(index)"
405
+ >
406
+ <Icon icon="fluent:delete-20-regular" />
407
+ </InputGroupButton>
408
+
409
+ <Field orientation="vertical">
410
+ <FieldLabel class="text-xs text-zinc-500">
411
+ <template
412
+ v-if="itemFieldDescription('label')"
413
+ #tooltip
414
+ >
415
+ <Markdown
416
+ :source="itemFieldDescription('label')"
417
+ block
418
+ class="prose prose-sm prose-zinc"
419
+ />
420
+ </template>
421
+ {{ itemFieldTitle("label") }}
422
+ </FieldLabel>
423
+ <LocaleField
424
+ markdown
425
+ translate-hint="combobox option label"
426
+ :model-value="item.label"
427
+ @update:model-value="(v) => setItemLabel(index, v)"
428
+ />
429
+ </Field>
430
+
431
+ <Field orientation="vertical">
432
+ <FieldLabel class="text-xs text-zinc-500">
433
+ <template
434
+ v-if="itemFieldDescription('value')"
435
+ #tooltip
436
+ >
437
+ <Markdown
438
+ :source="itemFieldDescription('value')"
439
+ block
440
+ class="prose prose-sm prose-zinc"
441
+ />
442
+ </template>
443
+ {{ itemFieldTitle("value") }}
444
+ </FieldLabel>
445
+ <InputGroup>
446
+ <InputGroupAddon align="inline-start">
447
+ <DropdownMenu>
448
+ <DropdownMenuTrigger as-child>
449
+ <InputGroupButton
450
+ size="icon-sm"
451
+ as-child
452
+ >
453
+ <button
454
+ type="button"
455
+ data-slot="combobox-single-item-kind-trigger"
456
+ class="text-zinc-500 transition-colors hover:text-zinc-700 [&_svg:not([class*='size-'])]:size-3.5"
457
+ aria-label="切换值类型"
458
+ >
459
+ <Icon
460
+ :icon="item.value.kind === 'number' ? 'fluent:number-symbol-20-regular' : 'fluent:textbox-20-regular'"
461
+ />
462
+ </button>
463
+ </InputGroupButton>
464
+ </DropdownMenuTrigger>
465
+ <DropdownMenuContent align="start">
466
+ <DropdownMenuItem @select="setItemKind(index, 'text')">
467
+ <Icon icon="fluent:textbox-20-regular" />
468
+ <span>文本</span>
469
+ </DropdownMenuItem>
470
+ <DropdownMenuItem @select="setItemKind(index, 'number')">
471
+ <Icon icon="fluent:number-symbol-20-regular" />
472
+ <span>数字</span>
473
+ </DropdownMenuItem>
474
+ </DropdownMenuContent>
475
+ </DropdownMenu>
476
+ </InputGroupAddon>
477
+
478
+ <InputGroupInput
479
+ v-if="item.value.kind === 'text'"
480
+ :model-value="item.value.value"
481
+ placeholder="例:admin"
482
+ @update:model-value="(v) => setItemTextValue(index, String(v ?? ''))"
483
+ />
484
+ <InputGroupNumberField
485
+ v-else
486
+ :model-value="item.value.value"
487
+ @update:model-value="(v) => setItemNumberValue(index, v)"
488
+ />
489
+ </InputGroup>
490
+ </Field>
491
+
492
+ <Field orientation="vertical">
493
+ <FieldLabel class="text-xs text-zinc-500">
494
+ <template
495
+ v-if="itemFieldDescription('tooltip')"
496
+ #tooltip
497
+ >
498
+ <Markdown
499
+ :source="itemFieldDescription('tooltip')"
500
+ block
501
+ class="prose prose-sm prose-zinc"
502
+ />
503
+ </template>
504
+ {{ itemFieldTitle("tooltip") }}
505
+ </FieldLabel>
506
+ <LocaleField
507
+ markdown
508
+ translate-hint="combobox option tooltip"
509
+ :model-value="item.tooltip"
510
+ @update:model-value="(v) => setItemTooltip(index, v)"
511
+ />
512
+ </Field>
513
+
514
+ <Field orientation="vertical">
515
+ <FieldLabel class="text-xs text-zinc-500">
516
+ <template
517
+ v-if="itemFieldDescription('keywords')"
518
+ #tooltip
519
+ >
520
+ <Markdown
521
+ :source="itemFieldDescription('keywords')"
522
+ block
523
+ class="prose prose-sm prose-zinc"
524
+ />
525
+ </template>
526
+ {{ itemFieldTitle("keywords") }}
527
+ </FieldLabel>
528
+ <Textarea
529
+ data-slot="combobox-single-item-keywords"
530
+ placeholder="每行一个关键词"
531
+ :model-value="keywordsText(item)"
532
+ @update:model-value="(v) => setItemKeywords(index, String(v ?? ''))"
533
+ />
534
+ </Field>
535
+ </div>
536
+
537
+ <Button
538
+ type="button"
539
+ data-slot="combobox-single-add-item"
540
+ class="w-full justify-center"
541
+ @click="addItem"
542
+ >
543
+ <Icon icon="fluent:add-20-regular" />
544
+ <span>增加选项</span>
545
+ </Button>
546
+ </div>
547
+ </TabsContent>
548
+ <TabsContent
549
+ value="remote"
550
+ class="outline-none"
551
+ >
552
+ <div class="grid grid-cols-2 gap-x-6 gap-y-4 pt-3">
553
+ <Field orientation="vertical">
554
+ <FieldLabel class="text-xs text-zinc-500">
555
+ <template
556
+ v-if="remoteFieldDescription('request')"
557
+ #tooltip
558
+ >
559
+ <Markdown
560
+ :source="remoteFieldDescription('request')"
561
+ block
562
+ class="prose prose-sm prose-zinc"
563
+ />
564
+ </template>
565
+ {{ remoteFieldTitle("request") }}
566
+ </FieldLabel>
567
+ <ExpressionEditor
568
+ v-model="requestModel"
569
+ placeholder="如 http.get('/api/roles');留空则不发起请求"
570
+ result-type="HttpRequest"
571
+ multiline
572
+ />
573
+ </Field>
574
+ <Field orientation="vertical">
575
+ <FieldLabel class="text-xs text-zinc-500">
576
+ <template
577
+ v-if="remoteFieldDescription('options')"
578
+ #tooltip
579
+ >
580
+ <Markdown
581
+ :source="remoteFieldDescription('options')"
582
+ block
583
+ class="prose prose-sm prose-zinc"
584
+ />
585
+ </template>
586
+ {{ remoteFieldTitle("options") }}
587
+ </FieldLabel>
588
+ <ExpressionEditor
589
+ v-model="optionsExprModel"
590
+ placeholder="如 json.data 或 [{value: 'a', label: 'A'}]"
591
+ result-type="dyn"
592
+ :extra-vars="JSON_VARS"
593
+ multiline
594
+ />
595
+ </Field>
596
+ <Field orientation="vertical">
597
+ <FieldLabel class="text-xs text-zinc-500">
598
+ <template
599
+ v-if="remoteFieldDescription('optionValue')"
600
+ #tooltip
601
+ >
602
+ <Markdown
603
+ :source="remoteFieldDescription('optionValue')"
604
+ block
605
+ class="prose prose-sm prose-zinc"
606
+ />
607
+ </template>
608
+ {{ remoteFieldTitle("optionValue") }}
609
+ </FieldLabel>
610
+ <ExpressionEditor
611
+ v-model="optionValueModel"
612
+ placeholder="如 option.value"
613
+ result-type="dyn"
614
+ :extra-vars="OPTION_VARS"
615
+ />
616
+ </Field>
617
+ <Field orientation="vertical">
618
+ <FieldLabel class="text-xs text-zinc-500">
619
+ <template
620
+ v-if="remoteFieldDescription('optionLabel')"
621
+ #tooltip
622
+ >
623
+ <Markdown
624
+ :source="remoteFieldDescription('optionLabel')"
625
+ block
626
+ class="prose prose-sm prose-zinc"
627
+ />
628
+ </template>
629
+ {{ remoteFieldTitle("optionLabel") }}
630
+ </FieldLabel>
631
+ <LocaleField
632
+ :model-value="optionLabelModel"
633
+ markdown
634
+ translate-hint="combobox option label"
635
+ @update:model-value="(v) => optionLabelModel = v"
636
+ />
637
+ </Field>
638
+ <Field orientation="vertical">
639
+ <FieldLabel class="text-xs text-zinc-500">
640
+ <template
641
+ v-if="remoteFieldDescription('optionKeywords')"
642
+ #tooltip
643
+ >
644
+ <Markdown
645
+ :source="remoteFieldDescription('optionKeywords')"
646
+ block
647
+ class="prose prose-sm prose-zinc"
648
+ />
649
+ </template>
650
+ {{ remoteFieldTitle("optionKeywords") }}
651
+ </FieldLabel>
652
+ <ExpressionEditor
653
+ v-model="optionKeywordsModel"
654
+ placeholder="如 [option.code, option.pinyin]"
655
+ result-type="list"
656
+ :extra-vars="OPTION_VARS"
657
+ />
658
+ </Field>
659
+ </div>
660
+ </TabsContent>
661
+ </Tabs>
662
+ </Field>
663
+
664
+ <div class="grid grid-cols-3 gap-3">
665
+ <Field orientation="vertical">
666
+ <FieldLabel class="text-xs text-zinc-500">
667
+ <template #tooltip>
668
+ <Markdown
669
+ :source="fieldDescription('hidden') ?? '\u8FD4\u56DE `true` \u65F6\u5B57\u6BB5\u5728\u6240\u6709\u5E03\u5C40\u4E2D\u90FD\u4E0D\u6E32\u67D3'"
670
+ block
671
+ class="prose prose-sm prose-zinc"
672
+ />
673
+ </template>
674
+ {{ fieldTitle("hidden") }}
675
+ </FieldLabel>
676
+ <ExpressionEditor
677
+ :model-value="value.hidden ?? ''"
678
+ placeholder="例:form.role == 'guest'"
679
+ result-type="bool"
680
+ class="min-h-10"
681
+ @update:model-value="(v) => value = { ...value, hidden: v.length > 0 ? v : void 0 }"
682
+ />
683
+ </Field>
684
+
685
+ <Field orientation="vertical">
686
+ <FieldLabel class="text-xs text-zinc-500">
687
+ <template #tooltip>
688
+ <Markdown
689
+ :source="fieldDescription('disabled') ?? '\u8FD4\u56DE `true` \u65F6\u4E0B\u62C9\u6846\u4ECD\u7136\u6E32\u67D3\u4F46\u4E0D\u53EF\u9009\u62E9'"
690
+ block
691
+ class="prose prose-sm prose-zinc"
692
+ />
693
+ </template>
694
+ {{ fieldTitle("disabled") }}
695
+ </FieldLabel>
696
+ <ExpressionEditor
697
+ :model-value="value.disabled ?? ''"
698
+ placeholder="例:form.status == 'locked'"
699
+ result-type="bool"
700
+ class="min-h-10"
701
+ @update:model-value="(v) => value = { ...value, disabled: v.length > 0 ? v : void 0 }"
702
+ />
703
+ </Field>
704
+
705
+ <Field orientation="vertical">
706
+ <FieldLabel class="text-xs text-zinc-500">
707
+ <template #tooltip>
708
+ <Markdown
709
+ :source="fieldDescription('readonly') ?? '\u8FD4\u56DE `true` \u65F6\u4EC5\u4EE5\u7EAF\u6587\u672C\u5C55\u793A\u5F53\u524D\u9009\u9879\u7684\u6807\u7B7E'"
710
+ block
711
+ class="prose prose-sm prose-zinc"
712
+ />
713
+ </template>
714
+ {{ fieldTitle("readonly") }}
715
+ </FieldLabel>
716
+ <ExpressionEditor
717
+ :model-value="value.readonly ?? ''"
718
+ placeholder="例:form.id != null"
719
+ result-type="bool"
720
+ class="min-h-10"
721
+ @update:model-value="(v) => value = { ...value, readonly: v.length > 0 ? v : void 0 }"
722
+ />
723
+ </Field>
724
+ </div>
725
+
726
+ <Field orientation="vertical">
727
+ <FieldLabel class="text-xs text-zinc-500">
728
+ <template #tooltip>
729
+ <Markdown
730
+ :source="fieldDescription('derived')"
731
+ block
732
+ class="prose prose-sm prose-zinc"
733
+ />
734
+ </template>
735
+ {{ fieldTitle("derived") }}
736
+ </FieldLabel>
737
+ <DerivedValueEditor
738
+ :model-value="value.derived"
739
+ result-type="dyn"
740
+ placeholder="例:form.category"
741
+ @update:model-value="(v) => value = { ...value, derived: v }"
742
+ />
743
+ </Field>
744
+ </div>
745
+ </template>