@shwfed/config 3.0.16 → 3.0.17

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 (103) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/runtime/components/actions/buttons/2026-06-25/com.shwfed.actions.button.state.write/config.d.vue.ts +8 -8
  3. package/dist/runtime/components/actions/buttons/2026-06-25/com.shwfed.actions.button.state.write/config.vue.d.ts +8 -8
  4. package/dist/runtime/components/actions/buttons/2026-07-13/com.shwfed.actions.button.state.write/config.d.vue.ts +8 -8
  5. package/dist/runtime/components/actions/buttons/2026-07-13/com.shwfed.actions.button.state.write/config.vue.d.ts +8 -8
  6. package/dist/runtime/components/actions/buttons/2026-07-13/com.shwfed.actions.button.state.write/runtime.vue +1 -16
  7. package/dist/runtime/components/config/blocks/2026-07-17/com.shwfed.block.invoice.realestate.lease/config.d.vue.ts +6 -6
  8. package/dist/runtime/components/config/blocks/2026-07-17/com.shwfed.block.invoice.realestate.lease/config.vue.d.ts +6 -6
  9. package/dist/runtime/components/config/blocks/2026-07-17/com.shwfed.block.invoice.realestate.lease/runtime.d.vue.ts +6 -6
  10. package/dist/runtime/components/config/blocks/2026-07-17/com.shwfed.block.invoice.realestate.lease/runtime.vue.d.ts +6 -6
  11. package/dist/runtime/components/form/fields/2026-04-22/com.shwfed.form.field.text/config.d.vue.ts +22 -22
  12. package/dist/runtime/components/form/fields/2026-04-22/com.shwfed.form.field.text/config.vue.d.ts +22 -22
  13. package/dist/runtime/components/form/fields/2026-04-22/com.shwfed.form.field.textarea/config.d.vue.ts +2 -2
  14. package/dist/runtime/components/form/fields/2026-04-22/com.shwfed.form.field.textarea/config.vue.d.ts +2 -2
  15. package/dist/runtime/components/form/fields/2026-04-28/com.shwfed.form.field.number/config.d.vue.ts +22 -22
  16. package/dist/runtime/components/form/fields/2026-04-28/com.shwfed.form.field.number/config.vue.d.ts +22 -22
  17. package/dist/runtime/components/form/index.vue +57 -2
  18. package/dist/runtime/components/form/schema.d.ts +5 -0
  19. package/dist/runtime/components/form/schema.js +14 -1
  20. package/dist/runtime/components/form/utils/state-write.d.ts +9 -0
  21. package/dist/runtime/components/form/utils/state-write.js +16 -0
  22. package/dist/runtime/components/operations/2026-07-19/com.shwfed.operation.form.state.write/config.d.vue.ts +21 -0
  23. package/dist/runtime/components/operations/2026-07-19/com.shwfed.operation.form.state.write/config.vue +100 -0
  24. package/dist/runtime/components/operations/2026-07-19/com.shwfed.operation.form.state.write/config.vue.d.ts +21 -0
  25. package/dist/runtime/components/operations/2026-07-19/com.shwfed.operation.form.state.write/schema.d.ts +18 -0
  26. package/dist/runtime/components/operations/2026-07-19/com.shwfed.operation.form.state.write/schema.js +47 -0
  27. package/dist/runtime/components/table/columns/2026-05-20/com.shwfed.table.column.combobox-single/config.d.vue.ts +2 -0
  28. package/dist/runtime/components/table/columns/2026-05-20/com.shwfed.table.column.combobox-single/config.vue +32 -0
  29. package/dist/runtime/components/table/columns/2026-05-20/com.shwfed.table.column.combobox-single/config.vue.d.ts +2 -0
  30. package/dist/runtime/components/table/columns/2026-05-20/com.shwfed.table.column.combobox-single/schema.d.ts +1 -0
  31. package/dist/runtime/components/table/columns/2026-05-20/com.shwfed.table.column.combobox-single/schema.js +1 -1
  32. package/dist/runtime/components/table/columns/2026-05-20/com.shwfed.table.column.number-input/config.vue +32 -0
  33. package/dist/runtime/components/table/columns/2026-05-20/com.shwfed.table.column.number-input/schema.d.ts +1 -0
  34. package/dist/runtime/components/table/columns/2026-05-20/com.shwfed.table.column.number-input/schema.js +1 -1
  35. package/dist/runtime/components/table/columns/2026-05-20/com.shwfed.table.column.switch/config.vue +28 -0
  36. package/dist/runtime/components/table/columns/2026-05-20/com.shwfed.table.column.switch/schema.d.ts +1 -0
  37. package/dist/runtime/components/table/columns/2026-05-20/com.shwfed.table.column.switch/schema.js +1 -1
  38. package/dist/runtime/components/table/columns/2026-05-20/com.shwfed.table.column.switch.local/config.vue +32 -0
  39. package/dist/runtime/components/table/columns/2026-05-20/com.shwfed.table.column.switch.local/schema.d.ts +1 -0
  40. package/dist/runtime/components/table/columns/2026-05-20/com.shwfed.table.column.switch.local/schema.js +1 -1
  41. package/dist/runtime/components/table/columns/2026-05-20/com.shwfed.table.column.text-input/config.vue +32 -0
  42. package/dist/runtime/components/table/columns/2026-05-20/com.shwfed.table.column.text-input/schema.d.ts +1 -0
  43. package/dist/runtime/components/table/columns/2026-05-20/com.shwfed.table.column.text-input/schema.js +1 -1
  44. package/dist/runtime/components/table/columns/2026-05-25/com.shwfed.table.column.combobox-multi/config.d.vue.ts +2 -0
  45. package/dist/runtime/components/table/columns/2026-05-25/com.shwfed.table.column.combobox-multi/config.vue +32 -0
  46. package/dist/runtime/components/table/columns/2026-05-25/com.shwfed.table.column.combobox-multi/config.vue.d.ts +2 -0
  47. package/dist/runtime/components/table/columns/2026-05-25/com.shwfed.table.column.combobox-multi/schema.d.ts +1 -0
  48. package/dist/runtime/components/table/columns/2026-05-25/com.shwfed.table.column.combobox-multi/schema.js +1 -1
  49. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-multi/config.d.vue.ts +2 -0
  50. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-multi/config.vue +22 -0
  51. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-multi/config.vue.d.ts +2 -0
  52. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-multi/schema.d.ts +1 -0
  53. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-multi/schema.js +1 -1
  54. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-single/config.d.vue.ts +2 -0
  55. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-single/config.vue +22 -0
  56. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-single/config.vue.d.ts +2 -0
  57. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-single/schema.d.ts +1 -0
  58. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-single/schema.js +1 -1
  59. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-multi/config.d.vue.ts +2 -0
  60. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-multi/config.vue +22 -0
  61. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-multi/config.vue.d.ts +2 -0
  62. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-multi/schema.d.ts +1 -0
  63. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-multi/schema.js +1 -1
  64. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-single/config.d.vue.ts +2 -0
  65. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-single/config.vue +22 -0
  66. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-single/config.vue.d.ts +2 -0
  67. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-single/schema.d.ts +1 -0
  68. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-single/schema.js +1 -1
  69. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-multi/config.d.vue.ts +2 -0
  70. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-multi/config.vue +22 -0
  71. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-multi/config.vue.d.ts +2 -0
  72. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-multi/schema.d.ts +1 -0
  73. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-multi/schema.js +1 -1
  74. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-single/config.d.vue.ts +2 -0
  75. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-single/config.vue +22 -0
  76. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-single/config.vue.d.ts +2 -0
  77. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-single/schema.d.ts +1 -0
  78. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-single/schema.js +1 -1
  79. package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.tree-combobox-multi/config.d.vue.ts +2 -0
  80. package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.tree-combobox-multi/config.vue +22 -0
  81. package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.tree-combobox-multi/config.vue.d.ts +2 -0
  82. package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.tree-combobox-multi/schema.d.ts +1 -0
  83. package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.tree-combobox-multi/schema.js +1 -1
  84. package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.tree-combobox-single/config.d.vue.ts +2 -0
  85. package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.tree-combobox-single/config.vue +22 -0
  86. package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.tree-combobox-single/config.vue.d.ts +2 -0
  87. package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.tree-combobox-single/schema.d.ts +1 -0
  88. package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.tree-combobox-single/schema.js +1 -1
  89. package/dist/runtime/components/table/columns/2026-06-17/com.shwfed.table.column.date-input/config.vue +32 -0
  90. package/dist/runtime/components/table/columns/2026-06-17/com.shwfed.table.column.date-input/schema.d.ts +1 -0
  91. package/dist/runtime/components/table/columns/2026-06-17/com.shwfed.table.column.date-input/schema.js +1 -1
  92. package/dist/runtime/components/table/columns/2026-06-22/com.shwfed.table.column.date-range-input/config.vue +32 -0
  93. package/dist/runtime/components/table/columns/2026-06-22/com.shwfed.table.column.date-range-input/schema.d.ts +1 -0
  94. package/dist/runtime/components/table/columns/2026-06-22/com.shwfed.table.column.date-range-input/schema.js +1 -1
  95. package/dist/runtime/components/table/columns/2026-07-16/com.shwfed.table.column.upload/config.vue +32 -0
  96. package/dist/runtime/components/table/columns/2026-07-16/com.shwfed.table.column.upload/schema.d.ts +1 -0
  97. package/dist/runtime/components/table/columns/2026-07-16/com.shwfed.table.column.upload/schema.js +1 -1
  98. package/dist/runtime/components/table/index.d.vue.ts +1 -0
  99. package/dist/runtime/components/table/index.vue +12 -1
  100. package/dist/runtime/components/table/index.vue.d.ts +1 -0
  101. package/dist/runtime/components/table/utils/shared.d.ts +2 -1
  102. package/dist/runtime/components/table/utils/shared.js +24 -1
  103. package/package.json +1 -1
@@ -42,6 +42,17 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
42
42
  readonly mode: "formula" | "prefill";
43
43
  readonly expression: string;
44
44
  } | undefined;
45
+ readonly validations?: readonly {
46
+ readonly message: readonly [{
47
+ readonly locale: "zh";
48
+ readonly message: string;
49
+ }, ...{
50
+ readonly locale: "en" | "ja" | "ko";
51
+ readonly message: string;
52
+ }[]];
53
+ readonly warning?: boolean | undefined;
54
+ readonly when: string;
55
+ }[] | undefined;
45
56
  readonly addon?: {
46
57
  readonly size: "default" | "sm" | "xs";
47
58
  readonly style?: string | undefined;
@@ -109,17 +120,6 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
109
120
  readonly variant?: "default" | "link" | "destructive" | "primary" | "ghost" | undefined;
110
121
  }[];
111
122
  } | undefined;
112
- readonly validations?: readonly {
113
- readonly message: readonly [{
114
- readonly locale: "zh";
115
- readonly message: string;
116
- }, ...{
117
- readonly locale: "en" | "ja" | "ko";
118
- readonly message: string;
119
- }[]];
120
- readonly warning?: boolean | undefined;
121
- readonly when: string;
122
- }[] | undefined;
123
123
  readonly precision?: number | undefined;
124
124
  readonly roundingMode?: "round" | "floor" | "ceil" | undefined;
125
125
  readonly valueAsString?: boolean | undefined;
@@ -165,6 +165,17 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
165
165
  readonly mode: "formula" | "prefill";
166
166
  readonly expression: string;
167
167
  } | undefined;
168
+ readonly validations?: readonly {
169
+ readonly message: readonly [{
170
+ readonly locale: "zh";
171
+ readonly message: string;
172
+ }, ...{
173
+ readonly locale: "en" | "ja" | "ko";
174
+ readonly message: string;
175
+ }[]];
176
+ readonly warning?: boolean | undefined;
177
+ readonly when: string;
178
+ }[] | undefined;
168
179
  readonly addon?: {
169
180
  readonly size: "default" | "sm" | "xs";
170
181
  readonly style?: string | undefined;
@@ -232,17 +243,6 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
232
243
  readonly variant?: "default" | "link" | "destructive" | "primary" | "ghost" | undefined;
233
244
  }[];
234
245
  } | undefined;
235
- readonly validations?: readonly {
236
- readonly message: readonly [{
237
- readonly locale: "zh";
238
- readonly message: string;
239
- }, ...{
240
- readonly locale: "en" | "ja" | "ko";
241
- readonly message: string;
242
- }[]];
243
- readonly warning?: boolean | undefined;
244
- readonly when: string;
245
- }[] | undefined;
246
246
  readonly precision?: number | undefined;
247
247
  readonly roundingMode?: "round" | "floor" | "ceil" | undefined;
248
248
  readonly valueAsString?: boolean | undefined;
@@ -42,6 +42,17 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
42
42
  readonly mode: "formula" | "prefill";
43
43
  readonly expression: string;
44
44
  } | undefined;
45
+ readonly validations?: readonly {
46
+ readonly message: readonly [{
47
+ readonly locale: "zh";
48
+ readonly message: string;
49
+ }, ...{
50
+ readonly locale: "en" | "ja" | "ko";
51
+ readonly message: string;
52
+ }[]];
53
+ readonly warning?: boolean | undefined;
54
+ readonly when: string;
55
+ }[] | undefined;
45
56
  readonly addon?: {
46
57
  readonly size: "default" | "sm" | "xs";
47
58
  readonly style?: string | undefined;
@@ -109,17 +120,6 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
109
120
  readonly variant?: "default" | "link" | "destructive" | "primary" | "ghost" | undefined;
110
121
  }[];
111
122
  } | undefined;
112
- readonly validations?: readonly {
113
- readonly message: readonly [{
114
- readonly locale: "zh";
115
- readonly message: string;
116
- }, ...{
117
- readonly locale: "en" | "ja" | "ko";
118
- readonly message: string;
119
- }[]];
120
- readonly warning?: boolean | undefined;
121
- readonly when: string;
122
- }[] | undefined;
123
123
  readonly precision?: number | undefined;
124
124
  readonly roundingMode?: "round" | "floor" | "ceil" | undefined;
125
125
  readonly valueAsString?: boolean | undefined;
@@ -165,6 +165,17 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
165
165
  readonly mode: "formula" | "prefill";
166
166
  readonly expression: string;
167
167
  } | undefined;
168
+ readonly validations?: readonly {
169
+ readonly message: readonly [{
170
+ readonly locale: "zh";
171
+ readonly message: string;
172
+ }, ...{
173
+ readonly locale: "en" | "ja" | "ko";
174
+ readonly message: string;
175
+ }[]];
176
+ readonly warning?: boolean | undefined;
177
+ readonly when: string;
178
+ }[] | undefined;
168
179
  readonly addon?: {
169
180
  readonly size: "default" | "sm" | "xs";
170
181
  readonly style?: string | undefined;
@@ -232,17 +243,6 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
232
243
  readonly variant?: "default" | "link" | "destructive" | "primary" | "ghost" | undefined;
233
244
  }[];
234
245
  } | undefined;
235
- readonly validations?: readonly {
236
- readonly message: readonly [{
237
- readonly locale: "zh";
238
- readonly message: string;
239
- }, ...{
240
- readonly locale: "en" | "ja" | "ko";
241
- readonly message: string;
242
- }[]];
243
- readonly warning?: boolean | undefined;
244
- readonly when: string;
245
- }[] | undefined;
246
246
  readonly precision?: number | undefined;
247
247
  readonly roundingMode?: "round" | "floor" | "ceil" | undefined;
248
248
  readonly valueAsString?: boolean | undefined;
@@ -1,7 +1,7 @@
1
1
  <script setup>
2
2
  import { cel as _rawCel } from "../../utils/cel";
3
3
  import { TZDate } from "@date-fns/tz";
4
- import { Effect } from "effect";
4
+ import { Cause, Effect } from "effect";
5
5
  import { Fetch } from "fx-fetch";
6
6
  import { computed } from "vue";
7
7
  import {
@@ -17,8 +17,10 @@ import { provideDerivedQuiescence, useDerived } from "./utils/derived";
17
17
  import { useFormHistory } from "./utils/history";
18
18
  import { evaluateInitial } from "./utils/initial";
19
19
  import { provideEventTarget } from "../../share/event-bus";
20
+ import * as stateWriteOp from "../operations/2026-07-19/com.shwfed.operation.form.state.write/schema";
20
21
  import { provideFormReadonly } from "./utils/readonly";
21
22
  import { provideFormState } from "./utils/state";
23
+ import { mergeAtPath } from "./utils/state-write";
22
24
  import { provideOptionsRegistry, provideSelectionsRegistry } from "../../utils/selections-registry";
23
25
  import { provideValidation } from "./utils/validation";
24
26
  defineOptions({ name: "ShwfedForm" });
@@ -116,7 +118,60 @@ provideEventTarget(formInstanceId, {
116
118
  }),
117
119
  "undo": () => Effect.sync(formHistory.undo),
118
120
  "redo": () => Effect.sync(formHistory.redo),
119
- "reset-to-initial": () => Effect.sync(formHistory.reset)
121
+ "reset-to-initial": () => Effect.sync(formHistory.reset),
122
+ // Host-coupled `state.write` op: it writes into THIS form's state bag, which
123
+ // a generic handler can't reach (the bag lives on the Vue inject chain), so
124
+ // like the table's `add-row` it ships no `runtime.ts` and is hand-wired here.
125
+ // It is the button's「写入表单状态」capability lifted out so any trigger list can
126
+ // dispatch it — but, being one step of a chain, it carries no bracketing
127
+ // 写入前/写入后 lists (the surrounding chain is the bracket).
128
+ //
129
+ // Params are decoded with the same loose posture the table uses for
130
+ // `add-row` — a plain cast, tolerating absent/malformed shapes — since the
131
+ // authoritative validation already ran in the trigger editor against the op's
132
+ // schema. Rows commit in LIST ORDER via `setAt` (dirty-marking is intended —
133
+ // an op write is user intent, as with the button and per `state.ts`'s
134
+ // "explicit clear counts as a touch"). Unlike the button there is no
135
+ // "commit out of the form I'm in" walk: the op explicitly targets THIS form,
136
+ // so it writes THIS form's own bag.
137
+ //
138
+ // Each `value` is evaluated with the emit-site evaluator (`cel` — the
139
+ // dispatching button's own scope, where a row action's `row` is live) when
140
+ // present, else the form's own `$cel`; both bind `{ steps }` (the chain's
141
+ // earlier outputs) into the context. A row whose evaluation or write throws
142
+ // logs UNGATED — designers configure inside the production-built app, so an
143
+ // `import.meta.dev`-gated log is one they can never see (see the button
144
+ // runtime's note) — then HALTS the remaining rows and the rest of the trigger
145
+ // chain via a defect, keeping the handler's `void` error channel (the guard
146
+ // shape `validate` uses above). `tapErrorCause` covers both a failed
147
+ // evaluation and a throwing `setAt`.
148
+ [stateWriteOp.type]: (params, cel, step) => {
149
+ const writes = params?.writes ?? [];
150
+ const steps = step?.outputs() ?? {};
151
+ return Effect.forEach(
152
+ writes,
153
+ (write) => {
154
+ const path = write.path?.trim() ?? "";
155
+ if (path.length === 0) return Effect.void;
156
+ const evaluated = cel ? cel(write.value, { steps }) : $cel(write.value, { steps });
157
+ return Effect.map(evaluated, (result) => {
158
+ formState.setAt(path, mergeAtPath(formState.getAt(path), result));
159
+ }).pipe(
160
+ Effect.tapErrorCause((cause) => Effect.sync(() => {
161
+ console.error(
162
+ `[shwfed-form] state.write: failed to write "${path}" for ${formInstanceId}:`,
163
+ Cause.squash(cause)
164
+ );
165
+ })),
166
+ // Re-raise as a defect so the chain halts (later rows + the rest of
167
+ // the trigger list stay skipped) without widening the infallible
168
+ // `void` error channel — same reason `validate` uses `Effect.die`.
169
+ Effect.catchAllCause((cause) => Effect.die(Cause.squash(cause)))
170
+ );
171
+ },
172
+ { discard: true }
173
+ );
174
+ }
120
175
  });
121
176
  defineExpose({
122
177
  seeded,
@@ -26,6 +26,11 @@ export declare const metadata: {
26
26
  readonly id: "reset-to-initial";
27
27
  readonly name: "重置为初始值";
28
28
  readonly icon: "fluent:arrow-reset-20-regular";
29
+ }, {
30
+ readonly id: "com.shwfed.operation.form.state.write";
31
+ readonly compatibilityDate: "2026-07-19";
32
+ readonly name: "写入表单状态";
33
+ readonly icon: "fluent:document-edit-20-regular";
29
34
  }];
30
35
  };
31
36
  type AnySchema = Schema.Schema<any, any, never>;
@@ -2,6 +2,7 @@ import { Schema } from "effect";
2
2
  import { Expression, HttpRequestResult } from "../../share/expression.js";
3
3
  import { allFieldSchemas } from "./utils/resolve.js";
4
4
  import { registerFormVariablesIfAbsent } from "./utils/form-vars.js";
5
+ import * as stateWriteOp from "../operations/2026-07-19/com.shwfed.operation.form.state.write/schema.js";
5
6
  import { md } from "../../share/markdown.js";
6
7
  import {
7
8
  LayoutSet,
@@ -23,7 +24,19 @@ export const metadata = {
23
24
  { id: "validate", name: "\u6821\u9A8C", icon: "fluent:checkmark-circle-20-regular" },
24
25
  { id: "undo", name: "\u64A4\u9500", icon: "fluent:arrow-undo-20-regular" },
25
26
  { id: "redo", name: "\u91CD\u505A", icon: "fluent:arrow-redo-20-regular" },
26
- { id: "reset-to-initial", name: "\u91CD\u7F6E\u4E3A\u521D\u59CB\u503C", icon: "fluent:arrow-reset-20-regular" }
27
+ { id: "reset-to-initial", name: "\u91CD\u7F6E\u4E3A\u521D\u59CB\u503C", icon: "fluent:arrow-reset-20-regular" },
28
+ // Parameterized (but host-coupled) op: `compatibilityDate` marks it as
29
+ // carrying params, so the trigger editor renders the op's `config.vue` and
30
+ // seeds its `defaults()`. Like the table's `add-row` it ships no
31
+ // `runtime.ts` — the write touches this form instance's private state bag,
32
+ // so the handler is hand-wired in `index.vue`'s `provideEventTarget`. `id`
33
+ // doubles as the operation-block `type`.
34
+ {
35
+ id: stateWriteOp.type,
36
+ compatibilityDate: stateWriteOp.compatibilityDate,
37
+ name: stateWriteOp.metadata.name,
38
+ icon: stateWriteOp.metadata.icon
39
+ }
27
40
  ]
28
41
  };
29
42
  function unitFields(configure) {
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Merge one write row's `next` value into the `current` value at its path.
3
+ *
4
+ * Only deep-merge when both sides are records. Otherwise the new value
5
+ * replaces wholesale — scalars, arrays, null, and mixed-type writes all fall
6
+ * through to a plain replace (`setAt(path, next)` at the call site). Arrays
7
+ * nested inside two merged records replace last-write-wins, per `mergeObjects`.
8
+ */
9
+ export declare function mergeAtPath(current: unknown, next: unknown): unknown;
@@ -0,0 +1,16 @@
1
+ import { createDefu } from "defu";
2
+ const mergeObjects = createDefu((obj, key, value) => {
3
+ if (Array.isArray(obj[key]) && Array.isArray(value)) {
4
+ obj[key] = value;
5
+ return true;
6
+ }
7
+ });
8
+ function isPlainObject(v) {
9
+ return typeof v === "object" && v !== null && !Array.isArray(v);
10
+ }
11
+ export function mergeAtPath(current, next) {
12
+ if (isPlainObject(current) && isPlainObject(next)) {
13
+ return mergeObjects({ ...next }, current);
14
+ }
15
+ return next;
16
+ }
@@ -0,0 +1,21 @@
1
+ import { type Value } from './schema.js';
2
+ type __VLS_ModelProps = {
3
+ modelValue: Value;
4
+ };
5
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
6
+ "update:modelValue": (value: {
7
+ readonly writes: readonly {
8
+ readonly path: string;
9
+ readonly value: string;
10
+ }[];
11
+ }) => any;
12
+ }, string, import("vue").PublicProps, Readonly<__VLS_ModelProps> & Readonly<{
13
+ "onUpdate:modelValue"?: ((value: {
14
+ readonly writes: readonly {
15
+ readonly path: string;
16
+ readonly value: string;
17
+ }[];
18
+ }) => any) | undefined;
19
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
20
+ declare const _default: typeof __VLS_export;
21
+ export default _default;
@@ -0,0 +1,100 @@
1
+ <script setup>
2
+ import { computed } from "vue";
3
+ import { Icon } from "@iconify/vue";
4
+ import { Button } from "../../../ui/button";
5
+ import { Field, FieldLabel } from "../../../ui/field";
6
+ import { ExpressionEditor } from "../../../ui/expression-editor";
7
+ import { Markdown } from "../../../ui/markdown";
8
+ import { InputGroupButton } from "../../../ui/input-group";
9
+ import { getStructFieldDescription, getStructFieldTitle } from "../../../../share/schema-meta";
10
+ import { schema } from "./schema";
11
+ defineOptions({ name: "ShwfedFormStateWriteOperationConfig" });
12
+ const value = defineModel({ type: null, ...{ required: true } });
13
+ const opSchema = schema(() => {
14
+ });
15
+ const fieldTitle = (f) => getStructFieldTitle(opSchema, f) ?? f;
16
+ const fieldDescription = (f) => getStructFieldDescription(opSchema, f);
17
+ const writes = computed(() => value.value.writes ?? []);
18
+ function patchWrites(next) {
19
+ value.value = { ...value.value, writes: next };
20
+ }
21
+ function updateRow(index, patch) {
22
+ patchWrites(writes.value.map((w, i) => i === index ? { ...w, ...patch } : w));
23
+ }
24
+ function addRow() {
25
+ patchWrites([...writes.value, { path: "", value: "" }]);
26
+ }
27
+ function removeRow(index) {
28
+ patchWrites(writes.value.filter((_, i) => i !== index));
29
+ }
30
+ </script>
31
+
32
+ <template>
33
+ <Field orientation="vertical">
34
+ <FieldLabel class="text-xs text-zinc-500">
35
+ <template
36
+ v-if="fieldDescription('writes')"
37
+ #tooltip
38
+ >
39
+ <Markdown
40
+ :source="fieldDescription('writes')"
41
+ block
42
+ class="prose prose-sm prose-zinc"
43
+ />
44
+ </template>
45
+ {{ fieldTitle("writes") }}
46
+ </FieldLabel>
47
+
48
+ <div class="flex flex-col gap-3">
49
+ <!-- One write item per multiline editor: the monofont binding path as a
50
+ full-width `leading` header row, the value expression wrapping below
51
+ (its own `{x}` badge), and a destructive delete in the `trailing`
52
+ bottom row. Reuses the ExpressionEditor's own InputGroup. -->
53
+ <ExpressionEditor
54
+ v-for="(row, index) in writes"
55
+ :key="index"
56
+ :model-value="row.value"
57
+ multiline
58
+ placeholder="值,如 selected[?0].?exchangeRate"
59
+ class="min-h-16"
60
+ @update:model-value="(v) => updateRow(index, { value: v })"
61
+ >
62
+ <template #leading>
63
+ <input
64
+ type="text"
65
+ data-slot="state-write-path"
66
+ :value="row.path"
67
+ placeholder="路径"
68
+ class="w-full min-w-0 bg-transparent font-mono text-sm text-zinc-700 outline-none placeholder:text-zinc-300"
69
+ :aria-label="`\u5199\u5165\u8DEF\u5F84 ${index + 1}`"
70
+ @input="updateRow(index, { path: $event.target.value })"
71
+ >
72
+ </template>
73
+ <template #trailing>
74
+ <InputGroupButton
75
+ variant="destructive"
76
+ size="icon-xs"
77
+ as-child
78
+ >
79
+ <button
80
+ type="button"
81
+ :aria-label="`\u79FB\u9664\u5199\u5165\u9879 ${index + 1}`"
82
+ @click="removeRow(index)"
83
+ >
84
+ <Icon icon="fluent:delete-20-regular" />
85
+ </button>
86
+ </InputGroupButton>
87
+ </template>
88
+ </ExpressionEditor>
89
+
90
+ <Button
91
+ type="button"
92
+ class="justify-center"
93
+ @click="addRow"
94
+ >
95
+ <Icon icon="fluent:add-20-regular" />
96
+ <span>添加写入项</span>
97
+ </Button>
98
+ </div>
99
+ </Field>
100
+ </template>
@@ -0,0 +1,21 @@
1
+ import { type Value } from './schema.js';
2
+ type __VLS_ModelProps = {
3
+ modelValue: Value;
4
+ };
5
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
6
+ "update:modelValue": (value: {
7
+ readonly writes: readonly {
8
+ readonly path: string;
9
+ readonly value: string;
10
+ }[];
11
+ }) => any;
12
+ }, string, import("vue").PublicProps, Readonly<__VLS_ModelProps> & Readonly<{
13
+ "onUpdate:modelValue"?: ((value: {
14
+ readonly writes: readonly {
15
+ readonly path: string;
16
+ readonly value: string;
17
+ }[];
18
+ }) => any) | undefined;
19
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
20
+ declare const _default: typeof __VLS_export;
21
+ export default _default;
@@ -0,0 +1,18 @@
1
+ import { Schema } from 'effect';
2
+ import type { Environment } from '../../../../vendor/cel-js/lib/index.js';
3
+ export declare const type: "com.shwfed.operation.form.state.write";
4
+ export declare const compatibilityDate: "2026-07-19";
5
+ export declare const metadata: {
6
+ readonly name: "写入表单状态";
7
+ readonly icon: "fluent:document-edit-20-regular";
8
+ readonly description: "按列表顺序把每个 CEL 求值结果写入目标表单状态的对应绑定路径;作为触发链中的一步派发";
9
+ };
10
+ export declare function schema(configure: (env: Environment) => void): Schema.Struct<{
11
+ writes: Schema.Array$<Schema.Struct<{
12
+ path: Schema.SchemaClass<string, string, never>;
13
+ value: Schema.Schema<string, string, never>;
14
+ }>>;
15
+ }>;
16
+ export type Value = Schema.Schema.Type<ReturnType<typeof schema>>;
17
+ export type WriteValue = Value['writes'][number];
18
+ export declare function defaults(): Partial<Value>;
@@ -0,0 +1,47 @@
1
+ import { Schema } from "effect";
2
+ import { Expression } from "../../../../share/expression.js";
3
+ import { md } from "../../../../share/markdown.js";
4
+ import { registerStepsVariableIfAbsent } from "../../utils/step-vars.js";
5
+ export const type = "com.shwfed.operation.form.state.write";
6
+ export const compatibilityDate = "2026-07-19";
7
+ export const metadata = {
8
+ name: "\u5199\u5165\u8868\u5355\u72B6\u6001",
9
+ icon: "fluent:document-edit-20-regular",
10
+ description: "\u6309\u5217\u8868\u987A\u5E8F\u628A\u6BCF\u4E2A CEL \u6C42\u503C\u7ED3\u679C\u5199\u5165\u76EE\u6807\u8868\u5355\u72B6\u6001\u7684\u5BF9\u5E94\u7ED1\u5B9A\u8DEF\u5F84\uFF1B\u4F5C\u4E3A\u89E6\u53D1\u94FE\u4E2D\u7684\u4E00\u6B65\u6D3E\u53D1"
11
+ };
12
+ export function schema(configure) {
13
+ const withSteps = (env) => {
14
+ configure(env);
15
+ registerStepsVariableIfAbsent(env);
16
+ };
17
+ const Write = Schema.Struct({
18
+ path: Schema.String.annotations({
19
+ title: "\u8DEF\u5F84",
20
+ description: "\u5199\u5165\u7684\u7ED1\u5B9A\u8DEF\u5F84\uFF0C\u5982 `dataJson.cus_currency`"
21
+ }),
22
+ value: Expression({ configure: withSteps }).annotations({
23
+ title: "\u503C",
24
+ description: '\u6C42\u503C\u7ED3\u679C\u5199\u5165\u8BE5\u8DEF\u5F84\uFF1B\u53EF\u7ECF `steps["<\u6B65\u9AA4\u6807\u8BC6>"]` \u5F15\u7528\u540C\u4E00\u89E6\u53D1\u94FE\u4E2D\u524D\u5E8F\u6B65\u9AA4\u7684\u8F93\u51FA'
25
+ })
26
+ });
27
+ return Schema.Struct({
28
+ writes: Schema.Array(Write).annotations({
29
+ title: "\u5199\u5165\u503C",
30
+ description: md`
31
+ 按列表顺序逐行求值并写入到目标表单的状态:每行的 \`值\`
32
+ 表达式结果写入其 \`路径\`。对象值与当前值深合并(数组整体替换),
33
+ 其他类型直接替换。留空表示不进行任何写入。
34
+ `
35
+ })
36
+ }).annotations({
37
+ title: "FormStateWriteOperation",
38
+ description: md`
39
+ 按顺序将每个 CEL 表达式的结果写回目标表单状态的对应路径。作为触发链中的
40
+ 一步派发;写入值可经 \`steps["<步骤标识>"]\` 引用同一触发链中前序步骤的输出。
41
+ 任一行求值或写入失败将中止本次触发链——其后各行与后续操作不再执行。
42
+ `
43
+ });
44
+ }
45
+ export function defaults() {
46
+ return { writes: [] };
47
+ }
@@ -23,6 +23,7 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
23
23
  readonly locale: "en" | "ja" | "ko";
24
24
  readonly message: string;
25
25
  }[]] | undefined;
26
+ readonly required?: string | undefined;
26
27
  readonly compatibilityDate: "2026-05-20";
27
28
  readonly grow?: boolean | undefined;
28
29
  readonly items: readonly {
@@ -87,6 +88,7 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
87
88
  readonly locale: "en" | "ja" | "ko";
88
89
  readonly message: string;
89
90
  }[]] | undefined;
91
+ readonly required?: string | undefined;
90
92
  readonly compatibilityDate: "2026-05-20";
91
93
  readonly grow?: boolean | undefined;
92
94
  readonly items: readonly {
@@ -77,6 +77,17 @@ const readonlyModel = computed({
77
77
  }
78
78
  }
79
79
  });
80
+ const requiredModel = computed({
81
+ get: () => value.value.required ?? "",
82
+ set: (v) => {
83
+ if (v === "") {
84
+ const { required: _omit, ...rest } = value.value;
85
+ value.value = rest;
86
+ } else {
87
+ value.value = { ...value.value, required: v };
88
+ }
89
+ }
90
+ });
80
91
  const derivedModel = computed({
81
92
  get: () => value.value.derived,
82
93
  set: (v) => {
@@ -479,6 +490,27 @@ function setItemTooltip(index, tooltip) {
479
490
  :extra-vars="ROW_VARS"
480
491
  />
481
492
  </Field>
493
+ <Field orientation="vertical">
494
+ <FieldLabel class="text-xs text-zinc-500">
495
+ <template
496
+ v-if="fieldDescription('required')"
497
+ #tooltip
498
+ >
499
+ <Markdown
500
+ :source="fieldDescription('required')"
501
+ block
502
+ class="prose prose-sm prose-zinc"
503
+ />
504
+ </template>
505
+ {{ fieldTitle("required") }}
506
+ </FieldLabel>
507
+ <ExpressionEditor
508
+ v-model="requiredModel"
509
+ placeholder="例:row.type == 'company'"
510
+ result-type="bool"
511
+ :extra-vars="ROW_VARS"
512
+ />
513
+ </Field>
482
514
  <Field
483
515
  orientation="vertical"
484
516
  class="col-span-2"
@@ -23,6 +23,7 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
23
23
  readonly locale: "en" | "ja" | "ko";
24
24
  readonly message: string;
25
25
  }[]] | undefined;
26
+ readonly required?: string | undefined;
26
27
  readonly compatibilityDate: "2026-05-20";
27
28
  readonly grow?: boolean | undefined;
28
29
  readonly items: readonly {
@@ -87,6 +88,7 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
87
88
  readonly locale: "en" | "ja" | "ko";
88
89
  readonly message: string;
89
90
  }[]] | undefined;
91
+ readonly required?: string | undefined;
90
92
  readonly compatibilityDate: "2026-05-20";
91
93
  readonly grow?: boolean | undefined;
92
94
  readonly items: readonly {
@@ -158,6 +158,7 @@ export declare function schema(configure: (env: Environment) => void): Schema.St
158
158
  readonly locale: "en" | "ja" | "ko";
159
159
  readonly message: string;
160
160
  }[]], never>>;
161
+ required: Schema.optional<Schema.Schema<string, string, never>>;
161
162
  id: Schema.refine<string, typeof Schema.String>;
162
163
  groupId: Schema.optional<typeof Schema.UUID>;
163
164
  type: Schema.Literal<["com.shwfed.table.column.combobox-single"]>;
@@ -49,7 +49,7 @@ export function schema(configure) {
49
49
  return Schema.Struct({
50
50
  type: Schema.Literal(type),
51
51
  compatibilityDate: Schema.Literal(compatibilityDate),
52
- ...editableColumnFields(),
52
+ ...editableColumnFields(configure),
53
53
  placeholder: Schema.optional(Locale.annotations({
54
54
  title: "\u5360\u4F4D\u7B26",
55
55
  description: "\u672A\u9009\u4E2D\u4EFB\u4F55\u9009\u9879\u65F6\u8F93\u5165\u6846\u4E2D\u7684\u5360\u4F4D\u6587\u672C"
@@ -138,6 +138,17 @@ const readonlyModel = computed({
138
138
  }
139
139
  }
140
140
  });
141
+ const requiredModel = computed({
142
+ get: () => value.value.required ?? "",
143
+ set: (v) => {
144
+ if (v === "") {
145
+ const { required: _drop, ...rest } = value.value;
146
+ value.value = rest;
147
+ } else {
148
+ value.value = { ...value.value, required: v };
149
+ }
150
+ }
151
+ });
141
152
  const derivedModel = computed({
142
153
  get: () => value.value.derived,
143
154
  set: (v) => {
@@ -575,6 +586,27 @@ function onMaxChange(v) {
575
586
  :extra-vars="ROW_VARS"
576
587
  />
577
588
  </Field>
589
+ <Field orientation="vertical">
590
+ <FieldLabel class="text-xs text-zinc-500">
591
+ <template
592
+ v-if="fieldDescription('required')"
593
+ #tooltip
594
+ >
595
+ <Markdown
596
+ :source="fieldDescription('required')"
597
+ block
598
+ class="prose prose-sm prose-zinc"
599
+ />
600
+ </template>
601
+ {{ fieldTitle("required") }}
602
+ </FieldLabel>
603
+ <ExpressionEditor
604
+ v-model="requiredModel"
605
+ placeholder="例:row.type == 'company'"
606
+ result-type="bool"
607
+ :extra-vars="ROW_VARS"
608
+ />
609
+ </Field>
578
610
  <Field
579
611
  orientation="vertical"
580
612
  class="col-span-2"
@@ -205,6 +205,7 @@ export declare function schema(configure: (env: Environment) => void): Schema.St
205
205
  readonly message: string;
206
206
  }[]], never>>;
207
207
  hidden: Schema.optional<Schema.SchemaClass<boolean, boolean, never>>;
208
+ required: Schema.optional<Schema.Schema<string, string, never>>;
208
209
  id: Schema.refine<string, typeof Schema.String>;
209
210
  groupId: Schema.optional<typeof Schema.UUID>;
210
211
  type: Schema.Literal<["com.shwfed.table.column.number-input"]>;