@shwfed/config 2.7.8 → 2.9.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 (153) hide show
  1. package/dist/mcp.mjs +97 -34
  2. package/dist/module.json +1 -1
  3. package/dist/preview/assets/{badge-KAEXz3VO.js → badge-Ddz0ExD-.js} +1 -1
  4. package/dist/preview/assets/{config-DbirfZyy.js → config---5_lEKG.js} +1 -1
  5. package/dist/preview/assets/{config-ZczGik30.js → config-5qIYVWZh.js} +1 -1
  6. package/dist/preview/assets/config-B8zbFg3y.js +1 -0
  7. package/dist/preview/assets/{config-DbfJWa8K.js → config-Bn619USg.js} +1 -1
  8. package/dist/preview/assets/{config-C-QRPeN1.js → config-CUeBTyLb.js} +1 -1
  9. package/dist/preview/assets/config-DN_3WauN.js +1 -0
  10. package/dist/preview/assets/config-U-3fWb-2.js +1 -0
  11. package/dist/preview/assets/config-q5VV9rp7.js +1 -0
  12. package/dist/preview/assets/config-vePqHFvZ.js +1 -0
  13. package/dist/preview/assets/{definition.vue_vue_type_script_setup_true_lang-CQ6MUPKO.js → definition.vue_vue_type_script_setup_true_lang-fQa65UMX.js} +1 -1
  14. package/dist/preview/assets/index-BKaqQGb-.js +688 -0
  15. package/dist/preview/assets/index-Bj8xIK5h.js +1 -0
  16. package/dist/preview/assets/index-BlHAyQdm.css +1 -0
  17. package/dist/preview/assets/{index-Bv_aA34a.js → index-CzWhSvDG.js} +1 -1
  18. package/dist/preview/assets/{item-SC0WQMVu.js → item-DHarupON.js} +1 -1
  19. package/dist/preview/assets/{runtime-DcStOiOi.js → runtime-560tuaHv.js} +1 -1
  20. package/dist/preview/assets/{runtime-Ckuz5Kxm.js → runtime-C2rQ3L3-.js} +1 -1
  21. package/dist/preview/assets/{runtime-BPOf7Yqz.js → runtime-CKghL8I_.js} +1 -1
  22. package/dist/preview/assets/runtime-CMsaNery.js +1 -0
  23. package/dist/preview/assets/runtime-CMuCGJZm.js +1 -0
  24. package/dist/preview/assets/{runtime-DO0anKbw.js → runtime-DOM_La4X.js} +1 -1
  25. package/dist/preview/assets/{runtime-EVgYW6_7.js → runtime-DQHb9t0r.js} +1 -1
  26. package/dist/preview/assets/{runtime-CnKlH0mi.js → runtime-Dgl3wVfD.js} +1 -1
  27. package/dist/preview/assets/{runtime-i32sR7d3.js → runtime-aLgWVLET.js} +1 -1
  28. package/dist/preview/index.html +2 -2
  29. package/dist/runtime/components/actions/buttons/2026-04-18/com.shwfed.actions.button.http.request.json/config.d.vue.ts +8 -0
  30. package/dist/runtime/components/actions/buttons/2026-04-18/com.shwfed.actions.button.http.request.json/config.vue +28 -0
  31. package/dist/runtime/components/actions/buttons/2026-04-18/com.shwfed.actions.button.http.request.json/config.vue.d.ts +8 -0
  32. package/dist/runtime/components/actions/buttons/2026-04-18/com.shwfed.actions.button.http.request.json/runtime.vue +17 -17
  33. package/dist/runtime/components/actions/buttons/2026-04-18/com.shwfed.actions.button.http.request.json/schema.d.ts +4 -0
  34. package/dist/runtime/components/actions/buttons/2026-04-18/com.shwfed.actions.button.http.request.json/schema.js +8 -0
  35. package/dist/runtime/components/actions/buttons/2026-04-18/com.shwfed.actions.button.http.request.json.confirm/config.d.vue.ts +8 -0
  36. package/dist/runtime/components/actions/buttons/2026-04-18/com.shwfed.actions.button.http.request.json.confirm/config.vue +25 -0
  37. package/dist/runtime/components/actions/buttons/2026-04-18/com.shwfed.actions.button.http.request.json.confirm/config.vue.d.ts +8 -0
  38. package/dist/runtime/components/actions/buttons/2026-04-18/com.shwfed.actions.button.http.request.json.confirm/runtime.vue +2 -7
  39. package/dist/runtime/components/actions/buttons/2026-04-18/com.shwfed.actions.button.http.request.json.confirm/schema.d.ts +4 -0
  40. package/dist/runtime/components/actions/buttons/2026-04-18/com.shwfed.actions.button.http.request.json.confirm/schema.js +8 -0
  41. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.table/config.d.vue.ts +2 -0
  42. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.table/config.vue.d.ts +2 -0
  43. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.table/runtime.d.vue.ts +2 -0
  44. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.table/runtime.vue.d.ts +2 -0
  45. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.table/schema.d.ts +2 -0
  46. package/dist/runtime/components/config/blocks/2026-06-02/com.shwfed.block.card/config.vue +2 -0
  47. package/dist/runtime/components/config/blocks/2026-06-02/com.shwfed.block.card/schema.d.ts +5 -0
  48. package/dist/runtime/components/config/blocks/2026-06-02/com.shwfed.block.card/schema.js +8 -3
  49. package/dist/runtime/components/form/fields/2026-04-22/com.shwfed.form.field.markdown/runtime.vue +12 -1
  50. package/dist/runtime/components/form/fields/2026-04-22/com.shwfed.form.field.markdown/schema.d.ts +8 -2
  51. package/dist/runtime/components/form/fields/2026-04-22/com.shwfed.form.field.markdown/schema.js +3 -3
  52. package/dist/runtime/components/form/fields/2026-04-22/com.shwfed.form.field.textarea/config.d.vue.ts +2 -2
  53. package/dist/runtime/components/form/fields/2026-04-22/com.shwfed.form.field.textarea/config.vue +15 -25
  54. package/dist/runtime/components/form/fields/2026-04-22/com.shwfed.form.field.textarea/config.vue.d.ts +2 -2
  55. package/dist/runtime/components/form/fields/2026-04-22/com.shwfed.form.field.textarea/runtime.vue +11 -2
  56. package/dist/runtime/components/form/fields/2026-04-22/com.shwfed.form.field.textarea/schema.d.ts +1 -1
  57. package/dist/runtime/components/form/fields/2026-04-22/com.shwfed.form.field.textarea/schema.js +4 -4
  58. package/dist/runtime/components/form/fields/2026-05-18/com.shwfed.form.field.table/config.d.vue.ts +2 -0
  59. package/dist/runtime/components/form/fields/2026-05-18/com.shwfed.form.field.table/config.vue.d.ts +2 -0
  60. package/dist/runtime/components/form/fields/2026-05-18/com.shwfed.form.field.table/schema.d.ts +2 -0
  61. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.multi/runtime.vue +13 -2
  62. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.multi/schema.d.ts +1 -0
  63. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.multi/schema.js +4 -1
  64. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.single/runtime.vue +10 -2
  65. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.single/schema.d.ts +1 -0
  66. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.single/schema.js +4 -1
  67. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.multi/runtime.vue +16 -0
  68. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.multi/schema.d.ts +1 -0
  69. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.multi/schema.js +4 -1
  70. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.single/runtime.vue +13 -5
  71. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.single/schema.d.ts +1 -0
  72. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.single/schema.js +4 -1
  73. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.multi/runtime.vue +25 -5
  74. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.multi/schema.d.ts +1 -0
  75. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.multi/schema.js +4 -1
  76. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.single/runtime.vue +18 -8
  77. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.single/schema.d.ts +1 -0
  78. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.single/schema.js +4 -1
  79. package/dist/runtime/components/form/index.vue +15 -3
  80. package/dist/runtime/components/form/schema.d.ts +4 -0
  81. package/dist/runtime/components/form/schema.js +1 -0
  82. package/dist/runtime/components/form/unit-config.vue +6 -1
  83. package/dist/runtime/components/form/utils/form-vars.js +4 -0
  84. package/dist/runtime/components/form/utils/resolve.d.ts +10 -0
  85. package/dist/runtime/components/table/columns/2026-05-24/com.shwfed.table.column.combobox-single.remote.options-remote/config.d.vue.ts +2 -2
  86. package/dist/runtime/components/table/columns/2026-05-24/com.shwfed.table.column.combobox-single.remote.options-remote/config.vue.d.ts +2 -2
  87. package/dist/runtime/components/table/columns/2026-05-24/com.shwfed.table.column.combobox-single.remote.options-static/config.d.vue.ts +2 -2
  88. package/dist/runtime/components/table/columns/2026-05-24/com.shwfed.table.column.combobox-single.remote.options-static/config.vue.d.ts +2 -2
  89. package/dist/runtime/components/table/columns/2026-05-25/com.shwfed.table.column.combobox-multi.remote.options-remote/config.d.vue.ts +2 -2
  90. package/dist/runtime/components/table/columns/2026-05-25/com.shwfed.table.column.combobox-multi.remote.options-remote/config.vue.d.ts +2 -2
  91. package/dist/runtime/components/table/columns/2026-05-25/com.shwfed.table.column.combobox-multi.remote.options-static/config.d.vue.ts +2 -2
  92. package/dist/runtime/components/table/columns/2026-05-25/com.shwfed.table.column.combobox-multi.remote.options-static/config.vue.d.ts +2 -2
  93. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-multi.remote/config.d.vue.ts +2 -2
  94. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-multi.remote/config.vue.d.ts +2 -2
  95. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-single.remote/config.d.vue.ts +2 -2
  96. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-single.remote/config.vue.d.ts +2 -2
  97. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-multi/config.d.vue.ts +2 -2
  98. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-multi/config.vue.d.ts +2 -2
  99. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-multi/runtime.vue +13 -2
  100. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-multi/schema.d.ts +1 -0
  101. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-multi/schema.js +4 -1
  102. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-single/config.d.vue.ts +2 -2
  103. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-single/config.vue.d.ts +2 -2
  104. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-single/runtime.vue +10 -2
  105. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-single/schema.d.ts +1 -0
  106. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-single/schema.js +4 -1
  107. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-multi/runtime.vue +16 -0
  108. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-multi/schema.d.ts +1 -0
  109. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-multi/schema.js +3 -1
  110. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-single/runtime.vue +13 -5
  111. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-single/schema.d.ts +1 -0
  112. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-single/schema.js +3 -1
  113. package/dist/runtime/components/table/config.vue +35 -1
  114. package/dist/runtime/components/table/index.d.vue.ts +2 -0
  115. package/dist/runtime/components/table/index.vue +8 -0
  116. package/dist/runtime/components/table/index.vue.d.ts +2 -0
  117. package/dist/runtime/components/table/row-provider.vue +8 -0
  118. package/dist/runtime/components/table/schema.d.ts +4 -0
  119. package/dist/runtime/components/table/schema.js +4 -0
  120. package/dist/runtime/components/table/utils/resolve.d.ts +7 -0
  121. package/dist/runtime/components/table/utils/shared.js +4 -0
  122. package/dist/runtime/components/ui/expression-editor/CodeMirrorInput.d.vue.ts +1 -0
  123. package/dist/runtime/components/ui/expression-editor/CodeMirrorInput.vue +9 -1
  124. package/dist/runtime/components/ui/expression-editor/CodeMirrorInput.vue.d.ts +1 -0
  125. package/dist/runtime/components/ui/expression-editor/ExpressionEditor.d.vue.ts +2 -2
  126. package/dist/runtime/components/ui/expression-editor/ExpressionEditor.vue +33 -4
  127. package/dist/runtime/components/ui/expression-editor/ExpressionEditor.vue.d.ts +2 -2
  128. package/dist/runtime/components/ui/expression-editor/picker-entries.d.ts +3 -2
  129. package/dist/runtime/components/ui/expression-editor/picker-entries.js +14 -3
  130. package/dist/runtime/components/ui/expression-editor/selection-chip-extension.d.ts +4 -0
  131. package/dist/runtime/components/ui/expression-editor/selection-chip-extension.js +119 -0
  132. package/dist/runtime/components/ui/expression-editor/selection-refs.d.ts +8 -0
  133. package/dist/runtime/components/ui/expression-editor/selection-refs.js +29 -0
  134. package/dist/runtime/share/event-bus.d.ts +12 -12
  135. package/dist/runtime/share/use-persisted-query.d.ts +21 -0
  136. package/dist/runtime/share/use-persisted-query.js +33 -0
  137. package/dist/runtime/utils/cel-context.d.ts +22 -0
  138. package/dist/runtime/utils/cel-context.js +8 -0
  139. package/dist/runtime/utils/selections-registry.d.ts +77 -0
  140. package/dist/runtime/utils/selections-registry.js +49 -0
  141. package/package.json +1 -1
  142. package/dist/preview/assets/config-BXx5syNf.js +0 -1
  143. package/dist/preview/assets/config-Bb9Yeh33.js +0 -1
  144. package/dist/preview/assets/config-CkKx7sVR.js +0 -1
  145. package/dist/preview/assets/config-CtbYlZCL.js +0 -1
  146. package/dist/preview/assets/config-DPlbFBRi.js +0 -1
  147. package/dist/preview/assets/index-C9P-6gZd.css +0 -1
  148. package/dist/preview/assets/index-CJFU9znN.js +0 -1
  149. package/dist/preview/assets/index-DUOkekYu.js +0 -680
  150. package/dist/preview/assets/runtime-CC2caFS9.js +0 -1
  151. package/dist/preview/assets/runtime-CLaRFZzt.js +0 -1
  152. package/dist/runtime/share/form-validate.d.ts +0 -18
  153. package/dist/runtime/share/form-validate.js +0 -8
@@ -6,7 +6,7 @@ import { cel as _rawCel } from "../../../../../utils/cel";
6
6
  import { celBindings, injectCELContext } from "../../../../../utils/cel-context";
7
7
  import { getLocalizedText } from "../../../../../share/locale";
8
8
  import { Field, FieldLabel, FieldMessages } from "../../../../ui/field";
9
- import { InputGroup, InputGroupTextarea } from "../../../../ui/input-group";
9
+ import { InputGroup, InputGroupAddon, InputGroupText, InputGroupTextarea } from "../../../../ui/input-group";
10
10
  import { Markdown } from "../../../../ui/markdown";
11
11
  import { DEFAULT_FIELD_ORIENTATION } from "../../../utils/common";
12
12
  import { useFieldValue } from "../../../utils/field-value";
@@ -29,6 +29,7 @@ const placeholderText = computed(
29
29
  const tooltipText = computed(
30
30
  () => props.config.tooltip ? getLocalizedText(props.config.tooltip, locale.value) : void 0
31
31
  );
32
+ const maxLength = computed(() => props.config.maxLength);
32
33
  function evalBool(expression, label) {
33
34
  if (!expression) return false;
34
35
  try {
@@ -94,9 +95,17 @@ const { isRequired, errors, warnings, visible } = useFieldValidation({
94
95
  v-model="draft"
95
96
  :placeholder="placeholderText"
96
97
  :disabled="isDisabled"
97
- :rows="config.rows"
98
+ :maxlength="maxLength"
98
99
  @blur="commit"
99
100
  />
101
+ <InputGroupAddon
102
+ v-if="maxLength != null"
103
+ align="block-end"
104
+ >
105
+ <InputGroupText class="tabular-nums">
106
+ {{ draft.length }} / {{ maxLength }}
107
+ </InputGroupText>
108
+ </InputGroupAddon>
100
109
  </InputGroup>
101
110
  <FieldMessages
102
111
  v-if="visible"
@@ -40,10 +40,10 @@ export declare function schema(configure: (env: Environment) => void): Schema.St
40
40
  message: Schema.SchemaClass<string, string, never>;
41
41
  }>]>>;
42
42
  orientation: Schema.optional<Schema.Literal<["vertical", "floating"]>>;
43
- rows: Schema.optional<Schema.refine<number, Schema.filter<typeof Schema.Number>>>;
44
43
  binding: Schema.optional<Schema.refine<string, typeof Schema.String>>;
45
44
  disabled: Schema.optional<Schema.Schema<string, string, never>>;
46
45
  readonly: Schema.optional<Schema.Schema<string, string, never>>;
46
+ maxLength: Schema.optional<Schema.refine<number, Schema.filter<typeof Schema.Number>>>;
47
47
  derived: Schema.optional<Schema.Struct<{
48
48
  mode: Schema.Literal<["formula", "prefill"]>;
49
49
  expression: Schema.Schema<string, string, never>;
@@ -29,10 +29,6 @@ export function schema(configure) {
29
29
  description: "\u9F20\u6807\u60AC\u505C\u5728\u6807\u7B7E\u4E0A\u65F6\u5C55\u793A\u7684\u8BF4\u660E"
30
30
  })),
31
31
  orientation: Schema.optional(FieldOrientationSchema),
32
- rows: Schema.optional(Schema.Number.pipe(Schema.int(), Schema.positive()).annotations({
33
- title: "\u884C\u6570",
34
- description: "\u8F93\u5165\u6846\u7684\u521D\u59CB\u53EF\u89C1\u884C\u6570\uFF1B\u7559\u7A7A\u4F7F\u7528\u9ED8\u8BA4\u9AD8\u5EA6"
35
- })),
36
32
  binding: Schema.optional(Schema.String.pipe(Schema.minLength(1)).annotations({
37
33
  title: "\u7ED1\u5B9A\u8DEF\u5F84",
38
34
  description: "\u5199\u5165\u8868\u5355\u72B6\u6001\u7684 `dot-prop` \u8DEF\u5F84\uFF0C\u4F8B\u5982 `user.bio`\uFF1B\u7559\u7A7A\u5219\u4E3A\u975E\u53D7\u63A7\u5B57\u6BB5\uFF0C\u4E0D\u5199\u5165\u8868\u5355\u72B6\u6001"
@@ -45,6 +41,10 @@ export function schema(configure) {
45
41
  title: "\u53EA\u8BFB\u6761\u4EF6",
46
42
  description: "\u8FD4\u56DE `true` \u65F6\u4EC5\u4EE5\u7EAF\u6587\u672C\u5C55\u793A\u5F53\u524D\u503C"
47
43
  })),
44
+ maxLength: Schema.optional(Schema.Number.pipe(Schema.int(), Schema.positive()).annotations({
45
+ title: "\u5B57\u6570\u9650\u5236",
46
+ description: "\u5141\u8BB8\u8F93\u5165\u7684\u6700\u5927\u5B57\u7B26\u6570\uFF1B\u8FBE\u5230\u4E0A\u9650\u540E\u65E0\u6CD5\u7EE7\u7EED\u8F93\u5165\uFF0C\u5E76\u5728\u53F3\u4E0B\u89D2\u5C55\u793A\u5B57\u6570\u8BA1\u6570"
47
+ })),
48
48
  derived: derivedField(configure, "string")
49
49
  }).annotations({
50
50
  title: "TextareaField",
@@ -30,6 +30,7 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
30
30
  cellStyle?: string;
31
31
  style?: string;
32
32
  pagination?: import("effect/Schema").Schema.Type<typeof import("../../../../table/schema.js").Pagination>;
33
+ persistQuery?: boolean;
33
34
  initialState?: import("effect/Schema").Schema.Type<import("effect/Schema").Struct<{
34
35
  columnVisibility: import("effect/Schema").optional<import("effect/Schema").Record$<typeof import("effect/Schema").String, typeof import("effect/Schema").Boolean>>;
35
36
  columnOrder: import("effect/Schema").optional<import("effect/Schema").Array$<typeof import("effect/Schema").String>>;
@@ -105,6 +106,7 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
105
106
  cellStyle?: string;
106
107
  style?: string;
107
108
  pagination?: import("effect/Schema").Schema.Type<typeof import("../../../../table/schema.js").Pagination>;
109
+ persistQuery?: boolean;
108
110
  initialState?: import("effect/Schema").Schema.Type<import("effect/Schema").Struct<{
109
111
  columnVisibility: import("effect/Schema").optional<import("effect/Schema").Record$<typeof import("effect/Schema").String, typeof import("effect/Schema").Boolean>>;
110
112
  columnOrder: import("effect/Schema").optional<import("effect/Schema").Array$<typeof import("effect/Schema").String>>;
@@ -30,6 +30,7 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
30
30
  cellStyle?: string;
31
31
  style?: string;
32
32
  pagination?: import("effect/Schema").Schema.Type<typeof import("../../../../table/schema.js").Pagination>;
33
+ persistQuery?: boolean;
33
34
  initialState?: import("effect/Schema").Schema.Type<import("effect/Schema").Struct<{
34
35
  columnVisibility: import("effect/Schema").optional<import("effect/Schema").Record$<typeof import("effect/Schema").String, typeof import("effect/Schema").Boolean>>;
35
36
  columnOrder: import("effect/Schema").optional<import("effect/Schema").Array$<typeof import("effect/Schema").String>>;
@@ -105,6 +106,7 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
105
106
  cellStyle?: string;
106
107
  style?: string;
107
108
  pagination?: import("effect/Schema").Schema.Type<typeof import("../../../../table/schema.js").Pagination>;
109
+ persistQuery?: boolean;
108
110
  initialState?: import("effect/Schema").Schema.Type<import("effect/Schema").Struct<{
109
111
  columnVisibility: import("effect/Schema").optional<import("effect/Schema").Record$<typeof import("effect/Schema").String, typeof import("effect/Schema").Boolean>>;
110
112
  columnOrder: import("effect/Schema").optional<import("effect/Schema").Array$<typeof import("effect/Schema").String>>;
@@ -47,6 +47,7 @@ export declare function schema(configure: (env: Environment) => void): Schema.St
47
47
  cellStyle?: string;
48
48
  style?: string;
49
49
  pagination?: Schema.Schema.Type<typeof import("../../../../table/schema.js").Pagination>;
50
+ persistQuery?: boolean;
50
51
  initialState?: Schema.Schema.Type<Schema.Struct<{
51
52
  columnVisibility: Schema.optional<Schema.Record$<typeof Schema.String, typeof Schema.Boolean>>;
52
53
  columnOrder: Schema.optional<Schema.Array$<typeof Schema.String>>;
@@ -82,6 +83,7 @@ export declare function schema(configure: (env: Environment) => void): Schema.St
82
83
  cellStyle?: string;
83
84
  style?: string;
84
85
  pagination?: Schema.Schema.Type<typeof import("../../../../table/schema.js").Pagination>;
86
+ persistQuery?: boolean;
85
87
  initialState?: Schema.Schema.Type<Schema.Struct<{
86
88
  columnVisibility: Schema.optional<Schema.Record$<typeof Schema.String, typeof Schema.Boolean>>;
87
89
  columnOrder: Schema.optional<Schema.Array$<typeof Schema.String>>;
@@ -8,6 +8,7 @@ import { useI18n } from "vue-i18n";
8
8
  import { asRequest, fetchJsonOption } from "../../../../../share/request";
9
9
  import { cel as _rawCel } from "../../../../../utils/cel";
10
10
  import { celBindings, injectCELContext } from "../../../../../utils/cel-context";
11
+ import { publishSelection } from "../../../../../utils/selections-registry";
11
12
  import { interpolateMarkdown } from "../../../../table/utils/runtime";
12
13
  import { getLocalizedText } from "../../../../../share/locale";
13
14
  import {
@@ -178,7 +179,8 @@ const entries = computed(() => {
178
179
  key: item.id,
179
180
  value: item.value.value,
180
181
  label: labelTpl ? safeInterpolate(labelTpl, ctx) : "",
181
- keywords: kw.length > 0 ? kw : void 0
182
+ keywords: kw.length > 0 ? kw : void 0,
183
+ raw: item
182
184
  };
183
185
  });
184
186
  }
@@ -194,7 +196,8 @@ const entries = computed(() => {
194
196
  key: String(idx),
195
197
  value: remoteValueOf(option),
196
198
  label: remoteLabelOf(option),
197
- keywords: remoteKeywordsOf(option)
199
+ keywords: remoteKeywordsOf(option),
200
+ raw: option
198
201
  }));
199
202
  });
200
203
  const uncontrolled = ref([]);
@@ -243,6 +246,14 @@ const selectedEntries = computed(() => {
243
246
  });
244
247
  const selectedKeys = computed(() => selectedEntries.value.map((e) => e.key));
245
248
  const selectedKeySet = computed(() => new Set(selectedKeys.value));
249
+ publishSelection(
250
+ props.fieldId,
251
+ () => selectedEntries.value.length > 0 ? selectedEntries.value : void 0,
252
+ {
253
+ identity: (list) => list.map((e) => e.key).join("\0"),
254
+ raw: (list) => list.map((e) => e.raw)
255
+ }
256
+ );
246
257
  const triggerLabel = computed(() => {
247
258
  const arr = selectedEntries.value;
248
259
  if (arr.length === 0) return "";
@@ -16,6 +16,7 @@ export declare const metadata: {
16
16
  readonly min: 2;
17
17
  readonly max: 2;
18
18
  };
19
+ readonly selection: true;
19
20
  };
20
21
  export declare function itemSchema(configure: (env: Environment) => void): Schema.Struct<{
21
22
  id: Schema.refine<string, typeof Schema.String>;
@@ -8,7 +8,10 @@ export const metadata = {
8
8
  name: "\u4E0B\u62C9\u591A\u9009",
9
9
  icon: "fluent:chevron-down-20-regular",
10
10
  w: { initial: 8, min: 4, max: Infinity },
11
- h: { initial: 2, min: 2, max: 2 }
11
+ h: { initial: 2, min: 2, max: 2 },
12
+ // Publishes its resolved options (array, in selection order) to the
13
+ // `selections` registry (runtime.vue), readable via `selections["<id>"]`.
14
+ selection: true
12
15
  };
13
16
  const isListType = (actual) => actual === "dyn" || actual.startsWith("list") || actual.startsWith("optional");
14
17
  function configureWithOption(configure) {
@@ -8,6 +8,7 @@ import { useI18n } from "vue-i18n";
8
8
  import { asRequest, fetchJsonOption } from "../../../../../share/request";
9
9
  import { cel as _rawCel } from "../../../../../utils/cel";
10
10
  import { celBindings, injectCELContext } from "../../../../../utils/cel-context";
11
+ import { publishSelection } from "../../../../../utils/selections-registry";
11
12
  import { interpolateMarkdown } from "../../../../table/utils/runtime";
12
13
  import { getLocalizedText } from "../../../../../share/locale";
13
14
  import {
@@ -180,7 +181,8 @@ const entries = computed(() => {
180
181
  value: item.value.value,
181
182
  label: labelTpl ? safeInterpolate(labelTpl, ctx) : "",
182
183
  tooltip: tooltipTpl ? safeInterpolate(tooltipTpl, ctx) : void 0,
183
- keywords: kw.length > 0 ? kw : void 0
184
+ keywords: kw.length > 0 ? kw : void 0,
185
+ raw: item
184
186
  };
185
187
  });
186
188
  }
@@ -196,7 +198,8 @@ const entries = computed(() => {
196
198
  key: String(idx),
197
199
  value: remoteValueOf(option),
198
200
  label: remoteLabelOf(option),
199
- keywords: remoteKeywordsOf(option)
201
+ keywords: remoteKeywordsOf(option),
202
+ raw: option
200
203
  }));
201
204
  });
202
205
  const uncontrolled = ref(void 0);
@@ -246,6 +249,11 @@ const selectedEntry = computed(
246
249
  );
247
250
  const selectedKey = computed(() => selectedEntry.value?.key);
248
251
  const selectedLabel = computed(() => selectedEntry.value?.label ?? "");
252
+ publishSelection(
253
+ props.fieldId,
254
+ () => selectedEntry.value,
255
+ { identity: (entry) => entry.key, raw: (entry) => entry.raw }
256
+ );
249
257
  const open = ref(false);
250
258
  function handleSelect(key) {
251
259
  if (typeof key !== "string") return;
@@ -16,6 +16,7 @@ export declare const metadata: {
16
16
  readonly min: 2;
17
17
  readonly max: 2;
18
18
  };
19
+ readonly selection: true;
19
20
  };
20
21
  export declare function itemSchema(configure: (env: Environment) => void): Schema.Struct<{
21
22
  id: Schema.refine<string, typeof Schema.String>;
@@ -8,7 +8,10 @@ export const metadata = {
8
8
  name: "\u4E0B\u62C9\u5355\u9009",
9
9
  icon: "fluent:chevron-down-20-regular",
10
10
  w: { initial: 8, min: 4, max: Infinity },
11
- h: { initial: 2, min: 2, max: 2 }
11
+ h: { initial: 2, min: 2, max: 2 },
12
+ // Publishes its resolved option to the `selections` registry (runtime.vue), so
13
+ // a sibling expression can read the full chosen record via `selections["<id>"]`.
14
+ selection: true
12
15
  };
13
16
  const isListType = (actual) => actual === "dyn" || actual.startsWith("list") || actual.startsWith("optional");
14
17
  function configureWithOption(configure) {
@@ -7,6 +7,7 @@ import { useI18n } from "vue-i18n";
7
7
  import { fetchJsonOption } from "../../../../../share/request";
8
8
  import { cel as _rawCel } from "../../../../../utils/cel";
9
9
  import { celBindings, injectCELContext } from "../../../../../utils/cel-context";
10
+ import { publishSelection } from "../../../../../utils/selections-registry";
10
11
  import { getLocalizedText } from "../../../../../share/locale";
11
12
  import { Field, FieldLabel, FieldMessages } from "../../../../ui/field";
12
13
  import { InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput } from "../../../../ui/input-group";
@@ -240,6 +241,21 @@ const triggerLabel = computed(() => {
240
241
  if (arr.length === 1) return head;
241
242
  return `${head} + ${arr.length - 1}`;
242
243
  });
244
+ const selectedLeaves = computed(
245
+ () => model.value.map((k) => {
246
+ const path = findWrappedPath(roots.value, k);
247
+ if (!path || path.length === 0) return void 0;
248
+ return path[path.length - 1];
249
+ }).filter((node) => node !== void 0)
250
+ );
251
+ publishSelection(
252
+ props.fieldId,
253
+ () => selectedLeaves.value.length > 0 ? selectedLeaves.value : void 0,
254
+ {
255
+ identity: (list) => list.map((w) => w.key).join(" "),
256
+ raw: (list) => list.map((w) => w.raw)
257
+ }
258
+ );
243
259
  const initialExpanded = computed(() => {
244
260
  if (!props.config.expandAll) return [];
245
261
  const out = [];
@@ -16,6 +16,7 @@ export declare const metadata: {
16
16
  readonly min: 2;
17
17
  readonly max: 2;
18
18
  };
19
+ readonly selection: true;
19
20
  };
20
21
  export declare function schema(configure: (env: Environment) => void): Schema.Struct<{
21
22
  label: Schema.optional<Schema.TupleType<readonly [Schema.Struct<{
@@ -9,7 +9,10 @@ export const metadata = {
9
9
  name: "\u4E0B\u62C9\u6811\uFF08\u591A\u9009\uFF09",
10
10
  icon: "fluent:tree-evergreen-20-regular",
11
11
  w: { initial: 8, min: 4, max: Infinity },
12
- h: { initial: 2, min: 2, max: 2 }
12
+ h: { initial: 2, min: 2, max: 2 },
13
+ // Publishes its resolved nodes (array, in selection order) to the `selections`
14
+ // registry (runtime.vue), readable via `selections["<id>"]`.
15
+ selection: true
13
16
  };
14
17
  const NODE_VAR = {
15
18
  type: "dyn",
@@ -7,6 +7,7 @@ import { useI18n } from "vue-i18n";
7
7
  import { fetchJsonOption } from "../../../../../share/request";
8
8
  import { cel as _rawCel } from "../../../../../utils/cel";
9
9
  import { celBindings, injectCELContext } from "../../../../../utils/cel-context";
10
+ import { publishSelection } from "../../../../../utils/selections-registry";
10
11
  import { getLocalizedText } from "../../../../../share/locale";
11
12
  import { Field, FieldLabel, FieldMessages } from "../../../../ui/field";
12
13
  import { InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput } from "../../../../ui/input-group";
@@ -227,14 +228,21 @@ const roots = computed(
227
228
  nodeChildren: nodeChildrenList
228
229
  })
229
230
  );
230
- const triggerLabel = computed(() => {
231
+ const selectedWrapped = computed(() => {
231
232
  const k = model.value;
232
- if (!k) return "";
233
+ if (!k) return void 0;
233
234
  const path = findWrappedPath(roots.value, k);
234
- if (!path || path.length === 0) return "";
235
- const leaf = path[path.length - 1];
236
- return wrappedLabelText(leaf);
235
+ if (!path || path.length === 0) return void 0;
236
+ return path[path.length - 1];
237
237
  });
238
+ const triggerLabel = computed(
239
+ () => selectedWrapped.value ? wrappedLabelText(selectedWrapped.value) : ""
240
+ );
241
+ publishSelection(
242
+ props.fieldId,
243
+ () => selectedWrapped.value,
244
+ { identity: (w) => w.key, raw: (w) => w.raw }
245
+ );
238
246
  const initialExpanded = computed(() => {
239
247
  if (!props.config.expandAll) return [];
240
248
  const out = [];
@@ -16,6 +16,7 @@ export declare const metadata: {
16
16
  readonly min: 2;
17
17
  readonly max: 2;
18
18
  };
19
+ readonly selection: true;
19
20
  };
20
21
  export declare function schema(configure: (env: Environment) => void): Schema.Struct<{
21
22
  label: Schema.optional<Schema.TupleType<readonly [Schema.Struct<{
@@ -9,7 +9,10 @@ export const metadata = {
9
9
  name: "\u4E0B\u62C9\u6811\uFF08\u5355\u9009\uFF09",
10
10
  icon: "fluent:tree-evergreen-20-regular",
11
11
  w: { initial: 8, min: 4, max: Infinity },
12
- h: { initial: 2, min: 2, max: 2 }
12
+ h: { initial: 2, min: 2, max: 2 },
13
+ // Publishes its resolved node (the backend record) to the `selections`
14
+ // registry (runtime.vue), readable via `selections["<id>"]`.
15
+ selection: true
13
16
  };
14
17
  const NODE_VAR = {
15
18
  type: "dyn",
@@ -7,6 +7,7 @@ import { useI18n } from "vue-i18n";
7
7
  import { fetchJsonOption } from "../../../../../share/request";
8
8
  import { cel as _rawCel } from "../../../../../utils/cel";
9
9
  import { celBindings, injectCELContext } from "../../../../../utils/cel-context";
10
+ import { publishSelection } from "../../../../../utils/selections-registry";
10
11
  import { getLocalizedText } from "../../../../../share/locale";
11
12
  import { Checkbox } from "../../../../ui/checkbox";
12
13
  import { Field, FieldLabel, FieldMessages } from "../../../../ui/field";
@@ -262,20 +263,39 @@ const filterLabelText = computed(() => {
262
263
  const localized = props.config.filter?.label ? getLocalizedText(props.config.filter.label, locale.value) : void 0;
263
264
  return localized && localized.length > 0 ? localized : t("tree-multi-search-label");
264
265
  });
265
- const readonlyText = computed(() => {
266
+ const resolvedByKey = computed(() => {
266
267
  const selected = new Set(model.value);
267
- const empty = t("tree-multi-readonly-empty");
268
- if (selected.size === 0) return empty;
269
268
  const found = /* @__PURE__ */ new Map();
269
+ if (selected.size === 0) return found;
270
270
  const stack = [...roots.value];
271
271
  while (stack.length) {
272
272
  const n = stack.pop();
273
273
  const k = getKey(n);
274
- if (selected.has(k)) found.set(k, nodeLabelText(n));
274
+ if (selected.has(k)) found.set(k, n);
275
275
  const kids = getChildren(n);
276
276
  if (kids && kids.length) stack.push(...kids);
277
277
  }
278
- const labels = model.value.map((id) => found.get(id) ?? id).filter((l) => l.length > 0);
278
+ return found;
279
+ });
280
+ const selectedNodes = computed(
281
+ () => model.value.map((id) => resolvedByKey.value.get(id)).filter((n) => n !== void 0)
282
+ );
283
+ publishSelection(
284
+ props.fieldId,
285
+ () => selectedNodes.value.length > 0 ? selectedNodes.value : void 0,
286
+ {
287
+ identity: (list) => list.map((n) => getKey(n)).join(" "),
288
+ raw: (list) => list
289
+ }
290
+ );
291
+ const readonlyText = computed(() => {
292
+ const empty = t("tree-multi-readonly-empty");
293
+ if (model.value.length === 0) return empty;
294
+ const found = resolvedByKey.value;
295
+ const labels = model.value.map((id) => {
296
+ const n = found.get(id);
297
+ return n !== void 0 ? nodeLabelText(n) : id;
298
+ }).filter((l) => l.length > 0);
279
299
  return labels.length > 0 ? labels.join(t("tree-multi-readonly-separator")) : empty;
280
300
  });
281
301
  </script>
@@ -17,6 +17,7 @@ export declare const metadata: {
17
17
  readonly max: number;
18
18
  readonly grow: true;
19
19
  };
20
+ readonly selection: true;
20
21
  };
21
22
  export declare function schema(configure: (env: Environment) => void): Schema.Struct<{
22
23
  label: Schema.optional<Schema.TupleType<readonly [Schema.Struct<{
@@ -9,7 +9,10 @@ export const metadata = {
9
9
  name: "\u6811\uFF08\u591A\u9009\uFF09",
10
10
  icon: "fluent:tree-evergreen-20-regular",
11
11
  w: { initial: 8, min: 4, max: Infinity },
12
- h: { initial: 8, min: 4, max: Infinity, grow: true }
12
+ h: { initial: 8, min: 4, max: Infinity, grow: true },
13
+ // Publishes its resolved nodes (array, in selection order) to the `selections`
14
+ // registry (runtime.vue), readable via `selections["<id>"]`.
15
+ selection: true
13
16
  };
14
17
  export function schema(configure) {
15
18
  const CelBool = Expression({ configure, resultType: "bool" });
@@ -7,6 +7,7 @@ import { useI18n } from "vue-i18n";
7
7
  import { fetchJsonOption } from "../../../../../share/request";
8
8
  import { cel as _rawCel } from "../../../../../utils/cel";
9
9
  import { celBindings, injectCELContext } from "../../../../../utils/cel-context";
10
+ import { publishSelection } from "../../../../../utils/selections-registry";
10
11
  import { getLocalizedText } from "../../../../../share/locale";
11
12
  import { Field, FieldLabel, FieldMessages } from "../../../../ui/field";
12
13
  import { InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput } from "../../../../ui/input-group";
@@ -258,21 +259,30 @@ const filterLabelText = computed(() => {
258
259
  const localized = props.config.filter?.label ? getLocalizedText(props.config.filter.label, locale.value) : void 0;
259
260
  return localized && localized.length > 0 ? localized : t("tree-single-search-label");
260
261
  });
261
- const readonlyText = computed(() => {
262
+ const selectedNode = computed(() => {
262
263
  const selected = model.value;
263
- const empty = t("tree-single-readonly-empty");
264
- if (selected == null) return empty;
264
+ if (selected == null) return void 0;
265
265
  const stack = [...roots.value];
266
266
  while (stack.length) {
267
267
  const n = stack.pop();
268
- if (getKey(n) === selected) {
269
- const label = nodeLabelText(n);
270
- return label.length > 0 ? label : selected;
271
- }
268
+ if (getKey(n) === selected) return n;
272
269
  const kids = getChildren(n);
273
270
  if (kids && kids.length) stack.push(...kids);
274
271
  }
275
- return selected;
272
+ return void 0;
273
+ });
274
+ publishSelection(
275
+ props.fieldId,
276
+ () => selectedNode.value,
277
+ { identity: (node) => getKey(node), raw: (node) => node }
278
+ );
279
+ const readonlyText = computed(() => {
280
+ const selected = model.value;
281
+ if (selected == null) return t("tree-single-readonly-empty");
282
+ const n = selectedNode.value;
283
+ if (n === void 0) return selected;
284
+ const label = nodeLabelText(n);
285
+ return label.length > 0 ? label : selected;
276
286
  });
277
287
  </script>
278
288
 
@@ -16,6 +16,7 @@ export declare const metadata: {
16
16
  readonly max: number;
17
17
  readonly grow: true;
18
18
  };
19
+ readonly selection: true;
19
20
  };
20
21
  export declare function schema(configure: (env: Environment) => void): Schema.Struct<{
21
22
  label: Schema.optional<Schema.TupleType<readonly [Schema.Struct<{
@@ -9,7 +9,10 @@ export const metadata = {
9
9
  name: "\u6811\uFF08\u5355\u9009\uFF09",
10
10
  icon: "fluent:tree-evergreen-20-regular",
11
11
  w: { initial: 8, min: 4, max: Infinity },
12
- h: { initial: 8, min: 4, max: Infinity, grow: true }
12
+ h: { initial: 8, min: 4, max: Infinity, grow: true },
13
+ // Publishes its resolved node (the backend record) to the `selections`
14
+ // registry (runtime.vue), readable via `selections["<id>"]`.
15
+ selection: true
13
16
  };
14
17
  export function schema(configure) {
15
18
  const CelBool = Expression({ configure, resultType: "bool" });
@@ -15,10 +15,10 @@ import { provideCommitBus } from "./utils/commit-bus";
15
15
  import { provideDerivedQuiescence, useDerived } from "./utils/derived";
16
16
  import { useFormHistory } from "./utils/history";
17
17
  import { evaluateInitial } from "./utils/initial";
18
- import { provideFormValidate } from "../../share/form-validate";
19
18
  import { provideEventTarget } from "../../share/event-bus";
20
19
  import { provideFormReadonly } from "./utils/readonly";
21
20
  import { provideFormState } from "./utils/state";
21
+ import { provideSelectionsRegistry } from "../../utils/selections-registry";
22
22
  import { provideValidation } from "./utils/validation";
23
23
  defineOptions({ name: "ShwfedForm" });
24
24
  const state = defineModel({ type: Object, ...{ default: () => ({}) } });
@@ -29,9 +29,15 @@ const props = defineProps({
29
29
  const configure = props.configure ?? (() => {
30
30
  });
31
31
  void configure;
32
+ const selections = provideSelectionsRegistry();
32
33
  provideCELContext(buildFormRuntimeScope({
33
34
  form: () => state.value ?? {},
34
- now: () => new TZDate()
35
+ now: () => new TZDate(),
36
+ // `formHistory` is created further down; these thunks are stored now and
37
+ // only called at eval time (long after setup), so reading it here is safe.
38
+ undoable: () => formHistory.canUndo.value,
39
+ redoable: () => formHistory.canRedo.value,
40
+ selections: () => selections.entries.value
35
41
  }));
36
42
  const inherited = injectCELContext();
37
43
  const $cel = (expression, context) => _rawCel(expression, { ...celBindings(inherited), ...context });
@@ -77,10 +83,16 @@ const validation = provideValidation({
77
83
  seeded,
78
84
  settled: quiescence.settled
79
85
  });
80
- provideFormValidate(validation.validate);
81
86
  const formHistory = useFormHistory(state, { quiescence, seeded, dirty: formState.dirty });
87
+ class FormInvalid {
88
+ _tag = "FormInvalid";
89
+ }
82
90
  const formInstanceId = config.value?.id ?? crypto.randomUUID();
83
91
  provideEventTarget(formInstanceId, {
92
+ "validate": () => Effect.gen(function* () {
93
+ const valid = yield* Effect.promise(() => validation.validate());
94
+ if (!valid) yield* Effect.die(new FormInvalid());
95
+ }),
84
96
  "undo": () => Effect.sync(formHistory.undo),
85
97
  "redo": () => Effect.sync(formHistory.redo),
86
98
  "reset-to-initial": () => Effect.sync(formHistory.reset)
@@ -11,6 +11,10 @@ export declare const metadata: {
11
11
  readonly name: "表单";
12
12
  readonly icon: "fluent:form-20-regular";
13
13
  readonly operations: readonly [{
14
+ readonly id: "validate";
15
+ readonly name: "校验";
16
+ readonly icon: "fluent:checkmark-circle-20-regular";
17
+ }, {
14
18
  readonly id: "undo";
15
19
  readonly name: "撤销";
16
20
  readonly icon: "fluent:arrow-undo-20-regular";
@@ -20,6 +20,7 @@ export const metadata = {
20
20
  name: "\u8868\u5355",
21
21
  icon: "fluent:form-20-regular",
22
22
  operations: [
23
+ { id: "validate", name: "\u6821\u9A8C", icon: "fluent:checkmark-circle-20-regular" },
23
24
  { id: "undo", name: "\u64A4\u9500", icon: "fluent:arrow-undo-20-regular" },
24
25
  { id: "redo", name: "\u91CD\u505A", icon: "fluent:arrow-redo-20-regular" },
25
26
  { id: "reset-to-initial", name: "\u91CD\u7F6E\u4E3A\u521D\u59CB\u503C", icon: "fluent:arrow-reset-20-regular" }
@@ -7,7 +7,8 @@ import { toast } from "vue-sonner";
7
7
  import {
8
8
  celBindings,
9
9
  injectCELContext,
10
- provideCELContext
10
+ provideCELContext,
11
+ provideSelectionRoster
11
12
  } from "../../utils/cel-context";
12
13
  import { findFreePlacement, normalizeLayoutSet, placeGroupAt } from "../../share/layout";
13
14
  import { readClip, reidFragment, writeClip } from "../../share/clipboard";
@@ -45,6 +46,10 @@ const breadcrumbExt = inject(BREADCRUMB_EXTENSION_KEY, null);
45
46
  const fullPane = ref(false);
46
47
  provide(FORM_FIELD_LAYOUT_KEY, { fullPane });
47
48
  provideCELContext(props.fieldCelScope ?? {});
49
+ const selectionRoster = computed(
50
+ () => unit.value.fields.filter((f) => findField(f.type, f.compatibilityDate)?.metadata?.selection).map((f) => ({ id: f.id, name: fieldLabel(f) }))
51
+ );
52
+ provideSelectionRoster(selectionRoster);
48
53
  const takeover = inject(SIDEBAR_TAKEOVER_KEY, null);
49
54
  const takeoverTarget = computed(() => takeover?.target.value ?? null);
50
55
  const activeFieldId = computed(() => {
@@ -1,5 +1,9 @@
1
+ import { SELECTIONS_VAR } from "../../../utils/cel-context.js";
1
2
  export function registerFormVariablesIfAbsent(env) {
2
3
  const declared = new Set(env.getDefinitions().variables.map((v) => v.name));
3
4
  if (!declared.has("now")) env.registerVariable("now", "Date", { label: "\u5F53\u524D\u65F6\u95F4", description: "\u5F53\u524D\u65E5\u671F/\u65F6\u95F4" });
4
5
  if (!declared.has("form")) env.registerVariable("form", "dyn", { label: "\u8868\u5355\u503C", description: "\u5F53\u524D\u8868\u5355\u72B6\u6001" });
6
+ if (!declared.has("undoable")) env.registerVariable("undoable", "bool", { label: "\u53EF\u64A4\u9500", description: "\u5F53\u524D\u662F\u5426\u6709\u53EF\u64A4\u9500\u7684\u4FEE\u6539" });
7
+ if (!declared.has("redoable")) env.registerVariable("redoable", "bool", { label: "\u53EF\u91CD\u505A", description: "\u5F53\u524D\u662F\u5426\u6709\u53EF\u91CD\u505A\u7684\u4FEE\u6539" });
8
+ if (!declared.has(SELECTIONS_VAR)) env.registerVariable(SELECTIONS_VAR, "dyn", { label: "\u9009\u4E2D\u9879", description: "\u5404\u9009\u62E9\u5B57\u6BB5\u5F53\u524D\u9009\u4E2D\u9879\u7684\u5B8C\u6574\u5BF9\u8C61\uFF08\u6309\u5B57\u6BB5\u6807\u8BC6\uFF09" });
5
9
  }
@@ -65,6 +65,16 @@ export type FieldMetadata = Readonly<{
65
65
  * fullscreen. See `BlockLayoutEditor`'s inline-config pane.
66
66
  */
67
67
  inlineConfig?: boolean;
68
+ /**
69
+ * Whether this field is *selection-like* — it publishes its currently-resolved
70
+ * full option to the `selections` registry at runtime (see
71
+ * `utils/selections-registry`), keyed by its uuid. The form's unit-config reads
72
+ * this to build the selection roster the ExpressionEditor advertises: a sibling
73
+ * expression reaches the chosen record via `selections["<id>"].code`, and the
74
+ * editor renders that uuid as this field's name. Set it together with the
75
+ * runtime publish so the picker never advertises a field that writes nothing.
76
+ */
77
+ selection?: boolean;
68
78
  }>;
69
79
  /**
70
80
  * Optional creation-time defaults factory. Returns a partial config that