@shwfed/config 3.0.13 → 3.0.15

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 (122) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/module.mjs +20 -1
  3. package/dist/runtime/components/actions/ai-l1.md +1 -1
  4. package/dist/runtime/components/actions/buttons/2026-05-15/com.shwfed.actions.button.event.dispatch/prompt.md +1 -1
  5. package/dist/runtime/components/actions/buttons/2026-05-21/com.shwfed.actions.button.http.download/schema.d.ts +1 -1
  6. package/dist/runtime/components/actions/buttons/2026-05-21/com.shwfed.actions.button.http.download/schema.js +2 -2
  7. package/dist/runtime/components/actions/buttons/2026-07-13/com.shwfed.actions.button.state.write/prompt.md +1 -1
  8. package/dist/runtime/components/actions/buttons/2026-07-13/com.shwfed.actions.button.state.write/runtime.vue +1 -1
  9. package/dist/runtime/components/actions/buttons/2026-07-13/com.shwfed.actions.button.state.write/schema.d.ts +2 -4
  10. package/dist/runtime/components/actions/buttons/2026-07-13/com.shwfed.actions.button.state.write/schema.js +1 -1
  11. package/dist/runtime/components/actions/components/trigger-row-scope.vue +6 -3
  12. package/dist/runtime/components/actions/utils/steps.d.ts +1 -1
  13. package/dist/runtime/components/config/blocks/2026-07-17/com.shwfed.block.invoice.digital/config.d.vue.ts +2 -0
  14. package/dist/runtime/components/config/blocks/2026-07-17/com.shwfed.block.invoice.digital/config.vue +10 -2
  15. package/dist/runtime/components/config/blocks/2026-07-17/com.shwfed.block.invoice.digital/config.vue.d.ts +2 -0
  16. package/dist/runtime/components/config/blocks/2026-07-17/com.shwfed.block.invoice.digital/runtime.d.vue.ts +2 -0
  17. package/dist/runtime/components/config/blocks/2026-07-17/com.shwfed.block.invoice.digital/runtime.vue.d.ts +2 -0
  18. package/dist/runtime/components/config/blocks/2026-07-17/com.shwfed.block.invoice.digital/schema.d.ts +1 -0
  19. package/dist/runtime/components/config/blocks/2026-07-17/com.shwfed.block.invoice.digital/schema.js +5 -0
  20. package/dist/runtime/components/config/blocks/2026-07-17/com.shwfed.block.invoice.realestate.lease/config.d.vue.ts +96 -0
  21. package/dist/runtime/components/config/blocks/2026-07-17/com.shwfed.block.invoice.realestate.lease/config.vue +385 -0
  22. package/dist/runtime/components/config/blocks/2026-07-17/com.shwfed.block.invoice.realestate.lease/config.vue.d.ts +96 -0
  23. package/dist/runtime/components/config/blocks/2026-07-17/com.shwfed.block.invoice.realestate.lease/items-colgroup.d.vue.ts +3 -0
  24. package/dist/runtime/components/config/blocks/2026-07-17/com.shwfed.block.invoice.realestate.lease/items-colgroup.vue +20 -0
  25. package/dist/runtime/components/config/blocks/2026-07-17/com.shwfed.block.invoice.realestate.lease/items-colgroup.vue.d.ts +3 -0
  26. package/dist/runtime/components/config/blocks/2026-07-17/com.shwfed.block.invoice.realestate.lease/runtime.d.vue.ts +96 -0
  27. package/dist/runtime/components/config/blocks/2026-07-17/com.shwfed.block.invoice.realestate.lease/runtime.vue +177 -0
  28. package/dist/runtime/components/config/blocks/2026-07-17/com.shwfed.block.invoice.realestate.lease/runtime.vue.d.ts +96 -0
  29. package/dist/runtime/components/config/blocks/2026-07-17/com.shwfed.block.invoice.realestate.lease/schema.d.ts +102 -0
  30. package/dist/runtime/components/config/blocks/2026-07-17/com.shwfed.block.invoice.realestate.lease/schema.js +186 -0
  31. package/dist/runtime/components/config/schema.js +2 -2
  32. package/dist/runtime/components/form/fields/2026-04-24/com.shwfed.form.field.combobox.single/config.d.vue.ts +16 -16
  33. package/dist/runtime/components/form/fields/2026-04-24/com.shwfed.form.field.combobox.single/config.vue.d.ts +16 -16
  34. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.daterange/config.d.vue.ts +6 -6
  35. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.daterange/config.vue.d.ts +6 -6
  36. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.datetimerange/config.d.vue.ts +8 -8
  37. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.datetimerange/config.vue.d.ts +8 -8
  38. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.timerange/config.d.vue.ts +2 -2
  39. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.timerange/config.vue.d.ts +2 -2
  40. package/dist/runtime/components/form/fields/2026-05-13/com.shwfed.form.field.combobox.single.remote/config.d.vue.ts +16 -16
  41. package/dist/runtime/components/form/fields/2026-05-13/com.shwfed.form.field.combobox.single.remote/config.vue.d.ts +16 -16
  42. package/dist/runtime/components/form/fields/2026-05-24/com.shwfed.form.field.monthrange/config.d.vue.ts +6 -6
  43. package/dist/runtime/components/form/fields/2026-05-24/com.shwfed.form.field.monthrange/config.vue.d.ts +6 -6
  44. package/dist/runtime/components/form/fields/2026-05-25/com.shwfed.form.field.combobox.multi/config.d.vue.ts +16 -16
  45. package/dist/runtime/components/form/fields/2026-05-25/com.shwfed.form.field.combobox.multi/config.vue.d.ts +16 -16
  46. package/dist/runtime/components/form/fields/2026-06-09/com.shwfed.form.field.upload/prompt.md +1 -1
  47. package/dist/runtime/components/form/fields/2026-07-18/com.shwfed.form.field.richtext/RichTextEditor.d.vue.ts +33 -0
  48. package/dist/runtime/components/form/fields/2026-07-18/com.shwfed.form.field.richtext/RichTextEditor.vue +269 -0
  49. package/dist/runtime/components/form/fields/2026-07-18/com.shwfed.form.field.richtext/RichTextEditor.vue.d.ts +33 -0
  50. package/dist/runtime/components/form/fields/2026-07-18/com.shwfed.form.field.richtext/config.d.vue.ts +107 -0
  51. package/dist/runtime/components/form/fields/2026-07-18/com.shwfed.form.field.richtext/config.vue +370 -0
  52. package/dist/runtime/components/form/fields/2026-07-18/com.shwfed.form.field.richtext/config.vue.d.ts +107 -0
  53. package/dist/runtime/components/form/fields/2026-07-18/com.shwfed.form.field.richtext/extensions.d.ts +27 -0
  54. package/dist/runtime/components/form/fields/2026-07-18/com.shwfed.form.field.richtext/extensions.js +83 -0
  55. package/dist/runtime/components/form/fields/2026-07-18/com.shwfed.form.field.richtext/features.d.ts +21 -0
  56. package/dist/runtime/components/form/fields/2026-07-18/com.shwfed.form.field.richtext/features.js +16 -0
  57. package/dist/runtime/components/form/fields/2026-07-18/com.shwfed.form.field.richtext/indent.d.ts +26 -0
  58. package/dist/runtime/components/form/fields/2026-07-18/com.shwfed.form.field.richtext/indent.js +64 -0
  59. package/dist/runtime/components/form/fields/2026-07-18/com.shwfed.form.field.richtext/prompt.md +33 -0
  60. package/dist/runtime/components/form/fields/2026-07-18/com.shwfed.form.field.richtext/runtime.d.vue.ts +8 -0
  61. package/dist/runtime/components/form/fields/2026-07-18/com.shwfed.form.field.richtext/runtime.vue +121 -0
  62. package/dist/runtime/components/form/fields/2026-07-18/com.shwfed.form.field.richtext/runtime.vue.d.ts +8 -0
  63. package/dist/runtime/components/form/fields/2026-07-18/com.shwfed.form.field.richtext/schema.d.ts +133 -0
  64. package/dist/runtime/components/form/fields/2026-07-18/com.shwfed.form.field.richtext/schema.js +65 -0
  65. package/dist/runtime/components/operations/2026-06-11/com.shwfed.operation.http.request.json/runtime.js +16 -4
  66. package/dist/runtime/components/operations/2026-06-11/com.shwfed.operation.http.request.json/schema.js +10 -3
  67. package/dist/runtime/components/operations/2026-06-15/com.shwfed.operation.http.download/schema.js +2 -2
  68. package/dist/runtime/components/operations/2026-06-15/com.shwfed.operation.navigation/schema.js +1 -1
  69. package/dist/runtime/components/operations/utils/resolve.d.ts +1 -1
  70. package/dist/runtime/components/operations/utils/step-vars.d.ts +16 -4
  71. package/dist/runtime/components/operations/utils/step-vars.js +14 -1
  72. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-multi/config.d.vue.ts +2 -2
  73. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-multi/config.vue.d.ts +2 -2
  74. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-single/config.d.vue.ts +2 -2
  75. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-single/config.vue.d.ts +2 -2
  76. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-multi/config.d.vue.ts +2 -2
  77. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-multi/config.vue.d.ts +2 -2
  78. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-single/config.d.vue.ts +2 -2
  79. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-single/config.vue.d.ts +2 -2
  80. package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.tree-combobox-multi/config.d.vue.ts +2 -2
  81. package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.tree-combobox-multi/config.vue.d.ts +2 -2
  82. package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.tree-combobox-single/config.d.vue.ts +2 -2
  83. package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.tree-combobox-single/config.vue.d.ts +2 -2
  84. package/dist/runtime/components/table/columns/2026-07-16/com.shwfed.table.column.upload/prompt.md +1 -1
  85. package/dist/runtime/components/table/columns/2026-07-16/com.shwfed.table.column.upload/runtime.vue +8 -2
  86. package/dist/runtime/components/ui/calendar/Calendar.d.vue.ts +8 -4
  87. package/dist/runtime/components/ui/calendar/Calendar.vue +39 -10
  88. package/dist/runtime/components/ui/calendar/Calendar.vue.d.ts +8 -4
  89. package/dist/runtime/components/ui/date-picker/DatePicker.vue +3 -1
  90. package/dist/runtime/components/ui/date-picker/DatePickerDatePanel.vue +6 -0
  91. package/dist/runtime/components/ui/date-picker/DatePickerDateTimePanel.vue +6 -0
  92. package/dist/runtime/components/ui/date-picker/DatePickerInput.d.vue.ts +1 -1
  93. package/dist/runtime/components/ui/date-picker/DatePickerInput.vue +7 -9
  94. package/dist/runtime/components/ui/date-picker/DatePickerInput.vue.d.ts +1 -1
  95. package/dist/runtime/components/ui/date-picker/DatePickerTimeInput.d.vue.ts +1 -1
  96. package/dist/runtime/components/ui/date-picker/DatePickerTimeInput.vue.d.ts +1 -1
  97. package/dist/runtime/components/ui/date-range-picker/DateRangePicker.vue +10 -7
  98. package/dist/runtime/components/ui/date-range-picker/DateRangePickerInput.d.vue.ts +3 -5
  99. package/dist/runtime/components/ui/date-range-picker/DateRangePickerInput.vue +28 -26
  100. package/dist/runtime/components/ui/date-range-picker/DateRangePickerInput.vue.d.ts +3 -5
  101. package/dist/runtime/components/ui/date-range-picker/DateRangePickerTimeInput.d.vue.ts +2 -2
  102. package/dist/runtime/components/ui/date-range-picker/DateRangePickerTimeInput.vue.d.ts +2 -2
  103. package/dist/runtime/components/ui/expression-editor/picker-entries.js +1 -1
  104. package/dist/runtime/components/ui/expression-editor/step-chip-extension.js +1 -1
  105. package/dist/runtime/components/ui/expression-editor/step-refs.js +1 -1
  106. package/dist/runtime/components/ui/range-calendar/RangeCalendar.d.vue.ts +5 -5
  107. package/dist/runtime/components/ui/range-calendar/RangeCalendar.vue +22 -5
  108. package/dist/runtime/components/ui/range-calendar/RangeCalendar.vue.d.ts +5 -5
  109. package/dist/runtime/components/ui/range-calendar/RangeCalendarNextButton.vue +0 -1
  110. package/dist/runtime/components/ui/range-calendar/RangeCalendarPrevButton.vue +0 -1
  111. package/dist/runtime/share/event-bus.d.ts +16 -0
  112. package/dist/runtime/share/event-bus.js +18 -13
  113. package/dist/runtime/share/idempotency-key.d.ts +18 -0
  114. package/dist/runtime/share/idempotency-key.js +9 -0
  115. package/dist/runtime/share/slot-renderer.vue +83 -24
  116. package/dist/runtime/utils/cel-context.d.ts +3 -2
  117. package/dist/runtime/utils/cel-context.js +1 -0
  118. package/dist/runtime/vendor/cel-js/CLAUDE.md +3 -1
  119. package/dist/runtime/vendor/cel-js/PROMPT.md +31 -2
  120. package/dist/runtime/vendor/cel-js/lib/functions.js +28 -1
  121. package/dist/runtime/vendor/cel-js/lib/registry.js +2 -1
  122. package/package.json +8 -1
@@ -0,0 +1,370 @@
1
+ <script setup>
2
+ import { computed } from "vue";
3
+ import { Field, FieldLabel } from "../../../../ui/field";
4
+ import { ExpressionEditor } from "../../../../ui/expression-editor";
5
+ import DerivedValueEditor from "../../../DerivedValueEditor.vue";
6
+ import ValidationRulesField from "../../../ValidationRulesField.vue";
7
+ import { InputGroup, InputGroupInput } from "../../../../ui/input-group";
8
+ import { Locale as LocaleField } from "../../../../ui/locale";
9
+ import { Markdown } from "../../../../ui/markdown";
10
+ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../../../../ui/select";
11
+ import { getStructFieldDescription, getStructFieldTitle } from "../../../schema";
12
+ import {
13
+ BLOCK_FEATURES,
14
+ INLINE_FEATURES,
15
+ schema
16
+ } from "./schema";
17
+ defineOptions({ name: "ShwfedRichTextFieldConfig" });
18
+ const value = defineModel({ type: null, ...{ required: true } });
19
+ const fieldSchema = schema(() => {
20
+ });
21
+ const fieldTitle = (f) => getStructFieldTitle(fieldSchema, f) ?? f;
22
+ const fieldDescription = (f) => getStructFieldDescription(fieldSchema, f);
23
+ const INLINE_LABELS = {
24
+ bold: "\u52A0\u7C97",
25
+ italic: "\u659C\u4F53",
26
+ underline: "\u4E0B\u5212\u7EBF",
27
+ strike: "\u5220\u9664\u7EBF"
28
+ };
29
+ const BLOCK_LABELS = {
30
+ bulletList: "\u65E0\u5E8F\u5217\u8868",
31
+ orderedList: "\u6709\u5E8F\u5217\u8868"
32
+ };
33
+ const inlineSelection = computed(() => [...value.value.inline ?? []]);
34
+ const blockSelection = computed(() => [...value.value.block ?? []]);
35
+ const inlineSummary = computed(
36
+ () => inlineSelection.value.map((f) => INLINE_LABELS[f]).join("\u3001")
37
+ );
38
+ const blockSummary = computed(
39
+ () => blockSelection.value.map((f) => BLOCK_LABELS[f]).join("\u3001")
40
+ );
41
+ function setInline(next) {
42
+ const picked = new Set(next);
43
+ value.value = { ...value.value, inline: INLINE_FEATURES.filter((f) => picked.has(f)) };
44
+ }
45
+ function setBlock(next) {
46
+ const picked = new Set(next);
47
+ value.value = { ...value.value, block: BLOCK_FEATURES.filter((f) => picked.has(f)) };
48
+ }
49
+ const pathText = computed({
50
+ get: () => value.value.binding ?? "",
51
+ set: (next) => {
52
+ const trimmed = next.trim();
53
+ if (trimmed.length === 0) {
54
+ const { binding: _omit, ...rest } = value.value;
55
+ value.value = rest;
56
+ } else {
57
+ value.value = { ...value.value, binding: trimmed };
58
+ }
59
+ }
60
+ });
61
+ </script>
62
+
63
+ <template>
64
+ <div class="flex flex-col gap-3">
65
+ <div class="grid grid-cols-2 gap-3">
66
+ <Field orientation="vertical">
67
+ <FieldLabel class="text-xs text-zinc-500">
68
+ <template
69
+ v-if="fieldDescription('displayName')"
70
+ #tooltip
71
+ >
72
+ <Markdown
73
+ :source="fieldDescription('displayName')"
74
+ block
75
+ class="prose prose-sm prose-zinc"
76
+ />
77
+ </template>
78
+ {{ fieldTitle("displayName") }}
79
+ </FieldLabel>
80
+ <InputGroup>
81
+ <InputGroupInput
82
+ :model-value="value.displayName ?? ''"
83
+ placeholder="例:正文"
84
+ @update:model-value="(v) => {
85
+ const s = String(v ?? '');
86
+ value = { ...value, displayName: s.length > 0 ? s : void 0 };
87
+ }"
88
+ />
89
+ </InputGroup>
90
+ </Field>
91
+
92
+ <Field orientation="vertical">
93
+ <FieldLabel class="text-xs text-zinc-500">
94
+ <template #tooltip>
95
+ <Markdown
96
+ :source="fieldDescription('binding')"
97
+ block
98
+ class="prose prose-sm prose-zinc"
99
+ />
100
+ </template>
101
+ {{ fieldTitle("binding") }}
102
+ </FieldLabel>
103
+ <InputGroup>
104
+ <InputGroupInput
105
+ v-model="pathText"
106
+ placeholder="例:article.body"
107
+ class="font-mono"
108
+ />
109
+ </InputGroup>
110
+ </Field>
111
+ </div>
112
+
113
+ <div class="grid grid-cols-3 gap-3">
114
+ <Field orientation="vertical">
115
+ <FieldLabel class="text-xs text-zinc-500">
116
+ <template
117
+ v-if="fieldDescription('label')"
118
+ #tooltip
119
+ >
120
+ <Markdown
121
+ :source="fieldDescription('label')"
122
+ block
123
+ class="prose prose-sm prose-zinc"
124
+ />
125
+ </template>
126
+ {{ fieldTitle("label") }}
127
+ </FieldLabel>
128
+ <LocaleField
129
+ :model-value="value.label"
130
+ @update:model-value="(v) => value = { ...value, label: v }"
131
+ />
132
+ </Field>
133
+
134
+ <Field orientation="vertical">
135
+ <FieldLabel class="text-xs text-zinc-500">
136
+ <template
137
+ v-if="fieldDescription('placeholder')"
138
+ #tooltip
139
+ >
140
+ <Markdown
141
+ :source="fieldDescription('placeholder')"
142
+ block
143
+ class="prose prose-sm prose-zinc"
144
+ />
145
+ </template>
146
+ {{ fieldTitle("placeholder") }}
147
+ </FieldLabel>
148
+ <LocaleField
149
+ :model-value="value.placeholder"
150
+ @update:model-value="(v) => value = { ...value, placeholder: v }"
151
+ />
152
+ </Field>
153
+
154
+ <Field orientation="vertical">
155
+ <FieldLabel class="text-xs text-zinc-500">
156
+ <template
157
+ v-if="fieldDescription('tooltip')"
158
+ #tooltip
159
+ >
160
+ <Markdown
161
+ :source="fieldDescription('tooltip')"
162
+ block
163
+ class="prose prose-sm prose-zinc"
164
+ />
165
+ </template>
166
+ {{ fieldTitle("tooltip") }}
167
+ </FieldLabel>
168
+ <LocaleField
169
+ markdown
170
+ :model-value="value.tooltip"
171
+ @update:model-value="(v) => value = { ...value, tooltip: v }"
172
+ />
173
+ </Field>
174
+ </div>
175
+
176
+ <div class="grid grid-cols-2 gap-3">
177
+ <Field orientation="vertical">
178
+ <FieldLabel class="text-xs text-zinc-500">
179
+ <template #tooltip>
180
+ <Markdown
181
+ :source="fieldDescription('inline')"
182
+ block
183
+ class="prose prose-sm prose-zinc"
184
+ />
185
+ </template>
186
+ {{ fieldTitle("inline") }}
187
+ </FieldLabel>
188
+ <Select
189
+ multiple
190
+ :model-value="inlineSelection"
191
+ @update:model-value="setInline"
192
+ >
193
+ <SelectTrigger class="w-full">
194
+ <SelectValue placeholder="全部关闭">
195
+ <span v-if="inlineSummary.length > 0">{{ inlineSummary }}</span>
196
+ <span
197
+ v-else
198
+ class="text-zinc-400"
199
+ >全部关闭</span>
200
+ </SelectValue>
201
+ </SelectTrigger>
202
+ <SelectContent>
203
+ <SelectItem
204
+ v-for="feature in INLINE_FEATURES"
205
+ :key="feature"
206
+ :value="feature"
207
+ >
208
+ {{ INLINE_LABELS[feature] }}
209
+ </SelectItem>
210
+ </SelectContent>
211
+ </Select>
212
+ </Field>
213
+
214
+ <Field orientation="vertical">
215
+ <FieldLabel class="text-xs text-zinc-500">
216
+ <template #tooltip>
217
+ <Markdown
218
+ :source="fieldDescription('block')"
219
+ block
220
+ class="prose prose-sm prose-zinc"
221
+ />
222
+ </template>
223
+ {{ fieldTitle("block") }}
224
+ </FieldLabel>
225
+ <Select
226
+ multiple
227
+ :model-value="blockSelection"
228
+ @update:model-value="setBlock"
229
+ >
230
+ <SelectTrigger class="w-full">
231
+ <SelectValue placeholder="全部关闭">
232
+ <span v-if="blockSummary.length > 0">{{ blockSummary }}</span>
233
+ <span
234
+ v-else
235
+ class="text-zinc-400"
236
+ >全部关闭</span>
237
+ </SelectValue>
238
+ </SelectTrigger>
239
+ <SelectContent>
240
+ <SelectItem
241
+ v-for="feature in BLOCK_FEATURES"
242
+ :key="feature"
243
+ :value="feature"
244
+ >
245
+ {{ BLOCK_LABELS[feature] }}
246
+ </SelectItem>
247
+ </SelectContent>
248
+ </Select>
249
+ </Field>
250
+ </div>
251
+
252
+ <div class="grid grid-cols-3 gap-3">
253
+ <Field orientation="vertical">
254
+ <FieldLabel class="text-xs text-zinc-500">
255
+ <template #tooltip>
256
+ <Markdown
257
+ :source="fieldDescription('required') ?? '\u8FD4\u56DE `true` \u65F6\u663E\u793A\u5FC5\u586B\u661F\u53F7\u5E76\u8981\u6C42\u975E\u7A7A'"
258
+ block
259
+ class="prose prose-sm prose-zinc"
260
+ />
261
+ </template>
262
+ {{ fieldTitle("required") }}
263
+ </FieldLabel>
264
+ <ExpressionEditor
265
+ :model-value="value.required ?? ''"
266
+ placeholder="例:form.status == 'published'"
267
+ result-type="bool"
268
+ class="min-h-10"
269
+ @update:model-value="(v) => value = { ...value, required: v.length > 0 ? v : void 0 }"
270
+ />
271
+ </Field>
272
+
273
+ <Field orientation="vertical">
274
+ <FieldLabel class="text-xs text-zinc-500">
275
+ <template #tooltip>
276
+ <Markdown
277
+ :source="fieldDescription('hidden') ?? '\u8FD4\u56DE `true` \u65F6\u5B57\u6BB5\u5728\u6240\u6709\u5E03\u5C40\u4E2D\u90FD\u4E0D\u6E32\u67D3'"
278
+ block
279
+ class="prose prose-sm prose-zinc"
280
+ />
281
+ </template>
282
+ {{ fieldTitle("hidden") }}
283
+ </FieldLabel>
284
+ <ExpressionEditor
285
+ :model-value="value.hidden ?? ''"
286
+ placeholder="例:form.role == 'guest'"
287
+ result-type="bool"
288
+ class="min-h-10"
289
+ @update:model-value="(v) => value = { ...value, hidden: v.length > 0 ? v : void 0 }"
290
+ />
291
+ </Field>
292
+
293
+ <Field orientation="vertical">
294
+ <FieldLabel class="text-xs text-zinc-500">
295
+ <template #tooltip>
296
+ <Markdown
297
+ :source="fieldDescription('disabled')"
298
+ block
299
+ class="prose prose-sm prose-zinc"
300
+ />
301
+ </template>
302
+ {{ fieldTitle("disabled") }}
303
+ </FieldLabel>
304
+ <ExpressionEditor
305
+ :model-value="value.disabled ?? ''"
306
+ placeholder="例:form.status == 'locked'"
307
+ result-type="bool"
308
+ class="min-h-10"
309
+ @update:model-value="(v) => value = { ...value, disabled: v.length > 0 ? v : void 0 }"
310
+ />
311
+ </Field>
312
+
313
+ <Field orientation="vertical">
314
+ <FieldLabel class="text-xs text-zinc-500">
315
+ <template #tooltip>
316
+ <Markdown
317
+ :source="fieldDescription('readonly')"
318
+ block
319
+ class="prose prose-sm prose-zinc"
320
+ />
321
+ </template>
322
+ {{ fieldTitle("readonly") }}
323
+ </FieldLabel>
324
+ <ExpressionEditor
325
+ :model-value="value.readonly ?? ''"
326
+ placeholder="例:form.id != null"
327
+ result-type="bool"
328
+ class="min-h-10"
329
+ @update:model-value="(v) => value = { ...value, readonly: v.length > 0 ? v : void 0 }"
330
+ />
331
+ </Field>
332
+ </div>
333
+
334
+ <Field orientation="vertical">
335
+ <FieldLabel class="text-xs text-zinc-500">
336
+ <template #tooltip>
337
+ <Markdown
338
+ :source="fieldDescription('derived')"
339
+ block
340
+ class="prose prose-sm prose-zinc"
341
+ />
342
+ </template>
343
+ {{ fieldTitle("derived") }}
344
+ </FieldLabel>
345
+ <DerivedValueEditor
346
+ :model-value="value.derived"
347
+ result-type="string"
348
+ placeholder="例:form.template"
349
+ @update:model-value="(v) => value = { ...value, derived: v }"
350
+ />
351
+ </Field>
352
+
353
+ <Field orientation="vertical">
354
+ <FieldLabel class="text-xs text-zinc-500">
355
+ <template #tooltip>
356
+ <Markdown
357
+ :source="fieldDescription('validations')"
358
+ block
359
+ class="prose prose-sm prose-zinc"
360
+ />
361
+ </template>
362
+ {{ fieldTitle("validations") }}
363
+ </FieldLabel>
364
+ <ValidationRulesField
365
+ :model-value="value.validations"
366
+ @update:model-value="(v) => value = { ...value, validations: v.length > 0 ? v : void 0 }"
367
+ />
368
+ </Field>
369
+ </div>
370
+ </template>
@@ -0,0 +1,107 @@
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 label?: readonly [{
8
+ readonly locale: "zh";
9
+ readonly message: string;
10
+ }, ...{
11
+ readonly locale: "en" | "ja" | "ko";
12
+ readonly message: string;
13
+ }[]] | undefined;
14
+ readonly disabled?: string | undefined;
15
+ readonly type: "com.shwfed.form.field.richtext";
16
+ readonly id: string;
17
+ readonly inline: readonly ("bold" | "strike" | "italic" | "underline")[];
18
+ readonly hidden?: string | undefined;
19
+ readonly block: readonly ("bulletList" | "orderedList")[];
20
+ readonly tooltip?: readonly [{
21
+ readonly locale: "zh";
22
+ readonly message: string;
23
+ }, ...{
24
+ readonly locale: "en" | "ja" | "ko";
25
+ readonly message: string;
26
+ }[]] | undefined;
27
+ readonly required?: string | undefined;
28
+ readonly displayName?: string | undefined;
29
+ readonly compatibilityDate: "2026-07-18";
30
+ readonly placeholder?: readonly [{
31
+ readonly locale: "zh";
32
+ readonly message: string;
33
+ }, ...{
34
+ readonly locale: "en" | "ja" | "ko";
35
+ readonly message: string;
36
+ }[]] | undefined;
37
+ readonly readonly?: string | undefined;
38
+ readonly binding?: string | undefined;
39
+ readonly derived?: {
40
+ readonly mode: "formula" | "prefill";
41
+ readonly expression: string;
42
+ } | undefined;
43
+ readonly validations?: readonly {
44
+ readonly message: readonly [{
45
+ readonly locale: "zh";
46
+ readonly message: string;
47
+ }, ...{
48
+ readonly locale: "en" | "ja" | "ko";
49
+ readonly message: string;
50
+ }[]];
51
+ readonly warning?: boolean | undefined;
52
+ readonly when: string;
53
+ }[] | undefined;
54
+ }) => any;
55
+ }, string, import("vue").PublicProps, Readonly<__VLS_ModelProps> & Readonly<{
56
+ "onUpdate:modelValue"?: ((value: {
57
+ readonly label?: readonly [{
58
+ readonly locale: "zh";
59
+ readonly message: string;
60
+ }, ...{
61
+ readonly locale: "en" | "ja" | "ko";
62
+ readonly message: string;
63
+ }[]] | undefined;
64
+ readonly disabled?: string | undefined;
65
+ readonly type: "com.shwfed.form.field.richtext";
66
+ readonly id: string;
67
+ readonly inline: readonly ("bold" | "strike" | "italic" | "underline")[];
68
+ readonly hidden?: string | undefined;
69
+ readonly block: readonly ("bulletList" | "orderedList")[];
70
+ readonly tooltip?: readonly [{
71
+ readonly locale: "zh";
72
+ readonly message: string;
73
+ }, ...{
74
+ readonly locale: "en" | "ja" | "ko";
75
+ readonly message: string;
76
+ }[]] | undefined;
77
+ readonly required?: string | undefined;
78
+ readonly displayName?: string | undefined;
79
+ readonly compatibilityDate: "2026-07-18";
80
+ readonly placeholder?: readonly [{
81
+ readonly locale: "zh";
82
+ readonly message: string;
83
+ }, ...{
84
+ readonly locale: "en" | "ja" | "ko";
85
+ readonly message: string;
86
+ }[]] | undefined;
87
+ readonly readonly?: string | undefined;
88
+ readonly binding?: string | undefined;
89
+ readonly derived?: {
90
+ readonly mode: "formula" | "prefill";
91
+ readonly expression: string;
92
+ } | undefined;
93
+ readonly validations?: readonly {
94
+ readonly message: readonly [{
95
+ readonly locale: "zh";
96
+ readonly message: string;
97
+ }, ...{
98
+ readonly locale: "en" | "ja" | "ko";
99
+ readonly message: string;
100
+ }[]];
101
+ readonly warning?: boolean | undefined;
102
+ readonly when: string;
103
+ }[] | undefined;
104
+ }) => any) | undefined;
105
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
106
+ declare const _default: typeof __VLS_export;
107
+ export default _default;
@@ -0,0 +1,27 @@
1
+ import { type Extensions } from '@tiptap/vue-3';
2
+ import type { RichTextFeatures } from './features.js';
3
+ export interface RichTextExtensionOptions {
4
+ features: RichTextFeatures;
5
+ getPlaceholder: () => string;
6
+ }
7
+ /**
8
+ * The editor's extension set — the single source of truth for what this field
9
+ * can produce. Lives apart from `RichTextEditor.vue` so it can be exercised
10
+ * against a real `Editor` in a test without dragging the toolbar's popovers
11
+ * and portals into jsdom.
12
+ *
13
+ * `getPlaceholder` is read lazily so a locale switch is reflected without
14
+ * reconfiguring the editor.
15
+ *
16
+ * Two different meanings of "off" live here, and the difference matters:
17
+ *
18
+ * - Nodes and marks the CONFIG switches off stay REGISTERED. Only the means of
19
+ * authoring them is withdrawn (button hidden, shortcut unbound), because
20
+ * dropping the extension would make ProseMirror discard the tag while
21
+ * parsing — so merely opening a record authored before the box was unchecked
22
+ * would strip it, and the next save would persist the loss.
23
+ * - Nodes this field does not support AT ALL are removed from the schema
24
+ * outright. Content carrying them is flattened on load. That is a deliberate
25
+ * trade: the field has never shipped, so no stored document can contain them.
26
+ */
27
+ export declare function richTextExtensions(options: RichTextExtensionOptions): Extensions;
@@ -0,0 +1,83 @@
1
+ import { TextAlign } from "@tiptap/extension-text-align";
2
+ import { OrderedList } from "@tiptap/extension-list";
3
+ import { Placeholder } from "@tiptap/extensions";
4
+ import StarterKit from "@tiptap/starter-kit";
5
+ import { Extension } from "@tiptap/vue-3";
6
+ import { INLINE_FEATURES } from "./schema.js";
7
+ import { Indent } from "./indent.js";
8
+ const INLINE_SHORTCUTS = {
9
+ bold: ["Mod-b", "Mod-B"],
10
+ italic: ["Mod-i", "Mod-I"],
11
+ underline: ["Mod-u", "Mod-U"],
12
+ strike: ["Mod-Shift-s"]
13
+ };
14
+ const BULLET_LIST_SHORTCUT = "Mod-Shift-8";
15
+ const ORDERED_LIST_SHORTCUT = "Mod-Shift-7";
16
+ function shortcutGuard(features) {
17
+ return Extension.create({
18
+ name: "richtextShortcutGuard",
19
+ priority: 1e3,
20
+ addKeyboardShortcuts() {
21
+ const handlers = {};
22
+ const block = (key) => {
23
+ handlers[key] = () => true;
24
+ };
25
+ for (const kind of INLINE_FEATURES) {
26
+ if (features.inline.has(kind)) continue;
27
+ for (const key of INLINE_SHORTCUTS[kind]) block(key);
28
+ }
29
+ if (!features.block.has("bulletList")) block(BULLET_LIST_SHORTCUT);
30
+ if (!features.block.has("orderedList")) block(ORDERED_LIST_SHORTCUT);
31
+ return handlers;
32
+ }
33
+ });
34
+ }
35
+ export function richTextExtensions(options) {
36
+ const { features, getPlaceholder } = options;
37
+ return [
38
+ // StarterKit v3 bundles bold / italic / strike / underline and the list
39
+ // nodes — in v2 underline was a separate install.
40
+ StarterKit.configure({
41
+ // Off outright, not merely unbound. These are the nodes whose input rules
42
+ // are the markdown behaviour being complained about (`# `, `> `, ``` ),
43
+ // and the toolbar never offered them, so removing them from the schema
44
+ // closes the door structurally rather than relying on `enableInputRules`
45
+ // alone.
46
+ heading: false,
47
+ blockquote: false,
48
+ codeBlock: false,
49
+ code: false,
50
+ horizontalRule: false,
51
+ // Links and tables are deferred, not merely disabled — the interaction
52
+ // design for both needs more thought than a toolbar button. Removed from
53
+ // the schema rather than left switchable so no half-built affordance
54
+ // ships. Loading content that contains them flattens an `<a>` to its text
55
+ // and drops the table; acceptable only because this field has never
56
+ // shipped and no stored document can contain either.
57
+ link: false,
58
+ // ProseMirror's own drop cursor drew a thick black bar during drags.
59
+ // Nothing in this field drags document nodes, so it has no job here.
60
+ dropcursor: false,
61
+ // Re-registered below with its paste plugin stripped.
62
+ orderedList: false
63
+ }),
64
+ // `OrderedList` ships a `handlePaste` ProseMirror plugin that converts
65
+ // plain-text `1. foo` into a real list whenever the clipboard carries no
66
+ // `text/html`. It is not an input rule and not a paste rule, so neither
67
+ // editor-level switch touches it — this is the last piece of markdown
68
+ // parsing, and the only way out is to drop the plugin.
69
+ OrderedList.extend({ addProseMirrorPlugins: () => [] }),
70
+ shortcutGuard(features),
71
+ // Alignment is deliberately not configurable — it is always-on toolbar
72
+ // furniture.
73
+ TextAlign.configure({
74
+ types: ["paragraph"],
75
+ alignments: ["left", "center", "right"],
76
+ // `null` rather than `'left'`: unaligned paragraphs then emit no `style`
77
+ // at all, keeping the stored HTML free of no-op attributes.
78
+ defaultAlignment: null
79
+ }),
80
+ Indent.configure({ types: ["paragraph"] }),
81
+ Placeholder.configure({ placeholder: () => getPlaceholder() })
82
+ ];
83
+ }
@@ -0,0 +1,21 @@
1
+ import { type BlockFeature, type InlineFeature, type Value } from './schema.js';
2
+ /**
3
+ * The config's feature lists, resolved into the form the editor consumes.
4
+ *
5
+ * Resolving here rather than at each read site keeps the membership tests from
6
+ * being scattered across the toolbar and the extension set — two places that
7
+ * must agree, since a button the extension set cannot serve is a dead button.
8
+ *
9
+ * A config predating the `inline` / `block` fields decodes with them absent.
10
+ * Treating that as "everything on" matches what such a field actually did.
11
+ */
12
+ export interface RichTextFeatures {
13
+ inline: ReadonlySet<InlineFeature>;
14
+ block: ReadonlySet<BlockFeature>;
15
+ }
16
+ export type RichTextFeatureConfig = Partial<Pick<Value, 'inline' | 'block'>>;
17
+ export declare function resolveFeatures(config?: RichTextFeatureConfig): RichTextFeatures;
18
+ /** True when no list kind is enabled — indent/outdent still applies to paragraphs. */
19
+ export declare function hasAnyList(features: RichTextFeatures): boolean;
20
+ /** A value that changes whenever the enabled set does; see `runtime.vue`. */
21
+ export declare function featureSignature(features: RichTextFeatures): string;
@@ -0,0 +1,16 @@
1
+ import { INLINE_FEATURES, BLOCK_FEATURES } from "./schema.js";
2
+ export function resolveFeatures(config = {}) {
3
+ return {
4
+ inline: new Set(config.inline ?? INLINE_FEATURES),
5
+ block: new Set(config.block ?? BLOCK_FEATURES)
6
+ };
7
+ }
8
+ export function hasAnyList(features) {
9
+ return features.block.has("bulletList") || features.block.has("orderedList");
10
+ }
11
+ export function featureSignature(features) {
12
+ return [
13
+ [...features.inline].sort().join(","),
14
+ [...features.block].sort().join(",")
15
+ ].join("|");
16
+ }
@@ -0,0 +1,26 @@
1
+ import { Extension } from '@tiptap/core';
2
+ export interface IndentOptions {
3
+ /** Node types that carry the attribute. */
4
+ types: string[];
5
+ /** Indentation step, in `em`. */
6
+ step: number;
7
+ /** Ceiling, so a held Tab cannot push content off the right edge. */
8
+ maxLevel: number;
9
+ }
10
+ declare module '@tiptap/core' {
11
+ interface Commands<ReturnType> {
12
+ indent: {
13
+ indent: () => ReturnType;
14
+ outdent: () => ReturnType;
15
+ };
16
+ }
17
+ }
18
+ /**
19
+ * Paragraph indentation, as an `indent` level attribute rendered to a margin.
20
+ *
21
+ * Tiptap has no official indent extension in v3 (`@tiptap/extension-indent`
22
+ * does not exist on npm), so this is ours. It exists because indent/outdent has
23
+ * to mean something outside lists too — inside a list the same toolbar button
24
+ * nests the item, which `sinkListItem` already handles.
25
+ */
26
+ export declare const Indent: Extension<IndentOptions, any>;