@shwfed/config 2.9.13 → 2.10.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 (95) hide show
  1. package/dist/mcp.mjs +1553 -1112
  2. package/dist/module.json +1 -1
  3. package/dist/preview/assets/{FieldGroup.vue_vue_type_script_setup_true_lang-DZ_H-YRf.js → FieldGroup.vue_vue_type_script_setup_true_lang-CCaOWk_7.js} +1 -1
  4. package/dist/preview/assets/{badge-DoNuZh0A.js → badge-D9_7atSJ.js} +1 -1
  5. package/dist/preview/assets/{config-DTEJOYqA.js → config-B2d8SiPi.js} +1 -1
  6. package/dist/preview/assets/{config-D4rFsdGO.js → config-BLEovXei.js} +1 -1
  7. package/dist/preview/assets/{config-BrNZsgV0.js → config-Bf5Vckj3.js} +1 -1
  8. package/dist/preview/assets/{config-ugF_BOWz.js → config-Bk2VSNeu.js} +1 -1
  9. package/dist/preview/assets/{config-Cla0Qngs.js → config-C8lCItmz.js} +1 -1
  10. package/dist/preview/assets/{config-BDDuqAht.js → config-C9WPOoA7.js} +1 -1
  11. package/dist/preview/assets/{config-YGBoSq6x.js → config-CNKb25Qo.js} +1 -1
  12. package/dist/preview/assets/{config-CLsjWZz2.js → config-CQrqVV1U.js} +1 -1
  13. package/dist/preview/assets/{config-CIYui2J_.js → config-DWA385pD.js} +1 -1
  14. package/dist/preview/assets/{config-C6Cm7DWx.js → config-DYxMKhCU.js} +1 -1
  15. package/dist/preview/assets/{config-Bhc_Vu67.js → config-DZlaJUlF.js} +1 -1
  16. package/dist/preview/assets/{config-tdZMdIN3.js → config-DyPl6K2G.js} +1 -1
  17. package/dist/preview/assets/{definition.vue_vue_type_script_setup_true_lang-CgNXv26P.js → definition.vue_vue_type_script_setup_true_lang-CFzQ7icU.js} +1 -1
  18. package/dist/preview/assets/index-7BE56IYF.js +739 -0
  19. package/dist/preview/assets/{index-CzzwZ7bp.css → index-BnJ5p1Mx.css} +1 -1
  20. package/dist/preview/assets/index-Bwv0Yz_L.js +1 -0
  21. package/dist/preview/assets/{index-C3FdepLE.js → index-CXOEVGFP.js} +1 -1
  22. package/dist/preview/assets/{item-DecwNzYq.js → item-DCVX69_o.js} +1 -1
  23. package/dist/preview/assets/{runtime-C3dmOj9s.js → runtime-BD1A-g1h.js} +1 -1
  24. package/dist/preview/assets/{runtime-C8Ufkmiw.js → runtime-BNk4EliL.js} +1 -1
  25. package/dist/preview/assets/{runtime-BK7KNEyN.js → runtime-BO-KY3T_.js} +1 -1
  26. package/dist/preview/assets/{runtime-DZ_AwduQ.js → runtime-BsNSI1XP.js} +1 -1
  27. package/dist/preview/assets/{runtime-blb90Fhv.js → runtime-Cbc5NH57.js} +1 -1
  28. package/dist/preview/assets/{runtime-CYpXd7Pq.js → runtime-DEWGIyvr.js} +1 -1
  29. package/dist/preview/assets/{runtime-CjPtRd-T.js → runtime-DJ9ElxWB.js} +1 -1
  30. package/dist/preview/assets/{runtime-C5hqSHRW.js → runtime-DSfMvph3.js} +1 -1
  31. package/dist/preview/assets/{runtime-DSUjc0Pk.js → runtime-O6MNC3GA.js} +1 -1
  32. package/dist/preview/assets/{runtime-DtP98Km5.js → runtime-r1wbrr4k.js} +1 -1
  33. package/dist/preview/assets/{schema-meta-DWUHNP8E.js → schema-meta-ovcuERKg.js} +1 -1
  34. package/dist/preview/index.html +2 -2
  35. package/dist/runtime/components/actions/components/triggers-field.vue +12 -12
  36. package/dist/runtime/components/config/use-editor.js +1 -1
  37. package/dist/runtime/components/config/utils/validation-error.d.ts +1 -1
  38. package/dist/runtime/components/config/utils/validation-error.js +40 -7
  39. package/dist/runtime/components/form/fields/2026-04-22/com.shwfed.form.field.markdown/runtime.vue +3 -3
  40. package/dist/runtime/components/form/fields/2026-04-22/com.shwfed.form.field.text/runtime.vue +6 -5
  41. package/dist/runtime/components/form/fields/2026-04-22/com.shwfed.form.field.textarea/runtime.vue +6 -5
  42. package/dist/runtime/components/form/fields/2026-04-24/com.shwfed.form.field.combobox.single/runtime.vue +10 -8
  43. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.date/runtime.vue +8 -6
  44. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.daterange/runtime.vue +10 -8
  45. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.datetime/runtime.vue +8 -6
  46. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.datetimerange/runtime.vue +10 -8
  47. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.time/runtime.vue +7 -5
  48. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.timerange/runtime.vue +8 -6
  49. package/dist/runtime/components/form/fields/2026-04-28/com.shwfed.form.field.number/runtime.vue +7 -6
  50. package/dist/runtime/components/form/fields/2026-04-28/com.shwfed.form.field.numberrange/runtime.vue +9 -7
  51. package/dist/runtime/components/form/fields/2026-04-28/com.shwfed.form.field.switch/runtime.vue +4 -3
  52. package/dist/runtime/components/form/fields/2026-04-29/com.shwfed.form.field.combobox.single/runtime.vue +8 -6
  53. package/dist/runtime/components/form/fields/2026-05-12/com.shwfed.form.field.upload/runtime.vue +5 -4
  54. package/dist/runtime/components/form/fields/2026-05-13/com.shwfed.form.field.combobox.single.remote/runtime.vue +12 -10
  55. package/dist/runtime/components/form/fields/2026-05-13/com.shwfed.form.field.list/runtime.vue +5 -4
  56. package/dist/runtime/components/form/fields/2026-05-17/com.shwfed.form.field.checkbox.group/runtime.vue +9 -7
  57. package/dist/runtime/components/form/fields/2026-05-17/com.shwfed.form.field.radio.group/runtime.vue +9 -7
  58. package/dist/runtime/components/form/fields/2026-05-23/com.shwfed.form.field.tree.multi/runtime.vue +13 -15
  59. package/dist/runtime/components/form/fields/2026-05-24/com.shwfed.form.field.month/runtime.vue +8 -6
  60. package/dist/runtime/components/form/fields/2026-05-24/com.shwfed.form.field.monthrange/runtime.vue +10 -8
  61. package/dist/runtime/components/form/fields/2026-05-25/com.shwfed.form.field.combobox.multi/runtime.vue +10 -8
  62. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.multi/runtime.vue +13 -14
  63. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.single/runtime.vue +13 -14
  64. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.multi/runtime.vue +14 -12
  65. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.single/runtime.vue +14 -12
  66. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.multi/runtime.vue +13 -14
  67. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.single/runtime.vue +13 -14
  68. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.multi/runtime.vue +13 -15
  69. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.single/runtime.vue +15 -16
  70. package/dist/runtime/components/form/fields/2026-06-09/com.shwfed.form.field.upload/runtime.vue +8 -7
  71. package/dist/runtime/components/form/fields/2026-06-14/com.shwfed.form.field.combobox.multi/config.d.vue.ts +175 -0
  72. package/dist/runtime/components/form/fields/2026-06-14/com.shwfed.form.field.combobox.multi/config.vue +782 -0
  73. package/dist/runtime/components/form/fields/2026-06-14/com.shwfed.form.field.combobox.multi/config.vue.d.ts +175 -0
  74. package/dist/runtime/components/form/fields/2026-06-14/com.shwfed.form.field.combobox.multi/runtime.d.vue.ts +8 -0
  75. package/dist/runtime/components/form/fields/2026-06-14/com.shwfed.form.field.combobox.multi/runtime.vue +413 -0
  76. package/dist/runtime/components/form/fields/2026-06-14/com.shwfed.form.field.combobox.multi/runtime.vue.d.ts +8 -0
  77. package/dist/runtime/components/form/fields/2026-06-14/com.shwfed.form.field.combobox.multi/schema.d.ts +214 -0
  78. package/dist/runtime/components/form/fields/2026-06-14/com.shwfed.form.field.combobox.multi/schema.js +191 -0
  79. package/dist/runtime/components/form/fields/2026-06-14/com.shwfed.form.field.combobox.single/config.d.vue.ts +175 -0
  80. package/dist/runtime/components/form/fields/2026-06-14/com.shwfed.form.field.combobox.single/config.vue +782 -0
  81. package/dist/runtime/components/form/fields/2026-06-14/com.shwfed.form.field.combobox.single/config.vue.d.ts +175 -0
  82. package/dist/runtime/components/form/fields/2026-06-14/com.shwfed.form.field.combobox.single/runtime.d.vue.ts +8 -0
  83. package/dist/runtime/components/form/fields/2026-06-14/com.shwfed.form.field.combobox.single/runtime.vue +426 -0
  84. package/dist/runtime/components/form/fields/2026-06-14/com.shwfed.form.field.combobox.single/runtime.vue.d.ts +8 -0
  85. package/dist/runtime/components/form/fields/2026-06-14/com.shwfed.form.field.combobox.single/schema.d.ts +214 -0
  86. package/dist/runtime/components/form/fields/2026-06-14/com.shwfed.form.field.combobox.single/schema.js +191 -0
  87. package/dist/runtime/components/form/fields/2026-06-14/combobox-migrate.d.ts +18 -0
  88. package/dist/runtime/components/form/fields/2026-06-14/combobox-migrate.js +36 -0
  89. package/dist/runtime/components/form/utils/state.d.ts +11 -0
  90. package/dist/runtime/components/form/utils/state.js +5 -0
  91. package/dist/runtime/components/ui/input-group/InputGroupNumberField.vue +1 -1
  92. package/dist/runtime/share/expression.js +1 -0
  93. package/package.json +1 -1
  94. package/dist/preview/assets/index-B-QhiviS.js +0 -1
  95. package/dist/preview/assets/index-CWMhB7z4.js +0 -735
@@ -25,7 +25,7 @@ import { Markdown } from "../../../../ui/markdown";
25
25
  import { Popover, PopoverAnchor, PopoverContent, PopoverTrigger } from "../../../../ui/popover";
26
26
  import { DEFAULT_FIELD_ORIENTATION } from "../../../utils/common";
27
27
  import { useFormReadonly } from "../../../utils/readonly";
28
- import { useFormState } from "../../../utils/state";
28
+ import { useFormScope, useFormState } from "../../../utils/state";
29
29
  import { useFieldValidation } from "../../../utils/validation";
30
30
  defineOptions({ name: "ShwfedComboboxSingleFieldRuntime" });
31
31
  const props = defineProps({
@@ -55,7 +55,8 @@ const { locale, t } = useI18n({
55
55
  }
56
56
  }
57
57
  });
58
- const { state, getAt, setAt, setAtSilent } = useFormState();
58
+ const { getAt, setAt, setAtSilent } = useFormState();
59
+ const formScope = useFormScope();
59
60
  const inherited = injectCELContext();
60
61
  const $cel = (expression, context) => _rawCel(expression, { ...celBindings(inherited), ...context });
61
62
  const labelText = computed(() => getLocalizedText(props.config.label, locale.value));
@@ -68,7 +69,7 @@ const tooltipText = computed(
68
69
  function evalBool(expression, label) {
69
70
  if (!expression) return false;
70
71
  try {
71
- return Effect.runSync($cel(expression, { form: state.value ?? {} }));
72
+ return Effect.runSync($cel(expression, { form: formScope.state.value ?? {} }));
72
73
  } catch (err) {
73
74
  console.error(`[shwfed-form] failed to evaluate ${label} for ${props.fieldId}:`, err);
74
75
  return false;
@@ -103,7 +104,7 @@ const requestSignature = computed(() => {
103
104
  const expr = opts.request;
104
105
  if (!expr) return null;
105
106
  try {
106
- const req = asRequest(Effect.runSync($cel(expr, { form: state.value ?? {} })));
107
+ const req = asRequest(Effect.runSync($cel(expr, { form: formScope.state.value ?? {} })));
107
108
  return Option.isSome(req) ? JSON.stringify(req.value.describe()) : null;
108
109
  } catch {
109
110
  return null;
@@ -126,7 +127,7 @@ async function fetchOptions() {
126
127
  }
127
128
  isLoading.value = true;
128
129
  const program = Effect.gen(function* () {
129
- const body = yield* fetchJsonOption(yield* $cel(expr, { form: state.value ?? {} }));
130
+ const body = yield* fetchJsonOption(yield* $cel(expr, { form: formScope.state.value ?? {} }));
130
131
  return Option.getOrNull(body);
131
132
  });
132
133
  try {
@@ -142,7 +143,7 @@ function remoteValueOf(option) {
142
143
  const opts = props.config.options;
143
144
  if (opts.kind !== "remote") return void 0;
144
145
  try {
145
- return Effect.runSync($cel(opts.optionValue, { form: state.value ?? {}, option }));
146
+ return Effect.runSync($cel(opts.optionValue, { form: formScope.state.value ?? {}, option }));
146
147
  } catch (err) {
147
148
  console.error(`[shwfed-form] failed to evaluate optionValue for ${props.fieldId}:`, err);
148
149
  return void 0;
@@ -153,13 +154,13 @@ function remoteLabelOf(option) {
153
154
  if (opts.kind !== "remote") return "";
154
155
  const tpl = getLocalizedText(opts.optionLabel, locale.value) ?? "";
155
156
  if (!tpl) return "";
156
- return interpolateMarkdown(tpl, $cel, { form: state.value ?? {}, option });
157
+ return interpolateMarkdown(tpl, $cel, { form: formScope.state.value ?? {}, option });
157
158
  }
158
159
  function remoteKeywordsOf(option) {
159
160
  const opts = props.config.options;
160
161
  if (opts.kind !== "remote" || !opts.optionKeywords) return void 0;
161
162
  try {
162
- const raw = Effect.runSync($cel(opts.optionKeywords, { form: state.value ?? {}, option }));
163
+ const raw = Effect.runSync($cel(opts.optionKeywords, { form: formScope.state.value ?? {}, option }));
163
164
  if (!Array.isArray(raw)) return void 0;
164
165
  const joined = raw.map((k) => k == null ? "" : String(k)).filter(Boolean).join(" ");
165
166
  return joined.length > 0 ? joined : void 0;
@@ -174,7 +175,7 @@ const entries = computed(() => {
174
175
  return (opts.items ?? []).map((item) => {
175
176
  const labelTpl = getLocalizedText(item.label, locale.value) ?? "";
176
177
  const tooltipTpl = item.tooltip ? getLocalizedText(item.tooltip, locale.value) : void 0;
177
- const ctx = { form: state.value ?? {} };
178
+ const ctx = { form: formScope.state.value ?? {} };
178
179
  const kw = (item.keywords ?? []).filter(Boolean).join(" ");
179
180
  return {
180
181
  key: item.id,
@@ -188,7 +189,7 @@ const entries = computed(() => {
188
189
  }
189
190
  let raw;
190
191
  try {
191
- raw = Effect.runSync($cel(opts.options, { form: state.value ?? {}, json: json.value }));
192
+ raw = Effect.runSync($cel(opts.options, { form: formScope.state.value ?? {}, json: json.value }));
192
193
  } catch (err) {
193
194
  console.error(`[shwfed-form] failed to evaluate options for ${props.fieldId}:`, err);
194
195
  return [];
@@ -311,14 +312,15 @@ const anyHasTooltip = computed(
311
312
  </FieldLabel>
312
313
  <div
313
314
  v-if="effectiveReadonly"
314
- class="min-h-9 py-1.5 text-sm text-zinc-700"
315
+ class="min-h-9 py-1.5 text-sm"
316
+ :class="selectedLabel ? 'text-zinc-700' : 'font-mono text-zinc-300 select-none'"
315
317
  >
316
318
  <Markdown
317
319
  v-if="selectedLabel"
318
320
  :source="selectedLabel"
319
321
  />
320
322
  <template v-else>
321
-
323
+ -
322
324
  </template>
323
325
  </div>
324
326
  <Popover
@@ -18,7 +18,7 @@ import { Tree as UiTree } from "../../../../ui/tree";
18
18
  import { interpolateMarkdown } from "../../../../table/utils/runtime";
19
19
  import { DEFAULT_FIELD_ORIENTATION } from "../../../utils/common";
20
20
  import { useFormReadonly } from "../../../utils/readonly";
21
- import { useFormState } from "../../../utils/state";
21
+ import { useFormScope, useFormState } from "../../../utils/state";
22
22
  import { useFieldValidation } from "../../../utils/validation";
23
23
  import {
24
24
  findWrappedPath,
@@ -39,8 +39,7 @@ const { locale, t } = useI18n({
39
39
  "tree-combobox-multi-search-clear": "\u6E05\u9664\u641C\u7D22",
40
40
  "tree-combobox-multi-empty": "\u65E0\u53EF\u9009\u9879",
41
41
  "tree-combobox-multi-load-error": "\u52A0\u8F7D\u5931\u8D25",
42
- "tree-combobox-multi-retry": "\u91CD\u8BD5",
43
- "tree-combobox-multi-readonly-empty": "\u2014"
42
+ "tree-combobox-multi-retry": "\u91CD\u8BD5"
44
43
  },
45
44
  en: {
46
45
  "tree-combobox-multi-placeholder": "Select\u2026",
@@ -48,8 +47,7 @@ const { locale, t } = useI18n({
48
47
  "tree-combobox-multi-search-clear": "Clear search",
49
48
  "tree-combobox-multi-empty": "No options",
50
49
  "tree-combobox-multi-load-error": "Failed to load",
51
- "tree-combobox-multi-retry": "Retry",
52
- "tree-combobox-multi-readonly-empty": "\u2014"
50
+ "tree-combobox-multi-retry": "Retry"
53
51
  },
54
52
  ja: {
55
53
  "tree-combobox-multi-placeholder": "\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044",
@@ -57,12 +55,12 @@ const { locale, t } = useI18n({
57
55
  "tree-combobox-multi-search-clear": "\u691C\u7D22\u3092\u30AF\u30EA\u30A2",
58
56
  "tree-combobox-multi-empty": "\u9078\u629E\u80A2\u306A\u3057",
59
57
  "tree-combobox-multi-load-error": "\u8AAD\u307F\u8FBC\u307F\u306B\u5931\u6557\u3057\u307E\u3057\u305F",
60
- "tree-combobox-multi-retry": "\u518D\u8A66\u884C",
61
- "tree-combobox-multi-readonly-empty": "\u2014"
58
+ "tree-combobox-multi-retry": "\u518D\u8A66\u884C"
62
59
  }
63
60
  }
64
61
  });
65
- const { state, getAt, setAt } = useFormState();
62
+ const { getAt, setAt } = useFormState();
63
+ const formScope = useFormScope();
66
64
  const inherited = injectCELContext();
67
65
  const $cel = (expression, context) => _rawCel(expression, { ...celBindings(inherited), ...context });
68
66
  const labelText = computed(() => getLocalizedText(props.config.label, locale.value));
@@ -75,7 +73,7 @@ const placeholderText = computed(
75
73
  function evalBool(expression, label) {
76
74
  if (!expression) return false;
77
75
  try {
78
- return Effect.runSync($cel(expression, { form: state.value ?? {} }));
76
+ return Effect.runSync($cel(expression, { form: formScope.state.value ?? {} }));
79
77
  } catch (err) {
80
78
  console.error(`[shwfed-form] failed to evaluate ${label} for ${props.fieldId}:`, err);
81
79
  return false;
@@ -111,7 +109,7 @@ const model = computed({
111
109
  }
112
110
  });
113
111
  function nodeCtx(raw) {
114
- return { form: state.value ?? {}, node: raw };
112
+ return { form: formScope.state.value ?? {}, node: raw };
115
113
  }
116
114
  function nodeKey(raw) {
117
115
  try {
@@ -184,11 +182,11 @@ async function fetchTree() {
184
182
  let jsonOpt = Option.none();
185
183
  if (dataSource.request) {
186
184
  jsonOpt = yield* fetchJsonOption(yield* $cel(dataSource.request, {
187
- form: state.value ?? {}
185
+ form: formScope.state.value ?? {}
188
186
  }));
189
187
  }
190
188
  const dataRaw = yield* $cel(dataSource.data, {
191
- form: state.value ?? {},
189
+ form: formScope.state.value ?? {},
192
190
  json: jsonOpt
193
191
  });
194
192
  return Array.isArray(dataRaw) ? dataRaw : [];
@@ -365,9 +363,10 @@ const hoveredTooltip = computed(() => {
365
363
 
366
364
  <div
367
365
  v-if="effectiveReadonly"
368
- class="min-h-9 py-1.5 text-sm text-zinc-700"
366
+ class="min-h-9 py-1.5 text-sm"
367
+ :class="triggerLabel ? 'text-zinc-700' : 'font-mono text-zinc-300 select-none'"
369
368
  >
370
- {{ triggerLabel || t("tree-combobox-multi-readonly-empty") }}
369
+ {{ triggerLabel || "-" }}
371
370
  </div>
372
371
 
373
372
  <Popover
@@ -18,7 +18,7 @@ import { Tree as UiTree } from "../../../../ui/tree";
18
18
  import { interpolateMarkdown } from "../../../../table/utils/runtime";
19
19
  import { DEFAULT_FIELD_ORIENTATION } from "../../../utils/common";
20
20
  import { useFormReadonly } from "../../../utils/readonly";
21
- import { useFormState } from "../../../utils/state";
21
+ import { useFormScope, useFormState } from "../../../utils/state";
22
22
  import { useFieldValidation } from "../../../utils/validation";
23
23
  import {
24
24
  findWrappedPath,
@@ -39,8 +39,7 @@ const { locale, t } = useI18n({
39
39
  "tree-combobox-single-search-clear": "\u6E05\u9664\u641C\u7D22",
40
40
  "tree-combobox-single-empty": "\u65E0\u53EF\u9009\u9879",
41
41
  "tree-combobox-single-load-error": "\u52A0\u8F7D\u5931\u8D25",
42
- "tree-combobox-single-retry": "\u91CD\u8BD5",
43
- "tree-combobox-single-readonly-empty": "\u2014"
42
+ "tree-combobox-single-retry": "\u91CD\u8BD5"
44
43
  },
45
44
  en: {
46
45
  "tree-combobox-single-placeholder": "Select\u2026",
@@ -48,8 +47,7 @@ const { locale, t } = useI18n({
48
47
  "tree-combobox-single-search-clear": "Clear search",
49
48
  "tree-combobox-single-empty": "No options",
50
49
  "tree-combobox-single-load-error": "Failed to load",
51
- "tree-combobox-single-retry": "Retry",
52
- "tree-combobox-single-readonly-empty": "\u2014"
50
+ "tree-combobox-single-retry": "Retry"
53
51
  },
54
52
  ja: {
55
53
  "tree-combobox-single-placeholder": "\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044",
@@ -57,12 +55,12 @@ const { locale, t } = useI18n({
57
55
  "tree-combobox-single-search-clear": "\u691C\u7D22\u3092\u30AF\u30EA\u30A2",
58
56
  "tree-combobox-single-empty": "\u9078\u629E\u80A2\u306A\u3057",
59
57
  "tree-combobox-single-load-error": "\u8AAD\u307F\u8FBC\u307F\u306B\u5931\u6557\u3057\u307E\u3057\u305F",
60
- "tree-combobox-single-retry": "\u518D\u8A66\u884C",
61
- "tree-combobox-single-readonly-empty": "\u2014"
58
+ "tree-combobox-single-retry": "\u518D\u8A66\u884C"
62
59
  }
63
60
  }
64
61
  });
65
- const { state, getAt, setAt } = useFormState();
62
+ const { getAt, setAt } = useFormState();
63
+ const formScope = useFormScope();
66
64
  const inherited = injectCELContext();
67
65
  const $cel = (expression, context) => _rawCel(expression, { ...celBindings(inherited), ...context });
68
66
  const labelText = computed(() => getLocalizedText(props.config.label, locale.value));
@@ -75,7 +73,7 @@ const placeholderText = computed(
75
73
  function evalBool(expression, label) {
76
74
  if (!expression) return false;
77
75
  try {
78
- return Effect.runSync($cel(expression, { form: state.value ?? {} }));
76
+ return Effect.runSync($cel(expression, { form: formScope.state.value ?? {} }));
79
77
  } catch (err) {
80
78
  console.error(`[shwfed-form] failed to evaluate ${label} for ${props.fieldId}:`, err);
81
79
  return false;
@@ -112,7 +110,7 @@ const model = computed({
112
110
  }
113
111
  });
114
112
  function nodeCtx(raw) {
115
- return { form: state.value ?? {}, node: raw };
113
+ return { form: formScope.state.value ?? {}, node: raw };
116
114
  }
117
115
  function nodeKey(raw) {
118
116
  try {
@@ -185,11 +183,11 @@ async function fetchTree() {
185
183
  let jsonOpt = Option.none();
186
184
  if (dataSource.request) {
187
185
  jsonOpt = yield* fetchJsonOption(yield* $cel(dataSource.request, {
188
- form: state.value ?? {}
186
+ form: formScope.state.value ?? {}
189
187
  }));
190
188
  }
191
189
  const dataRaw = yield* $cel(dataSource.data, {
192
- form: state.value ?? {},
190
+ form: formScope.state.value ?? {},
193
191
  json: jsonOpt
194
192
  });
195
193
  return Array.isArray(dataRaw) ? dataRaw : [];
@@ -353,9 +351,10 @@ const hoveredTooltip = computed(() => {
353
351
 
354
352
  <div
355
353
  v-if="effectiveReadonly"
356
- class="min-h-9 py-1.5 text-sm text-zinc-700"
354
+ class="min-h-9 py-1.5 text-sm"
355
+ :class="triggerLabel ? 'text-zinc-700' : 'font-mono text-zinc-300 select-none'"
357
356
  >
358
- {{ triggerLabel || t("tree-combobox-single-readonly-empty") }}
357
+ {{ triggerLabel || "-" }}
359
358
  </div>
360
359
 
361
360
  <Popover
@@ -17,7 +17,7 @@ import { Skeleton } from "../../../../ui/skeleton";
17
17
  import { Tree as UiTree } from "../../../../ui/tree";
18
18
  import { interpolateMarkdown } from "../../../../table/utils/runtime";
19
19
  import { useFormReadonly } from "../../../utils/readonly";
20
- import { useFormState } from "../../../utils/state";
20
+ import { useFormScope, useFormState } from "../../../utils/state";
21
21
  import { useFieldValidation } from "../../../utils/validation";
22
22
  defineOptions({ name: "ShwfedTreeMultiFieldRuntime" });
23
23
  const props = defineProps({
@@ -32,7 +32,6 @@ const { locale, t } = useI18n({
32
32
  "tree-multi-search-clear": "\u6E05\u9664\u641C\u7D22",
33
33
  "tree-multi-load-error": "\u52A0\u8F7D\u5931\u8D25",
34
34
  "tree-multi-empty": "\u65E0\u53EF\u9009\u9879",
35
- "tree-multi-readonly-empty": "\u2014",
36
35
  "tree-multi-readonly-separator": "\u3001"
37
36
  },
38
37
  en: {
@@ -40,7 +39,6 @@ const { locale, t } = useI18n({
40
39
  "tree-multi-search-clear": "Clear search",
41
40
  "tree-multi-load-error": "Failed to load",
42
41
  "tree-multi-empty": "No options",
43
- "tree-multi-readonly-empty": "\u2014",
44
42
  "tree-multi-readonly-separator": ", "
45
43
  },
46
44
  ja: {
@@ -48,12 +46,12 @@ const { locale, t } = useI18n({
48
46
  "tree-multi-search-clear": "\u691C\u7D22\u3092\u30AF\u30EA\u30A2",
49
47
  "tree-multi-load-error": "\u8AAD\u307F\u8FBC\u307F\u306B\u5931\u6557\u3057\u307E\u3057\u305F",
50
48
  "tree-multi-empty": "\u9078\u629E\u80A2\u306A\u3057",
51
- "tree-multi-readonly-empty": "\u2014",
52
49
  "tree-multi-readonly-separator": "\u3001"
53
50
  }
54
51
  }
55
52
  });
56
- const { state, getAt, setAt } = useFormState();
53
+ const { getAt, setAt } = useFormState();
54
+ const formScope = useFormScope();
57
55
  const inherited = injectCELContext();
58
56
  const $cel = (expression, context) => _rawCel(expression, { ...celBindings(inherited), ...context });
59
57
  const labelText = computed(() => getLocalizedText(props.config.label, locale.value));
@@ -63,7 +61,7 @@ const tooltipText = computed(
63
61
  function evalBool(expression, label) {
64
62
  if (!expression) return false;
65
63
  try {
66
- return Effect.runSync($cel(expression, { form: state.value ?? {} }));
64
+ return Effect.runSync($cel(expression, { form: formScope.state.value ?? {} }));
67
65
  } catch (err) {
68
66
  console.error(`[shwfed-form] failed to evaluate ${label} for ${props.fieldId}:`, err);
69
67
  return false;
@@ -111,11 +109,11 @@ async function fetchTree() {
111
109
  let jsonOpt = Option.none();
112
110
  if (dataSource.request) {
113
111
  jsonOpt = yield* fetchJsonOption(yield* $cel(dataSource.request, {
114
- form: state.value ?? {}
112
+ form: formScope.state.value ?? {}
115
113
  }));
116
114
  }
117
115
  const dataRaw = yield* $cel(dataSource.data, {
118
- form: state.value ?? {},
116
+ form: formScope.state.value ?? {},
119
117
  json: jsonOpt
120
118
  });
121
119
  return Array.isArray(dataRaw) ? dataRaw : [];
@@ -149,7 +147,7 @@ watch(
149
147
  { immediate: true }
150
148
  );
151
149
  function nodeCtx(node) {
152
- return { form: state.value ?? {}, node };
150
+ return { form: formScope.state.value ?? {}, node };
153
151
  }
154
152
  function getKey(node) {
155
153
  try {
@@ -186,7 +184,7 @@ function nodeSelectable(node, _depth) {
186
184
  }
187
185
  function safeInterpolate(tpl, node) {
188
186
  try {
189
- return interpolateMarkdown(tpl, $cel, { form: state.value ?? {}, node });
187
+ return interpolateMarkdown(tpl, $cel, { form: formScope.state.value ?? {}, node });
190
188
  } catch (err) {
191
189
  console.error(`[shwfed-form] failed to interpolate node text for ${props.fieldId}:`, err);
192
190
  return tpl;
@@ -289,14 +287,13 @@ publishSelection(
289
287
  }
290
288
  );
291
289
  const readonlyText = computed(() => {
292
- const empty = t("tree-multi-readonly-empty");
293
- if (model.value.length === 0) return empty;
290
+ if (model.value.length === 0) return null;
294
291
  const found = resolvedByKey.value;
295
292
  const labels = model.value.map((id) => {
296
293
  const n = found.get(id);
297
294
  return n !== void 0 ? nodeLabelText(n) : id;
298
295
  }).filter((l) => l.length > 0);
299
- return labels.length > 0 ? labels.join(t("tree-multi-readonly-separator")) : empty;
296
+ return labels.length > 0 ? labels.join(t("tree-multi-readonly-separator")) : null;
300
297
  });
301
298
  </script>
302
299
 
@@ -327,9 +324,10 @@ const readonlyText = computed(() => {
327
324
 
328
325
  <div
329
326
  v-if="effectiveReadonly"
330
- class="min-h-9 py-1.5 text-sm text-zinc-700"
327
+ class="min-h-9 py-1.5 text-sm"
328
+ :class="readonlyText ? 'text-zinc-700' : 'font-mono text-zinc-300 select-none'"
331
329
  >
332
- {{ readonlyText }}
330
+ {{ readonlyText || "-" }}
333
331
  </div>
334
332
 
335
333
  <template v-else>
@@ -16,7 +16,7 @@ import { Skeleton } from "../../../../ui/skeleton";
16
16
  import { Tree as UiTree } from "../../../../ui/tree";
17
17
  import { interpolateMarkdown } from "../../../../table/utils/runtime";
18
18
  import { useFormReadonly } from "../../../utils/readonly";
19
- import { useFormState } from "../../../utils/state";
19
+ import { useFormScope, useFormState } from "../../../utils/state";
20
20
  import { useFieldValidation } from "../../../utils/validation";
21
21
  defineOptions({ name: "ShwfedTreeSingleFieldRuntime" });
22
22
  const props = defineProps({
@@ -30,26 +30,24 @@ const { locale, t } = useI18n({
30
30
  "tree-single-search-label": "\u641C\u7D22",
31
31
  "tree-single-search-clear": "\u6E05\u9664\u641C\u7D22",
32
32
  "tree-single-load-error": "\u52A0\u8F7D\u5931\u8D25",
33
- "tree-single-empty": "\u65E0\u53EF\u9009\u9879",
34
- "tree-single-readonly-empty": "\u2014"
33
+ "tree-single-empty": "\u65E0\u53EF\u9009\u9879"
35
34
  },
36
35
  en: {
37
36
  "tree-single-search-label": "Search",
38
37
  "tree-single-search-clear": "Clear search",
39
38
  "tree-single-load-error": "Failed to load",
40
- "tree-single-empty": "No options",
41
- "tree-single-readonly-empty": "\u2014"
39
+ "tree-single-empty": "No options"
42
40
  },
43
41
  ja: {
44
42
  "tree-single-search-label": "\u691C\u7D22",
45
43
  "tree-single-search-clear": "\u691C\u7D22\u3092\u30AF\u30EA\u30A2",
46
44
  "tree-single-load-error": "\u8AAD\u307F\u8FBC\u307F\u306B\u5931\u6557\u3057\u307E\u3057\u305F",
47
- "tree-single-empty": "\u9078\u629E\u80A2\u306A\u3057",
48
- "tree-single-readonly-empty": "\u2014"
45
+ "tree-single-empty": "\u9078\u629E\u80A2\u306A\u3057"
49
46
  }
50
47
  }
51
48
  });
52
- const { state, getAt, setAt } = useFormState();
49
+ const { getAt, setAt } = useFormState();
50
+ const formScope = useFormScope();
53
51
  const inherited = injectCELContext();
54
52
  const $cel = (expression, context) => _rawCel(expression, { ...celBindings(inherited), ...context });
55
53
  const labelText = computed(() => getLocalizedText(props.config.label, locale.value));
@@ -59,7 +57,7 @@ const tooltipText = computed(
59
57
  function evalBool(expression, label) {
60
58
  if (!expression) return false;
61
59
  try {
62
- return Effect.runSync($cel(expression, { form: state.value ?? {} }));
60
+ return Effect.runSync($cel(expression, { form: formScope.state.value ?? {} }));
63
61
  } catch (err) {
64
62
  console.error(`[shwfed-form] failed to evaluate ${label} for ${props.fieldId}:`, err);
65
63
  return false;
@@ -107,11 +105,11 @@ async function fetchTree() {
107
105
  let jsonOpt = Option.none();
108
106
  if (dataSource.request) {
109
107
  jsonOpt = yield* fetchJsonOption(yield* $cel(dataSource.request, {
110
- form: state.value ?? {}
108
+ form: formScope.state.value ?? {}
111
109
  }));
112
110
  }
113
111
  const dataRaw = yield* $cel(dataSource.data, {
114
- form: state.value ?? {},
112
+ form: formScope.state.value ?? {},
115
113
  json: jsonOpt
116
114
  });
117
115
  return Array.isArray(dataRaw) ? dataRaw : [];
@@ -145,7 +143,7 @@ watch(
145
143
  { immediate: true }
146
144
  );
147
145
  function nodeCtx(node) {
148
- return { form: state.value ?? {}, node };
146
+ return { form: formScope.state.value ?? {}, node };
149
147
  }
150
148
  function getKey(node) {
151
149
  try {
@@ -182,7 +180,7 @@ function nodeSelectable(node, _depth) {
182
180
  }
183
181
  function safeInterpolate(tpl, node) {
184
182
  try {
185
- return interpolateMarkdown(tpl, $cel, { form: state.value ?? {}, node });
183
+ return interpolateMarkdown(tpl, $cel, { form: formScope.state.value ?? {}, node });
186
184
  } catch (err) {
187
185
  console.error(`[shwfed-form] failed to interpolate node text for ${props.fieldId}:`, err);
188
186
  return tpl;
@@ -278,7 +276,7 @@ publishSelection(
278
276
  );
279
277
  const readonlyText = computed(() => {
280
278
  const selected = model.value;
281
- if (selected == null) return t("tree-single-readonly-empty");
279
+ if (selected == null) return null;
282
280
  const n = selectedNode.value;
283
281
  if (n === void 0) return selected;
284
282
  const label = nodeLabelText(n);
@@ -313,9 +311,10 @@ const readonlyText = computed(() => {
313
311
 
314
312
  <div
315
313
  v-if="effectiveReadonly"
316
- class="min-h-9 py-1.5 text-sm text-zinc-700"
314
+ class="min-h-9 py-1.5 text-sm"
315
+ :class="readonlyText ? 'text-zinc-700' : 'font-mono text-zinc-300 select-none'"
317
316
  >
318
- {{ readonlyText }}
317
+ {{ readonlyText || "-" }}
319
318
  </div>
320
319
 
321
320
  <template v-else>
@@ -14,7 +14,7 @@ import { Markdown } from "../../../../ui/markdown";
14
14
  import { DEFAULT_FIELD_ORIENTATION } from "../../../utils/common";
15
15
  import { useFieldValidation } from "../../../utils/validation";
16
16
  import { useFormReadonly } from "../../../utils/readonly";
17
- import { useFormState } from "../../../utils/state";
17
+ import { useFormScope, useFormState } from "../../../utils/state";
18
18
  const ICONS = {
19
19
  "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": "vscode-icons:file-type-excel",
20
20
  "application/vnd.ms-excel": "vscode-icons:file-type-excel",
@@ -91,7 +91,8 @@ const { locale, t } = useI18n({
91
91
  }
92
92
  }
93
93
  });
94
- const { state, getAt, setAt } = useFormState();
94
+ const { getAt, setAt } = useFormState();
95
+ const formScope = useFormScope();
95
96
  const inherited = injectCELContext();
96
97
  const $cel = (expression, context) => _rawCel(expression, { ...celBindings(inherited), ...context });
97
98
  const labelText = computed(
@@ -106,7 +107,7 @@ const tooltipText = computed(
106
107
  function evalBool(expression, label) {
107
108
  if (!expression) return false;
108
109
  try {
109
- return Effect.runSync($cel(expression, { form: state.value ?? {} }));
110
+ return Effect.runSync($cel(expression, { form: formScope.state.value ?? {} }));
110
111
  } catch (err) {
111
112
  console.error(`[shwfed-form] failed to evaluate ${label} for ${props.fieldId}:`, err);
112
113
  return false;
@@ -146,7 +147,7 @@ function entryName(entry) {
146
147
  const expr = props.config.upload?.filename;
147
148
  if (expr) {
148
149
  try {
149
- const name = Effect.runSync($cel(expr, { form: state.value ?? {}, file: entry }));
150
+ const name = Effect.runSync($cel(expr, { form: formScope.state.value ?? {}, file: entry }));
150
151
  if (typeof name === "string" && name.length > 0) return name;
151
152
  } catch (err) {
152
153
  console.error(`[shwfed-form] failed to evaluate upload filename for ${props.fieldId}:`, err);
@@ -215,11 +216,11 @@ async function uploadFiles(accepted) {
215
216
  if (!upload) return [];
216
217
  const program = Effect.gen(function* () {
217
218
  const builder = yield* $cel(upload.request, {
218
- form: state.value ?? {},
219
+ form: formScope.state.value ?? {},
219
220
  files: accepted
220
221
  });
221
222
  const json = yield* builder.json();
222
- return yield* $cel(upload.handle, { form: state.value ?? {}, json });
223
+ return yield* $cel(upload.handle, { form: formScope.state.value ?? {}, json });
223
224
  });
224
225
  try {
225
226
  const items = await Effect.runPromise(Effect.provide(program, Fetch.layer));
@@ -287,7 +288,7 @@ function templateLabelText(template) {
287
288
  return (template.label ? getLocalizedText(template.label, locale.value) : void 0) ?? "\u4E0B\u8F7D\u6A21\u677F";
288
289
  }
289
290
  async function onDownloadTemplate(template) {
290
- const ctx = { form: state.value ?? {} };
291
+ const ctx = { form: formScope.state.value ?? {} };
291
292
  const program = Effect.gen(function* () {
292
293
  const requestBuilder = yield* $cel(template.request, ctx);
293
294
  if (!template.download) {