@dou-ui/form-builder 0.0.0-stage → 0.1.0-alpha.1

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 (182) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +10 -2
  3. package/dist/builder/canvas.js +695 -0
  4. package/dist/builder/canvas.js.map +1 -0
  5. package/dist/builder/completion.js +49 -0
  6. package/dist/builder/completion.js.map +1 -0
  7. package/dist/builder/condition-editor.js +6 -0
  8. package/dist/builder/condition-editor.js.map +1 -0
  9. package/dist/builder/condition-editor.vue_vue_type_script_setup_true_lang.js +410 -0
  10. package/dist/builder/condition-editor.vue_vue_type_script_setup_true_lang.js.map +1 -0
  11. package/dist/builder/condition.js +159 -0
  12. package/dist/builder/condition.js.map +1 -0
  13. package/dist/builder/context.js +477 -0
  14. package/dist/builder/context.js.map +1 -0
  15. package/dist/builder/core/commands.js +373 -0
  16. package/dist/builder/core/commands.js.map +1 -0
  17. package/dist/builder/core/history.js +76 -0
  18. package/dist/builder/core/history.js.map +1 -0
  19. package/dist/builder/core/transaction.js +298 -0
  20. package/dist/builder/core/transaction.js.map +1 -0
  21. package/dist/builder/drag.js +466 -0
  22. package/dist/builder/drag.js.map +1 -0
  23. package/dist/builder/expression-box.js +19 -0
  24. package/dist/builder/expression-box.js.map +1 -0
  25. package/dist/builder/expression-input.js +6 -0
  26. package/dist/builder/expression-input.js.map +1 -0
  27. package/dist/builder/expression-input.vue_vue_type_script_setup_true_lang.js +117 -0
  28. package/dist/builder/expression-input.vue_vue_type_script_setup_true_lang.js.map +1 -0
  29. package/dist/builder/extension.js +47 -0
  30. package/dist/builder/extension.js.map +1 -0
  31. package/dist/builder/form-builder.js +6 -0
  32. package/dist/builder/form-builder.js.map +1 -0
  33. package/dist/builder/form-builder.vue_vue_type_script_setup_true_lang.js +450 -0
  34. package/dist/builder/form-builder.vue_vue_type_script_setup_true_lang.js.map +1 -0
  35. package/dist/builder/index.js +22 -0
  36. package/dist/builder/index.js.map +1 -0
  37. package/dist/builder/inspector.js +6 -0
  38. package/dist/builder/inspector.js.map +1 -0
  39. package/dist/builder/inspector.vue_vue_type_script_setup_true_lang.js +442 -0
  40. package/dist/builder/inspector.vue_vue_type_script_setup_true_lang.js.map +1 -0
  41. package/dist/builder/json-dialog.js +6 -0
  42. package/dist/builder/json-dialog.js.map +1 -0
  43. package/dist/builder/json-dialog.vue_vue_type_script_setup_true_lang.js +281 -0
  44. package/dist/builder/json-dialog.vue_vue_type_script_setup_true_lang.js.map +1 -0
  45. package/dist/builder/locale.js +1271 -0
  46. package/dist/builder/locale.js.map +1 -0
  47. package/dist/builder/logic-fields.js +18 -0
  48. package/dist/builder/logic-fields.js.map +1 -0
  49. package/dist/builder/logic.js +332 -0
  50. package/dist/builder/logic.js.map +1 -0
  51. package/dist/builder/menu.js +92 -0
  52. package/dist/builder/menu.js.map +1 -0
  53. package/dist/builder/outline-row.js +6 -0
  54. package/dist/builder/outline-row.js.map +1 -0
  55. package/dist/builder/outline-row.vue_vue_type_script_setup_true_lang.js +88 -0
  56. package/dist/builder/outline-row.vue_vue_type_script_setup_true_lang.js.map +1 -0
  57. package/dist/builder/outline.js +6 -0
  58. package/dist/builder/outline.js.map +1 -0
  59. package/dist/builder/outline.vue_vue_type_script_setup_true_lang.js +111 -0
  60. package/dist/builder/outline.vue_vue_type_script_setup_true_lang.js.map +1 -0
  61. package/dist/builder/palette.js +6 -0
  62. package/dist/builder/palette.js.map +1 -0
  63. package/dist/builder/palette.vue_vue_type_script_setup_true_lang.js +96 -0
  64. package/dist/builder/palette.vue_vue_type_script_setup_true_lang.js.map +1 -0
  65. package/dist/builder/preview.js +6 -0
  66. package/dist/builder/preview.js.map +1 -0
  67. package/dist/builder/preview.vue_vue_type_script_setup_true_lang.js +111 -0
  68. package/dist/builder/preview.vue_vue_type_script_setup_true_lang.js.map +1 -0
  69. package/dist/builder/settings-binding.js +57 -0
  70. package/dist/builder/settings-binding.js.map +1 -0
  71. package/dist/builder/settings.js +487 -0
  72. package/dist/builder/settings.js.map +1 -0
  73. package/dist/builder/span-field.js +104 -0
  74. package/dist/builder/span-field.js.map +1 -0
  75. package/dist/code/expression-input.js +6 -0
  76. package/dist/code/expression-input.js.map +1 -0
  77. package/dist/code/expression-input.vue_vue_type_script_setup_true_lang.js +88 -0
  78. package/dist/code/expression-input.vue_vue_type_script_setup_true_lang.js.map +1 -0
  79. package/dist/code/extension.js +202 -0
  80. package/dist/code/extension.js.map +1 -0
  81. package/dist/code/index.js +19 -0
  82. package/dist/code/index.js.map +1 -0
  83. package/dist/code/language.js +43 -0
  84. package/dist/code/language.js.map +1 -0
  85. package/dist/collaboration/index.js +382 -0
  86. package/dist/collaboration/index.js.map +1 -0
  87. package/dist/collaboration/order.js +88 -0
  88. package/dist/collaboration/order.js.map +1 -0
  89. package/dist/core/check.js +314 -0
  90. package/dist/core/check.js.map +1 -0
  91. package/dist/core/document.js +112 -0
  92. package/dist/core/document.js.map +1 -0
  93. package/dist/core/expression.js +854 -0
  94. package/dist/core/expression.js.map +1 -0
  95. package/dist/core/formulas.js +242 -0
  96. package/dist/core/formulas.js.map +1 -0
  97. package/dist/core/rules.js +83 -0
  98. package/dist/core/rules.js.map +1 -0
  99. package/dist/core/values.js +80 -0
  100. package/dist/core/values.js.map +1 -0
  101. package/dist/fields/builtin.js +167 -0
  102. package/dist/fields/builtin.js.map +1 -0
  103. package/dist/fields/components.js +155 -0
  104. package/dist/fields/components.js.map +1 -0
  105. package/dist/fields/define.js +44 -0
  106. package/dist/fields/define.js.map +1 -0
  107. package/dist/fields/format.js +125 -0
  108. package/dist/fields/format.js.map +1 -0
  109. package/dist/fields/options.js +54 -0
  110. package/dist/fields/options.js.map +1 -0
  111. package/dist/index.js +20 -0
  112. package/dist/locale.js +161 -0
  113. package/dist/locale.js.map +1 -0
  114. package/dist/renderer/containers.js +430 -0
  115. package/dist/renderer/containers.js.map +1 -0
  116. package/dist/renderer/context.js +21 -0
  117. package/dist/renderer/context.js.map +1 -0
  118. package/dist/renderer/form-renderer.js +6 -0
  119. package/dist/renderer/form-renderer.js.map +1 -0
  120. package/dist/renderer/form-renderer.vue_vue_type_script_setup_true_lang.js +272 -0
  121. package/dist/renderer/form-renderer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  122. package/dist/renderer/index.js +19 -0
  123. package/dist/renderer/index.js.map +1 -0
  124. package/dist/renderer/node-view.js +385 -0
  125. package/dist/renderer/node-view.js.map +1 -0
  126. package/dist/style.css +1 -0
  127. package/dist/style.d.ts +1 -0
  128. package/dist/style.js +27 -0
  129. package/dist/types/builder/canvas.d.ts +5 -0
  130. package/dist/types/builder/completion.d.ts +35 -0
  131. package/dist/types/builder/condition-editor.vue.d.ts +17 -0
  132. package/dist/types/builder/condition.d.ts +37 -0
  133. package/dist/types/builder/context.d.ts +149 -0
  134. package/dist/types/builder/core/commands.d.ts +74 -0
  135. package/dist/types/builder/core/history.d.ts +23 -0
  136. package/dist/types/builder/core/transaction.d.ts +108 -0
  137. package/dist/types/builder/drag.d.ts +52 -0
  138. package/dist/types/builder/expression-box.d.ts +8 -0
  139. package/dist/types/builder/expression-input.vue.d.ts +29 -0
  140. package/dist/types/builder/extension.d.ts +149 -0
  141. package/dist/types/builder/form-builder.vue.d.ts +24 -0
  142. package/dist/types/builder/index.d.ts +76 -0
  143. package/dist/types/builder/inspector.vue.d.ts +3 -0
  144. package/dist/types/builder/json-dialog.vue.d.ts +10 -0
  145. package/dist/types/builder/locale.d.ts +195 -0
  146. package/dist/types/builder/logic-fields.d.ts +2 -0
  147. package/dist/types/builder/logic.d.ts +57 -0
  148. package/dist/types/builder/menu.d.ts +23 -0
  149. package/dist/types/builder/outline-row.vue.d.ts +19 -0
  150. package/dist/types/builder/outline.vue.d.ts +3 -0
  151. package/dist/types/builder/palette.vue.d.ts +3 -0
  152. package/dist/types/builder/preview.vue.d.ts +3 -0
  153. package/dist/types/builder/settings-binding.d.ts +23 -0
  154. package/dist/types/builder/settings.d.ts +49 -0
  155. package/dist/types/builder/span-field.d.ts +4 -0
  156. package/dist/types/builder/types.d.ts +59 -0
  157. package/dist/types/code/expression-input.vue.d.ts +23 -0
  158. package/dist/types/code/extension.d.ts +45 -0
  159. package/dist/types/code/index.d.ts +12 -0
  160. package/dist/types/code/language.d.ts +6 -0
  161. package/dist/types/collaboration/index.d.ts +64 -0
  162. package/dist/types/collaboration/order.d.ts +20 -0
  163. package/dist/types/core/check.d.ts +68 -0
  164. package/dist/types/core/document.d.ts +36 -0
  165. package/dist/types/core/expression.d.ts +175 -0
  166. package/dist/types/core/formulas.d.ts +44 -0
  167. package/dist/types/core/rules.d.ts +23 -0
  168. package/dist/types/core/types.d.ts +211 -0
  169. package/dist/types/core/values.d.ts +22 -0
  170. package/dist/types/fields/builtin.d.ts +9 -0
  171. package/dist/types/fields/components.d.ts +177 -0
  172. package/dist/types/fields/define.d.ts +93 -0
  173. package/dist/types/fields/format.d.ts +76 -0
  174. package/dist/types/fields/options.d.ts +11 -0
  175. package/dist/types/index.d.ts +3 -0
  176. package/dist/types/locale.d.ts +45 -0
  177. package/dist/types/renderer/containers.d.ts +20 -0
  178. package/dist/types/renderer/context.d.ts +186 -0
  179. package/dist/types/renderer/form-renderer.vue.d.ts +25 -0
  180. package/dist/types/renderer/index.d.ts +81 -0
  181. package/dist/types/renderer/node-view.d.ts +56 -0
  182. package/package.json +88 -4
@@ -0,0 +1,442 @@
1
+ import { isContainer, isField, isList } from "../core/document.js";
2
+ import { normalizeOptions } from "../fields/components.js";
3
+ import { builtinFields } from "../fields/builtin.js";
4
+ import { formatMessage } from "../locale.js";
5
+ import { controlsReadonlyKey } from "../renderer/context.js";
6
+ import form_renderer_default from "../renderer/form-renderer.js";
7
+ import { formNodePlaces } from "./core/transaction.js";
8
+ import { scopeOf } from "./core/commands.js";
9
+ import { builtinSettings, documentSettings, iconOf, labelOf, nodeSettings, nodeTitle, settingsDocument } from "./settings.js";
10
+ import { useBuilderState } from "./context.js";
11
+ import { itemToRule, logicScope, logicSettings, ruleSettings, ruleToItem, sameLogicScope } from "./logic.js";
12
+ import { conditionField, expressionField } from "./logic-fields.js";
13
+ import { useSettingsBinding } from "./settings-binding.js";
14
+ import { spanField } from "./span-field.js";
15
+ import { DouButton } from "dou-ui";
16
+ import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, mergeProps, onBeforeUnmount, openBlock, provide, renderList, resolveDynamicComponent, toDisplayString, unref, useTemplateRef, watchEffect, withCtx } from "vue";
17
+ import { CopyIcon, PlusIcon, SquareDashedIcon, TrashIcon } from "@dou-ui/icons";
18
+ // src/builder/inspector.vue?vue&type=script&setup=true&lang.ts
19
+ var _hoisted_1 = { class: "dou-form-builder__inspector-header" };
20
+ var _hoisted_2 = { class: "dou-form-builder__inspector-title" };
21
+ var _hoisted_3 = {
22
+ key: 1,
23
+ class: "dou-form-builder__inspector-type"
24
+ };
25
+ var _hoisted_4 = { class: "dou-form-builder__inspector-body" };
26
+ var _hoisted_5 = {
27
+ key: 0,
28
+ class: "dou-form-builder__inspector-actions"
29
+ };
30
+ var _hoisted_6 = { class: "dou-form-builder__inspector-section" };
31
+ var _hoisted_7 = { class: "dou-form-builder__inspector-section" };
32
+ var _hoisted_8 = { class: "dou-form-builder__inspector-section" };
33
+ var _hoisted_9 = { class: "dou-form-builder__inspector-section" };
34
+ var inspector_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
35
+ name: "DouFormBuilderInspector",
36
+ __name: "inspector",
37
+ setup(__props) {
38
+ const state = useBuilderState();
39
+ provide(controlsReadonlyKey, () => state.readonly);
40
+ const root = useTemplateRef("root");
41
+ watchEffect(() => state.inspector.value = root.value);
42
+ onBeforeUnmount(() => {
43
+ if (state.inspector.value === root.value) state.inspector.value = null;
44
+ });
45
+ const messages = computed(() => state.messages);
46
+ const types = computed(() => state.fields);
47
+ const builderFields = [
48
+ spanField,
49
+ expressionField,
50
+ conditionField
51
+ ];
52
+ const extra = builderFields;
53
+ const rendererFields = computed(() => [...types.value.values(), ...builderFields]);
54
+ const inspectorFields = computed(() => new Map([...types.value, ...builderFields.map((type) => [type.type, type])]));
55
+ const count = computed(() => state.selection.length);
56
+ const node = computed(() => count.value === 1 ? state.focused.value : void 0);
57
+ const place = computed(() => node.value ? formNodePlaces(state.document).get(node.value.id) : void 0);
58
+ const spec = computed(() => node.value && isField(node.value) ? types.value.get(node.value.type) : void 0);
59
+ /** Columns of the grid a node sits on. */
60
+ function gridColumns(id) {
61
+ const document = state.document;
62
+ const own = Math.max(1, Math.round(document.columns ?? 12));
63
+ if (!id) return own;
64
+ const map = formNodePlaces(document);
65
+ let parent = map.get(id)?.parent;
66
+ while (parent) {
67
+ if ("columns" in parent && parent.columns) return parent.columns;
68
+ if (parent.type === "tabs" || parent.type === "steps") {
69
+ parent = map.get(parent.id)?.parent;
70
+ continue;
71
+ }
72
+ parent = map.get(parent.id)?.parent;
73
+ }
74
+ return own;
75
+ }
76
+ function memo(deps, make) {
77
+ let last;
78
+ let value;
79
+ return computed(() => {
80
+ const next = deps();
81
+ if (!last || next.length !== last.length || next.some((dep, index) => dep !== last[index])) {
82
+ last = next;
83
+ value = make();
84
+ }
85
+ return value;
86
+ });
87
+ }
88
+ const columns = computed(() => gridColumns(node.value?.id));
89
+ const inItem = computed(() => !!scopeOf(state.document, place.value?.parent?.id ?? null));
90
+ const nodeForm = memo(() => {
91
+ const current = node.value;
92
+ return [
93
+ current && (isField(current) ? "field" : current.type),
94
+ current?.type,
95
+ current?.props,
96
+ columns.value,
97
+ inItem.value,
98
+ messages.value,
99
+ spec.value
100
+ ];
101
+ }, () => settingsDocument(node.value ? nodeSettings(node.value, {
102
+ messages: messages.value,
103
+ columns: columns.value,
104
+ inItem: inItem.value,
105
+ type: spec.value
106
+ }) : []));
107
+ const isBuiltin = (type) => !!type && builtinFields.includes(type);
108
+ const typeForm = memo(() => [
109
+ node.value?.type,
110
+ spec.value,
111
+ messages.value
112
+ ], () => {
113
+ const type = spec.value;
114
+ const nodes = type?.settings ?? (isBuiltin(type) ? builtinSettings(type.type, messages.value) : []);
115
+ return settingsDocument(nodes);
116
+ });
117
+ const formForm = memo(() => [messages.value], () => settingsDocument(documentSettings(messages.value)));
118
+ const spanForm = memo(() => [messages.value, state.document.columns], () => settingsDocument(nodeSettings({
119
+ id: "",
120
+ type: "tabs",
121
+ children: []
122
+ }, {
123
+ messages: messages.value,
124
+ columns: Math.max(1, Math.round(state.document.columns ?? 12)),
125
+ inItem: false
126
+ })));
127
+ let lastScope;
128
+ const logic = computed(() => {
129
+ const next = logicScope(state.document, node.value?.id, types.value, messages.value);
130
+ if (!lastScope || !sameLogicScope(lastScope, next)) lastScope = next;
131
+ return lastScope;
132
+ });
133
+ const holdsValue = computed(() => {
134
+ const current = node.value;
135
+ if (!current) return false;
136
+ return isList(current) || isField(current) && spec.value?.kind !== "display";
137
+ });
138
+ const logicForm = memo(() => [
139
+ node.value?.type,
140
+ node.value?.name,
141
+ logic.value,
142
+ spec.value,
143
+ messages.value
144
+ ], () => settingsDocument(node.value ? logicSettings(node.value, {
145
+ messages: messages.value,
146
+ scope: logic.value,
147
+ type: spec.value
148
+ }) : []));
149
+ const validatorNames = computed(() => {
150
+ const given = state.validators();
151
+ return given ? Object.keys(given) : void 0;
152
+ });
153
+ const ruleForm = memo(() => [
154
+ holdsValue.value,
155
+ logic.value,
156
+ messages.value,
157
+ validatorNames.value?.join()
158
+ ], () => settingsDocument(holdsValue.value ? ruleSettings({
159
+ messages: messages.value,
160
+ scope: logic.value,
161
+ validators: validatorNames.value
162
+ }) : []));
163
+ /** Make a change of the settings, unless the builder is read-only. */
164
+ function commit(tr) {
165
+ if (!state.readonly) state.dispatch(tr);
166
+ }
167
+ function update(id, patch) {
168
+ const tr = state.transaction().update(id, patch);
169
+ tr.setMeta("group", `inspector:${id}:${Object.keys(patch).join(",")}`);
170
+ tr.setMeta("origin", "inspector");
171
+ commit(tr);
172
+ return formNodePlaces(state.document).get(id)?.node;
173
+ }
174
+ const nodeModel = useSettingsBinding({
175
+ source: () => node.value,
176
+ form: () => nodeForm.value,
177
+ fields: () => inspectorFields.value,
178
+ apply: (patch) => node.value ? update(node.value.id, patch) : void 0
179
+ });
180
+ const logicModel = useSettingsBinding({
181
+ source: () => node.value,
182
+ form: () => logicForm.value,
183
+ fields: () => inspectorFields.value,
184
+ apply: (patch) => node.value ? update(node.value.id, patch) : void 0
185
+ });
186
+ const ruleModel = useSettingsBinding({
187
+ source: () => node.value,
188
+ form: () => ruleForm.value,
189
+ fields: () => inspectorFields.value,
190
+ prepare: (data) => {
191
+ const rules = data.rules ?? [];
192
+ return {
193
+ ...data,
194
+ rules: rules.map(ruleToItem)
195
+ };
196
+ },
197
+ apply: (patch) => {
198
+ const current = node.value;
199
+ if (!current || !("rules" in patch)) return void 0;
200
+ const rules = (patch.rules ?? []).map(itemToRule);
201
+ return update(current.id, { rules: rules.length ? rules : void 0 });
202
+ }
203
+ });
204
+ /** Parts of the inspector from extensions, for the node or the form. */
205
+ const sections = computed(() => count.value > 1 ? [] : state.extensions().inspectors.flatMap((inspector) => inspector(state, node.value)));
206
+ const typeModel = useSettingsBinding({
207
+ source: () => node.value?.props,
208
+ key: () => node.value?.id,
209
+ form: () => typeForm.value,
210
+ fields: () => inspectorFields.value,
211
+ prepare: (props) => {
212
+ const prop = spec.value?.optionsProp;
213
+ const options = prop ? props[prop] : void 0;
214
+ if (prop && Array.isArray(options) && options.some((option) => typeof option !== "object")) props[prop] = normalizeOptions(options).map(({ label, value }) => ({
215
+ label,
216
+ value
217
+ }));
218
+ return props;
219
+ },
220
+ apply: (patch) => {
221
+ const current = node.value;
222
+ if (!current) return void 0;
223
+ const props = { ...current.props };
224
+ for (const [key, value] of Object.entries(patch)) if (value === void 0) delete props[key];
225
+ else props[key] = value;
226
+ return update(current.id, { props: Object.keys(props).length ? props : void 0 })?.props;
227
+ }
228
+ });
229
+ const settingKeys = [
230
+ "layout",
231
+ "labelAlign",
232
+ "labelWidth",
233
+ "size",
234
+ "requiredMark",
235
+ "columns"
236
+ ];
237
+ let lastSettings = {};
238
+ const documentSettingsOf = computed(() => {
239
+ const document = state.document;
240
+ if (settingKeys.every((key) => lastSettings[key] === document[key])) return lastSettings;
241
+ const next = {};
242
+ for (const key of settingKeys) if (document[key] !== void 0) next[key] = document[key];
243
+ return lastSettings = next;
244
+ });
245
+ const formModel = useSettingsBinding({
246
+ source: () => documentSettingsOf.value,
247
+ form: () => formForm.value,
248
+ fields: () => inspectorFields.value,
249
+ apply: (patch) => {
250
+ const tr = state.transaction().updateDocument(patch);
251
+ tr.setMeta("group", `inspector:document:${Object.keys(patch).join(",")}`);
252
+ tr.setMeta("origin", "inspector");
253
+ commit(tr);
254
+ return documentSettingsOf.value;
255
+ }
256
+ });
257
+ const spanModel = useSettingsBinding({
258
+ source: () => count.value > 1 ? state.focused.value : void 0,
259
+ key: () => state.selection.join(),
260
+ form: () => spanForm.value,
261
+ fields: () => inspectorFields.value,
262
+ apply: (patch) => {
263
+ const tr = state.transaction();
264
+ for (const id of state.selection) tr.update(id, patch);
265
+ tr.setMeta("group", `inspector:${state.selection.join()}:span`);
266
+ commit(tr);
267
+ return state.focused.value;
268
+ }
269
+ });
270
+ /** The other names of the scope the node's name is a key of. */
271
+ function otherNames(current) {
272
+ const document = state.document;
273
+ const scope = scopeOf(document, formNodePlaces(document).get(current.id)?.parent?.id ?? null);
274
+ const names = /* @__PURE__ */ new Set();
275
+ const visit = (nodes) => {
276
+ for (const each of nodes) {
277
+ if (each.id !== current.id && "name" in each && each.name) names.add(each.name);
278
+ if (isContainer(each) && !isList(each)) visit(each.children);
279
+ }
280
+ };
281
+ visit(scope ? scope.children : document.nodes);
282
+ return names;
283
+ }
284
+ const nameRules = computed(() => ({ name: [{
285
+ validator: (value) => {
286
+ const current = node.value;
287
+ if (!current) return true;
288
+ const name = typeof value === "string" ? value.trim() : "";
289
+ if (!name) return holdsValue.value ? messages.value.errors.name : true;
290
+ if (otherNames(current).has(name)) return formatMessage(messages.value.errors.taken, { text: name });
291
+ return true;
292
+ },
293
+ trigger: "change"
294
+ }] }));
295
+ const heading = computed(() => {
296
+ if (count.value > 1) return {
297
+ icon: SquareDashedIcon,
298
+ title: formatMessage(messages.value.inspector.multiple, { count: count.value }),
299
+ type: ""
300
+ };
301
+ const current = node.value;
302
+ if (!current) return {
303
+ icon: void 0,
304
+ title: messages.value.inspector.form,
305
+ type: ""
306
+ };
307
+ const type = labelOf(current.type, types.value.get(current.type), messages.value);
308
+ const title = nodeTitle(current, types.value, messages.value);
309
+ return {
310
+ icon: iconOf(current.type, types.value.get(current.type)),
311
+ title,
312
+ type: title === type ? "" : type
313
+ };
314
+ });
315
+ const holdsPages = computed(() => node.value?.type === "tabs" || node.value?.type === "steps");
316
+ const canWrap = computed(() => {
317
+ const map = formNodePlaces(state.document);
318
+ return new Set(state.selection.map((id) => map.get(id)?.parent?.id ?? null)).size === 1 && !state.selection.some((id) => map.get(id)?.node.type === "page");
319
+ });
320
+ return (_ctx, _cache) => {
321
+ return openBlock(), createElementBlock("div", {
322
+ ref_key: "root",
323
+ ref: root,
324
+ class: "dou-form-builder__inspector"
325
+ }, [createElementVNode("div", _hoisted_1, [
326
+ heading.value.icon ? (openBlock(), createBlock(resolveDynamicComponent(heading.value.icon), {
327
+ key: 0,
328
+ class: "dou-form-builder__inspector-icon"
329
+ })) : createCommentVNode("", true),
330
+ createElementVNode("span", _hoisted_2, toDisplayString(heading.value.title), 1),
331
+ heading.value.type ? (openBlock(), createElementBlock("span", _hoisted_3, toDisplayString(heading.value.type), 1)) : createCommentVNode("", true)
332
+ ]), createElementVNode("div", _hoisted_4, [count.value > 1 ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [createVNode(form_renderer_default, {
333
+ form: unref(spanForm),
334
+ model: unref(spanModel),
335
+ fields: unref(extra)
336
+ }, null, 8, [
337
+ "form",
338
+ "model",
339
+ "fields"
340
+ ]), !unref(state).readonly ? (openBlock(), createElementBlock("div", _hoisted_5, [
341
+ createVNode(unref(DouButton), {
342
+ size: "sm",
343
+ variant: "outline",
344
+ onClick: _cache[0] || (_cache[0] = ($event) => unref(state).duplicate())
345
+ }, {
346
+ leading: withCtx(() => [createVNode(unref(CopyIcon))]),
347
+ default: withCtx(() => [createTextVNode(" " + toDisplayString(messages.value.actions.duplicate), 1)]),
348
+ _: 1
349
+ }),
350
+ createVNode(unref(DouButton), {
351
+ size: "sm",
352
+ variant: "outline",
353
+ disabled: !canWrap.value,
354
+ onClick: _cache[1] || (_cache[1] = ($event) => unref(state).wrap())
355
+ }, {
356
+ leading: withCtx(() => [createVNode(unref(SquareDashedIcon))]),
357
+ default: withCtx(() => [createTextVNode(" " + toDisplayString(messages.value.actions.wrap), 1)]),
358
+ _: 1
359
+ }, 8, ["disabled"]),
360
+ createVNode(unref(DouButton), {
361
+ size: "sm",
362
+ variant: "outline",
363
+ tone: "danger",
364
+ onClick: _cache[2] || (_cache[2] = ($event) => unref(state).remove())
365
+ }, {
366
+ leading: withCtx(() => [createVNode(unref(TrashIcon))]),
367
+ default: withCtx(() => [createTextVNode(" " + toDisplayString(messages.value.actions.remove), 1)]),
368
+ _: 1
369
+ })
370
+ ])) : createCommentVNode("", true)], 64)) : node.value ? (openBlock(), createElementBlock(Fragment, { key: 1 }, [
371
+ (openBlock(), createBlock(form_renderer_default, {
372
+ key: node.value.id,
373
+ form: unref(nodeForm),
374
+ model: unref(nodeModel),
375
+ fields: rendererFields.value,
376
+ rules: nameRules.value
377
+ }, null, 8, [
378
+ "form",
379
+ "model",
380
+ "fields",
381
+ "rules"
382
+ ])),
383
+ holdsPages.value && !unref(state).readonly ? (openBlock(), createBlock(unref(DouButton), {
384
+ key: 0,
385
+ class: "dou-form-builder__inspector-add",
386
+ size: "sm",
387
+ variant: "outline",
388
+ onClick: _cache[3] || (_cache[3] = ($event) => unref(state).addPage(node.value.id))
389
+ }, {
390
+ leading: withCtx(() => [createVNode(unref(PlusIcon))]),
391
+ default: withCtx(() => [createTextVNode(" " + toDisplayString(messages.value.actions.addPage), 1)]),
392
+ _: 1
393
+ })) : createCommentVNode("", true),
394
+ unref(typeForm).nodes.length ? (openBlock(), createElementBlock(Fragment, { key: 1 }, [createElementVNode("div", _hoisted_6, toDisplayString(messages.value.inspector.type), 1), (openBlock(), createBlock(form_renderer_default, {
395
+ key: `${node.value.id}/props`,
396
+ form: unref(typeForm),
397
+ model: unref(typeModel),
398
+ fields: rendererFields.value
399
+ }, null, 8, [
400
+ "form",
401
+ "model",
402
+ "fields"
403
+ ]))], 64)) : createCommentVNode("", true),
404
+ unref(ruleForm).nodes.length ? (openBlock(), createElementBlock(Fragment, { key: 2 }, [createElementVNode("div", _hoisted_7, toDisplayString(messages.value.inspector.rules), 1), (openBlock(), createBlock(form_renderer_default, {
405
+ key: `${node.value.id}/rules`,
406
+ form: unref(ruleForm),
407
+ model: unref(ruleModel),
408
+ fields: rendererFields.value
409
+ }, null, 8, [
410
+ "form",
411
+ "model",
412
+ "fields"
413
+ ]))], 64)) : createCommentVNode("", true),
414
+ createElementVNode("div", _hoisted_8, toDisplayString(messages.value.inspector.logic), 1),
415
+ (openBlock(), createBlock(form_renderer_default, {
416
+ key: `${node.value.id}/logic`,
417
+ form: unref(logicForm),
418
+ model: unref(logicModel),
419
+ fields: rendererFields.value
420
+ }, null, 8, [
421
+ "form",
422
+ "model",
423
+ "fields"
424
+ ]))
425
+ ], 64)) : (openBlock(), createBlock(form_renderer_default, {
426
+ key: 2,
427
+ form: unref(formForm),
428
+ model: unref(formModel),
429
+ fields: unref(extra)
430
+ }, null, 8, [
431
+ "form",
432
+ "model",
433
+ "fields"
434
+ ])), (openBlock(true), createElementBlock(Fragment, null, renderList(sections.value, (section) => {
435
+ return openBlock(), createElementBlock(Fragment, { key: section.key }, [createElementVNode("div", _hoisted_9, toDisplayString(section.title), 1), (openBlock(), createBlock(resolveDynamicComponent(section.component), mergeProps({ ref_for: true }, section.props), null, 16))], 64);
436
+ }), 128))])], 512);
437
+ };
438
+ }
439
+ });
440
+ export { inspector_vue_vue_type_script_setup_true_lang_default as default };
441
+
442
+ //# sourceMappingURL=inspector.vue_vue_type_script_setup_true_lang.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inspector.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createElementBlock","_createElementVNode","_createBlock","_resolveDynamicComponent","_createCommentVNode","_toDisplayString","_Fragment","_createVNode","FormRenderer","_unref","_withCtx","_createTextVNode","_renderList","_mergeProps"],"sources":["../../src/builder/inspector.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, onBeforeUnmount, provide, useTemplateRef, watchEffect } from 'vue'\nimport { DouButton } from 'dou-ui'\nimport type { FormRules } from 'dou-ui'\nimport { CopyIcon, PlusIcon, SquareDashedIcon, TrashIcon } from '@dou-ui/icons'\nimport { isContainer, isField, isList } from '../core/document'\nimport type { FormFieldNode, FormNode, FormRuleSpec } from '../core/types'\nimport { builtinFields } from '../fields/builtin'\nimport { normalizeOptions } from '../fields/components'\nimport type { FormFieldType } from '../fields/define'\nimport { formatMessage } from '../locale'\nimport FormRenderer from '../renderer/form-renderer.vue'\nimport { controlsReadonlyKey } from '../renderer/context'\nimport { useBuilderState } from './context'\nimport type { FormBuilderTransaction } from './core/transaction'\nimport { scopeOf } from './core/commands'\nimport { formNodePlaces } from './core/transaction'\nimport {\n itemToRule,\n logicScope,\n sameLogicScope,\n logicSettings,\n ruleSettings,\n ruleToItem,\n} from './logic'\nimport type { LogicScope } from './logic'\nimport { conditionField, expressionField } from './logic-fields'\nimport {\n builtinSettings,\n documentSettings,\n iconOf,\n labelOf,\n nodeSettings,\n nodeTitle,\n settingsDocument,\n} from './settings'\nimport { useSettingsBinding } from './settings-binding'\nimport { spanField } from './span-field'\n\ndefineOptions({ name: 'DouFormBuilderInspector' })\n\nconst state = useBuilderState()\n// A read-only builder's settings can be read, not changed: the controls stay legible.\nprovide(controlsReadonlyKey, () => state.readonly)\nconst root = useTemplateRef<HTMLElement>('root')\nwatchEffect(() => (state.inspector.value = root.value))\nonBeforeUnmount(() => {\n if (state.inspector.value === root.value) state.inspector.value = null\n})\n\nconst messages = computed(() => state.messages)\nconst types = computed(() => state.fields as Map<string, FormFieldType>)\nconst builderFields = [spanField, expressionField, conditionField]\nconst extra = builderFields\nconst rendererFields = computed(() => [...types.value.values(), ...builderFields])\nconst inspectorFields = computed(\n () => new Map([...types.value, ...builderFields.map((type) => [type.type, type] as const)]),\n)\n\nconst count = computed(() => state.selection.length)\nconst node = computed(() => (count.value === 1 ? state.focused.value : undefined))\nconst place = computed(() =>\n node.value ? formNodePlaces(state.document).get(node.value.id) : undefined,\n)\nconst spec = computed(() =>\n node.value && isField(node.value) ? types.value.get(node.value.type) : undefined,\n)\n\n/** Columns of the grid a node sits on. */\nfunction gridColumns(id: string | undefined) {\n const document = state.document\n const own = Math.max(1, Math.round(document.columns ?? 12))\n if (!id) return own\n const map = formNodePlaces(document)\n let parent = map.get(id)?.parent\n while (parent) {\n if ('columns' in parent && parent.columns) return parent.columns\n if (parent.type === 'tabs' || parent.type === 'steps') {\n parent = map.get(parent.id)?.parent\n continue\n }\n parent = map.get(parent.id)?.parent\n }\n return own\n}\n\n// The settings forms change only with what they depend on, so typing in one keeps the others.\nfunction memo<T>(deps: () => unknown[], make: () => T) {\n let last: unknown[] | undefined\n let value: T\n return computed(() => {\n const next = deps()\n if (!last || next.length !== last.length || next.some((dep, index) => dep !== last![index])) {\n last = next\n value = make()\n }\n return value\n })\n}\n\nconst columns = computed(() => gridColumns(node.value?.id))\nconst inItem = computed(() => !!scopeOf(state.document, place.value?.parent?.id ?? null))\n\nconst nodeForm = memo(\n () => {\n const current = node.value\n const kind = current && (isField(current) ? 'field' : current.type)\n return [\n kind,\n current?.type,\n (current as FormFieldNode | undefined)?.props,\n columns.value,\n inItem.value,\n messages.value,\n spec.value,\n ]\n },\n () =>\n settingsDocument(\n node.value\n ? nodeSettings(node.value, {\n messages: messages.value,\n columns: columns.value,\n inItem: inItem.value,\n type: spec.value,\n })\n : [],\n ),\n)\n\nconst isBuiltin = (type: FormFieldType | undefined) => !!type && builtinFields.includes(type)\nconst typeForm = memo(\n () => [node.value?.type, spec.value, messages.value],\n () => {\n const type = spec.value\n const nodes =\n type?.settings ?? (isBuiltin(type) ? builtinSettings(type!.type, messages.value) : [])\n return settingsDocument(nodes)\n },\n)\nconst formForm = memo(\n () => [messages.value],\n () => settingsDocument(documentSettings(messages.value)),\n)\nconst spanForm = memo(\n () => [messages.value, state.document.columns],\n () =>\n settingsDocument(\n nodeSettings(\n { id: '', type: 'tabs', children: [] },\n {\n messages: messages.value,\n columns: Math.max(1, Math.round(state.document.columns ?? 12)),\n inItem: false,\n },\n ),\n ),\n)\n\n// What the node's logic can read; kept as one object while the fields it lists stay the same.\nlet lastScope: LogicScope | undefined\nconst logic = computed(() => {\n const next = logicScope(state.document, node.value?.id, types.value, messages.value)\n if (!lastScope || !sameLogicScope(lastScope, next)) lastScope = next\n return lastScope\n})\nconst holdsValue = computed(() => {\n const current = node.value\n if (!current) return false\n return isList(current) || (isField(current) && spec.value?.kind !== 'display')\n})\n\nconst logicForm = memo(\n () => [\n node.value?.type,\n (node.value as FormFieldNode | undefined)?.name,\n logic.value,\n spec.value,\n messages.value,\n ],\n () =>\n settingsDocument(\n node.value\n ? logicSettings(node.value, {\n messages: messages.value,\n scope: logic.value,\n type: spec.value,\n })\n : [],\n ),\n)\nconst validatorNames = computed(() => {\n const given = state.validators()\n return given ? Object.keys(given) : undefined\n})\nconst ruleForm = memo(\n () => [holdsValue.value, logic.value, messages.value, validatorNames.value?.join()],\n () =>\n settingsDocument(\n holdsValue.value\n ? ruleSettings({\n messages: messages.value,\n scope: logic.value,\n validators: validatorNames.value,\n })\n : [],\n ),\n)\n\n/** Make a change of the settings, unless the builder is read-only. */\nfunction commit(tr: FormBuilderTransaction) {\n if (!state.readonly) state.dispatch(tr)\n}\n\nfunction update(id: string, patch: Record<string, unknown>) {\n const tr = state.transaction().update(id, patch)\n tr.setMeta('group', `inspector:${id}:${Object.keys(patch).join(',')}`)\n tr.setMeta('origin', 'inspector')\n commit(tr)\n return formNodePlaces(state.document).get(id)?.node\n}\n\nconst nodeModel = useSettingsBinding({\n source: () => node.value as Record<string, unknown> | undefined,\n form: () => nodeForm.value,\n fields: () => inspectorFields.value,\n apply: (patch) =>\n node.value ? (update(node.value.id, patch) as unknown as Record<string, unknown>) : undefined,\n})\n\nconst logicModel = useSettingsBinding({\n source: () => node.value as Record<string, unknown> | undefined,\n form: () => logicForm.value,\n fields: () => inspectorFields.value,\n apply: (patch) =>\n node.value ? (update(node.value.id, patch) as unknown as Record<string, unknown>) : undefined,\n})\n\nconst ruleModel = useSettingsBinding({\n source: () => node.value as Record<string, unknown> | undefined,\n form: () => ruleForm.value,\n fields: () => inspectorFields.value,\n prepare: (data) => {\n const rules = (data.rules as FormRuleSpec[] | undefined) ?? []\n return { ...data, rules: rules.map(ruleToItem) }\n },\n apply: (patch) => {\n const current = node.value\n if (!current || !('rules' in patch)) return undefined\n const items = (patch.rules as Record<string, unknown>[] | undefined) ?? []\n const rules = items.map(itemToRule)\n return update(current.id, { rules: rules.length ? rules : undefined }) as unknown as\n Record<string, unknown> | undefined\n },\n})\n\n/** Parts of the inspector from extensions, for the node or the form. */\nconst sections = computed(() =>\n count.value > 1\n ? []\n : state.extensions().inspectors.flatMap((inspector) => inspector(state, node.value)),\n)\n\nconst typeModel = useSettingsBinding({\n source: () => (node.value as FormFieldNode | undefined)?.props,\n key: () => node.value?.id,\n form: () => typeForm.value,\n fields: () => inspectorFields.value,\n prepare: (props) => {\n // Options written as plain values show as rows of text and value.\n const prop = spec.value?.optionsProp\n const options = prop ? props[prop] : undefined\n if (prop && Array.isArray(options) && options.some((option) => typeof option !== 'object'))\n props[prop] = normalizeOptions(options).map(({ label, value }) => ({ label, value }))\n return props\n },\n apply: (patch) => {\n const current = node.value as FormFieldNode | undefined\n if (!current) return undefined\n const props: Record<string, unknown> = { ...current.props }\n for (const [key, value] of Object.entries(patch)) {\n if (value === undefined) delete props[key]\n else props[key] = value\n }\n const next = update(current.id, { props: Object.keys(props).length ? props : undefined })\n return (next as FormFieldNode | undefined)?.props\n },\n})\n\n// The document's own settings, as an object that changes only when one of them does.\nconst settingKeys = [\n 'layout',\n 'labelAlign',\n 'labelWidth',\n 'size',\n 'requiredMark',\n 'columns',\n] as const\nlet lastSettings: Record<string, unknown> = {}\nconst documentSettingsOf = computed(() => {\n const document = state.document as unknown as Record<string, unknown>\n if (settingKeys.every((key) => lastSettings[key] === document[key])) return lastSettings\n const next: Record<string, unknown> = {}\n for (const key of settingKeys) if (document[key] !== undefined) next[key] = document[key]\n return (lastSettings = next)\n})\n\nconst formModel = useSettingsBinding({\n source: () => documentSettingsOf.value,\n form: () => formForm.value,\n fields: () => inspectorFields.value,\n apply: (patch) => {\n const tr = state.transaction().updateDocument(patch)\n tr.setMeta('group', `inspector:document:${Object.keys(patch).join(',')}`)\n tr.setMeta('origin', 'inspector')\n commit(tr)\n return documentSettingsOf.value\n },\n})\n\nconst spanModel = useSettingsBinding({\n source: () =>\n count.value > 1 ? (state.focused.value as Record<string, unknown> | undefined) : undefined,\n key: () => state.selection.join(),\n form: () => spanForm.value,\n fields: () => inspectorFields.value,\n apply: (patch) => {\n const tr = state.transaction()\n for (const id of state.selection) tr.update(id, patch)\n tr.setMeta('group', `inspector:${state.selection.join()}:span`)\n commit(tr)\n return state.focused.value as Record<string, unknown> | undefined\n },\n})\n\n/** The other names of the scope the node's name is a key of. */\nfunction otherNames(current: FormNode) {\n const document = state.document\n const scope = scopeOf(document, formNodePlaces(document).get(current.id)?.parent?.id ?? null)\n const names = new Set<string>()\n const visit = (nodes: readonly FormNode[]) => {\n for (const each of nodes) {\n if (each.id !== current.id && 'name' in each && each.name) names.add(each.name)\n if (isContainer(each) && !isList(each)) visit(each.children)\n }\n }\n visit(scope ? scope.children : document.nodes)\n return names\n}\n\nconst nameRules = computed<FormRules>(() => ({\n name: [\n {\n validator: (value: unknown) => {\n const current = node.value\n if (!current) return true\n const name = typeof value === 'string' ? value.trim() : ''\n if (!name) return holdsValue.value ? messages.value.errors.name : true\n if (otherNames(current).has(name))\n return formatMessage(messages.value.errors.taken, { text: name })\n return true\n },\n trigger: 'change',\n },\n ],\n}))\n\nconst heading = computed(() => {\n if (count.value > 1)\n return {\n icon: SquareDashedIcon,\n title: formatMessage(messages.value.inspector.multiple, { count: count.value }),\n type: '',\n }\n const current = node.value\n if (!current) return { icon: undefined, title: messages.value.inspector.form, type: '' }\n const type = labelOf(current.type, types.value.get(current.type), messages.value)\n const title = nodeTitle(current, types.value, messages.value)\n return {\n icon: iconOf(current.type, types.value.get(current.type)),\n title,\n type: title === type ? '' : type,\n }\n})\n\nconst holdsPages = computed(() => node.value?.type === 'tabs' || node.value?.type === 'steps')\nconst canWrap = computed(() => {\n const map = formNodePlaces(state.document)\n const parents = new Set(state.selection.map((id) => map.get(id)?.parent?.id ?? null))\n return parents.size === 1 && !state.selection.some((id) => map.get(id)?.node.type === 'page')\n})\n</script>\n\n<template>\n <div ref=\"root\" class=\"dou-form-builder__inspector\">\n <div class=\"dou-form-builder__inspector-header\">\n <component :is=\"heading.icon\" v-if=\"heading.icon\" class=\"dou-form-builder__inspector-icon\" />\n <span class=\"dou-form-builder__inspector-title\">{{ heading.title }}</span>\n <span v-if=\"heading.type\" class=\"dou-form-builder__inspector-type\">{{ heading.type }}</span>\n </div>\n <div class=\"dou-form-builder__inspector-body\">\n <template v-if=\"count > 1\">\n <FormRenderer :form=\"spanForm\" :model=\"spanModel\" :fields=\"extra\" />\n <div v-if=\"!state.readonly\" class=\"dou-form-builder__inspector-actions\">\n <DouButton size=\"sm\" variant=\"outline\" @click=\"state.duplicate()\">\n <template #leading><CopyIcon /></template>\n {{ messages.actions.duplicate }}\n </DouButton>\n <DouButton size=\"sm\" variant=\"outline\" :disabled=\"!canWrap\" @click=\"state.wrap()\">\n <template #leading><SquareDashedIcon /></template>\n {{ messages.actions.wrap }}\n </DouButton>\n <DouButton size=\"sm\" variant=\"outline\" tone=\"danger\" @click=\"state.remove()\">\n <template #leading><TrashIcon /></template>\n {{ messages.actions.remove }}\n </DouButton>\n </div>\n </template>\n <template v-else-if=\"node\">\n <FormRenderer\n :key=\"node.id\"\n :form=\"nodeForm\"\n :model=\"nodeModel\"\n :fields=\"rendererFields\"\n :rules=\"nameRules\"\n />\n <DouButton\n v-if=\"holdsPages && !state.readonly\"\n class=\"dou-form-builder__inspector-add\"\n size=\"sm\"\n variant=\"outline\"\n @click=\"state.addPage(node.id)\"\n >\n <template #leading><PlusIcon /></template>\n {{ messages.actions.addPage }}\n </DouButton>\n <template v-if=\"typeForm.nodes.length\">\n <div class=\"dou-form-builder__inspector-section\">{{ messages.inspector.type }}</div>\n <FormRenderer\n :key=\"`${node.id}/props`\"\n :form=\"typeForm\"\n :model=\"typeModel\"\n :fields=\"rendererFields\"\n />\n </template>\n <template v-if=\"ruleForm.nodes.length\">\n <div class=\"dou-form-builder__inspector-section\">{{ messages.inspector.rules }}</div>\n <FormRenderer\n :key=\"`${node.id}/rules`\"\n :form=\"ruleForm\"\n :model=\"ruleModel\"\n :fields=\"rendererFields\"\n />\n </template>\n <div class=\"dou-form-builder__inspector-section\">{{ messages.inspector.logic }}</div>\n <FormRenderer\n :key=\"`${node.id}/logic`\"\n :form=\"logicForm\"\n :model=\"logicModel\"\n :fields=\"rendererFields\"\n />\n </template>\n <FormRenderer v-else :form=\"formForm\" :model=\"formModel\" :fields=\"extra\" />\n <template v-for=\"section in sections\" :key=\"section.key\">\n <div class=\"dou-form-builder__inspector-section\">{{ section.title }}</div>\n <component :is=\"section.component\" v-bind=\"section.props\" />\n </template>\n </div>\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAyCA,MAAM,QAAQ,gBAAgB;EAE9B,QAAQ,2BAA2B,MAAM,QAAQ;EACjD,MAAM,OAAO,eAA4B,MAAM;EAC/C,kBAAmB,MAAM,UAAU,QAAQ,KAAK,KAAM;EACtD,sBAAsB;GACpB,IAAI,MAAM,UAAU,UAAU,KAAK,OAAO,MAAM,UAAU,QAAQ;EACpE,CAAC;EAED,MAAM,WAAW,eAAe,MAAM,QAAQ;EAC9C,MAAM,QAAQ,eAAe,MAAM,MAAoC;EACvE,MAAM,gBAAgB;GAAC;GAAW;GAAiB;EAAc;EACjE,MAAM,QAAQ;EACd,MAAM,iBAAiB,eAAe,CAAC,GAAG,MAAM,MAAM,OAAO,GAAG,GAAG,aAAa,CAAC;EACjF,MAAM,kBAAkB,eAChB,IAAI,IAAI,CAAC,GAAG,MAAM,OAAO,GAAG,cAAc,KAAK,SAAS,CAAC,KAAK,MAAM,IAAI,CAAU,CAAC,CAAC,CAC5F;EAEA,MAAM,QAAQ,eAAe,MAAM,UAAU,MAAM;EACnD,MAAM,OAAO,eAAgB,MAAM,UAAU,IAAI,MAAM,QAAQ,QAAQ,KAAA,CAAU;EACjF,MAAM,QAAQ,eACZ,KAAK,QAAQ,eAAe,MAAM,QAAQ,CAAC,CAAC,IAAI,KAAK,MAAM,EAAE,IAAI,KAAA,CACnE;EACA,MAAM,OAAO,eACX,KAAK,SAAS,QAAQ,KAAK,KAAK,IAAI,MAAM,MAAM,IAAI,KAAK,MAAM,IAAI,IAAI,KAAA,CACzE;;EAGA,SAAS,YAAY,IAAwB;GAC3C,MAAM,WAAW,MAAM;GACvB,MAAM,MAAM,KAAK,IAAI,GAAG,KAAK,MAAM,SAAS,WAAW,EAAE,CAAC;GAC1D,IAAI,CAAC,IAAI,OAAO;GAChB,MAAM,MAAM,eAAe,QAAQ;GACnC,IAAI,SAAS,IAAI,IAAI,EAAE,CAAC,EAAE;GAC1B,OAAO,QAAQ;IACb,IAAI,aAAa,UAAU,OAAO,SAAS,OAAO,OAAO;IACzD,IAAI,OAAO,SAAS,UAAU,OAAO,SAAS,SAAS;KACrD,SAAS,IAAI,IAAI,OAAO,EAAE,CAAC,EAAE;KAC7B;IACF;IACA,SAAS,IAAI,IAAI,OAAO,EAAE,CAAC,EAAE;GAC/B;GACA,OAAO;EACT;EAGA,SAAS,KAAQ,MAAuB,MAAe;GACrD,IAAI;GACJ,IAAI;GACJ,OAAO,eAAe;IACpB,MAAM,OAAO,KAAK;IAClB,IAAI,CAAC,QAAQ,KAAK,WAAW,KAAK,UAAU,KAAK,MAAM,KAAK,UAAU,QAAQ,KAAM,MAAM,GAAG;KAC3F,OAAO;KACP,QAAQ,KAAK;IACf;IACA,OAAO;GACT,CAAC;EACH;EAEA,MAAM,UAAU,eAAe,YAAY,KAAK,OAAO,EAAE,CAAC;EAC1D,MAAM,SAAS,eAAe,CAAC,CAAC,QAAQ,MAAM,UAAU,MAAM,OAAO,QAAQ,MAAM,IAAI,CAAC;EAExF,MAAM,WAAW,WACT;GACJ,MAAM,UAAU,KAAK;GAErB,OAAO;IADM,YAAY,QAAQ,OAAO,IAAI,UAAU,QAAQ;IAG5D,SAAS;IACR,SAAuC;IACxC,QAAQ;IACR,OAAO;IACP,SAAS;IACT,KAAK;GACP;EACF,SAEE,iBACE,KAAK,QACD,aAAa,KAAK,OAAO;GACvB,UAAU,SAAS;GACnB,SAAS,QAAQ;GACjB,QAAQ,OAAO;GACf,MAAM,KAAK;EACb,CAAC,IACD,CAAC,CACP,CACJ;EAEA,MAAM,aAAa,SAAoC,CAAC,CAAC,QAAQ,cAAc,SAAS,IAAI;EAC5F,MAAM,WAAW,WACT;GAAC,KAAK,OAAO;GAAM,KAAK;GAAO,SAAS;EAAK,SAC7C;GACJ,MAAM,OAAO,KAAK;GAClB,MAAM,QACJ,MAAM,aAAa,UAAU,IAAI,IAAI,gBAAgB,KAAM,MAAM,SAAS,KAAK,IAAI,CAAC;GACtF,OAAO,iBAAiB,KAAK;EAC/B,CACF;EACA,MAAM,WAAW,WACT,CAAC,SAAS,KAAK,SACf,iBAAiB,iBAAiB,SAAS,KAAK,CAAC,CACzD;EACA,MAAM,WAAW,WACT,CAAC,SAAS,OAAO,MAAM,SAAS,OAAO,SAE3C,iBACE,aACE;GAAE,IAAI;GAAI,MAAM;GAAQ,UAAU,CAAC;EAAE,GACrC;GACE,UAAU,SAAS;GACnB,SAAS,KAAK,IAAI,GAAG,KAAK,MAAM,MAAM,SAAS,WAAW,EAAE,CAAC;GAC7D,QAAQ;EACV,CACF,CACF,CACJ;EAGA,IAAI;EACJ,MAAM,QAAQ,eAAe;GAC3B,MAAM,OAAO,WAAW,MAAM,UAAU,KAAK,OAAO,IAAI,MAAM,OAAO,SAAS,KAAK;GACnF,IAAI,CAAC,aAAa,CAAC,eAAe,WAAW,IAAI,GAAG,YAAY;GAChE,OAAO;EACT,CAAC;EACD,MAAM,aAAa,eAAe;GAChC,MAAM,UAAU,KAAK;GACrB,IAAI,CAAC,SAAS,OAAO;GACrB,OAAO,OAAO,OAAO,KAAM,QAAQ,OAAO,KAAK,KAAK,OAAO,SAAS;EACtE,CAAC;EAED,MAAM,YAAY,WACV;GACJ,KAAK,OAAO;GACX,KAAK,OAAqC;GAC3C,MAAM;GACN,KAAK;GACL,SAAS;EACX,SAEE,iBACE,KAAK,QACD,cAAc,KAAK,OAAO;GACxB,UAAU,SAAS;GACnB,OAAO,MAAM;GACb,MAAM,KAAK;EACb,CAAC,IACD,CAAC,CACP,CACJ;EACA,MAAM,iBAAiB,eAAe;GACpC,MAAM,QAAQ,MAAM,WAAW;GAC/B,OAAO,QAAQ,OAAO,KAAK,KAAK,IAAI,KAAA;EACtC,CAAC;EACD,MAAM,WAAW,WACT;GAAC,WAAW;GAAO,MAAM;GAAO,SAAS;GAAO,eAAe,OAAO,KAAK;EAAC,SAEhF,iBACE,WAAW,QACP,aAAa;GACX,UAAU,SAAS;GACnB,OAAO,MAAM;GACb,YAAY,eAAe;EAC7B,CAAC,IACD,CAAC,CACP,CACJ;;EAGA,SAAS,OAAO,IAA4B;GAC1C,IAAI,CAAC,MAAM,UAAU,MAAM,SAAS,EAAE;EACxC;EAEA,SAAS,OAAO,IAAY,OAAgC;GAC1D,MAAM,KAAK,MAAM,YAAY,CAAC,CAAC,OAAO,IAAI,KAAK;GAC/C,GAAG,QAAQ,SAAS,aAAa,GAAG,GAAG,OAAO,KAAK,KAAK,CAAC,CAAC,KAAK,GAAG,GAAG;GACrE,GAAG,QAAQ,UAAU,WAAW;GAChC,OAAO,EAAE;GACT,OAAO,eAAe,MAAM,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE;EACjD;EAEA,MAAM,YAAY,mBAAmB;GACnC,cAAc,KAAK;GACnB,YAAY,SAAS;GACrB,cAAc,gBAAgB;GAC9B,QAAQ,UACN,KAAK,QAAS,OAAO,KAAK,MAAM,IAAI,KAAK,IAA2C,KAAA;EACxF,CAAC;EAED,MAAM,aAAa,mBAAmB;GACpC,cAAc,KAAK;GACnB,YAAY,UAAU;GACtB,cAAc,gBAAgB;GAC9B,QAAQ,UACN,KAAK,QAAS,OAAO,KAAK,MAAM,IAAI,KAAK,IAA2C,KAAA;EACxF,CAAC;EAED,MAAM,YAAY,mBAAmB;GACnC,cAAc,KAAK;GACnB,YAAY,SAAS;GACrB,cAAc,gBAAgB;GAC9B,UAAU,SAAS;IACjB,MAAM,QAAS,KAAK,SAAwC,CAAC;IAC7D,OAAO;KAAE,GAAG;KAAM,OAAO,MAAM,IAAI,UAAU;IAAE;GACjD;GACA,QAAQ,UAAU;IAChB,MAAM,UAAU,KAAK;IACrB,IAAI,CAAC,WAAW,EAAE,WAAW,QAAQ,OAAO,KAAA;IAE5C,MAAM,SADS,MAAM,SAAmD,CAAC,EAAA,CACrD,IAAI,UAAU;IAClC,OAAO,OAAO,QAAQ,IAAI,EAAE,OAAO,MAAM,SAAS,QAAQ,KAAA,EAAU,CAAC;GAEvE;EACF,CAAC;;EAGD,MAAM,WAAW,eACf,MAAM,QAAQ,IACV,CAAC,IACD,MAAM,WAAW,CAAC,CAAC,WAAW,SAAS,cAAc,UAAU,OAAO,KAAK,KAAK,CAAC,CACvF;EAEA,MAAM,YAAY,mBAAmB;GACnC,cAAe,KAAK,OAAqC;GACzD,WAAW,KAAK,OAAO;GACvB,YAAY,SAAS;GACrB,cAAc,gBAAgB;GAC9B,UAAU,UAAU;IAElB,MAAM,OAAO,KAAK,OAAO;IACzB,MAAM,UAAU,OAAO,MAAM,QAAQ,KAAA;IACrC,IAAI,QAAQ,MAAM,QAAQ,OAAO,KAAK,QAAQ,MAAM,WAAW,OAAO,WAAW,QAAQ,GACvF,MAAM,QAAQ,iBAAiB,OAAO,CAAC,CAAC,KAAK,EAAE,OAAO,aAAa;KAAE;KAAO;IAAM,EAAE;IACtF,OAAO;GACT;GACA,QAAQ,UAAU;IAChB,MAAM,UAAU,KAAK;IACrB,IAAI,CAAC,SAAS,OAAO,KAAA;IACrB,MAAM,QAAiC,EAAE,GAAG,QAAQ,MAAM;IAC1D,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,KAAK,GAC7C,IAAI,UAAU,KAAA,GAAW,OAAO,MAAM;SACjC,MAAM,OAAO;IAGpB,OADa,OAAO,QAAQ,IAAI,EAAE,OAAO,OAAO,KAAK,KAAK,CAAC,CAAC,SAAS,QAAQ,KAAA,EAAU,CAC/E,CAAA,EAAoC;GAC9C;EACF,CAAC;EAGD,MAAM,cAAc;GAClB;GACA;GACA;GACA;GACA;GACA;EACF;EACA,IAAI,eAAwC,CAAC;EAC7C,MAAM,qBAAqB,eAAe;GACxC,MAAM,WAAW,MAAM;GACvB,IAAI,YAAY,OAAO,QAAQ,aAAa,SAAS,SAAS,IAAI,GAAG,OAAO;GAC5E,MAAM,OAAgC,CAAC;GACvC,KAAK,MAAM,OAAO,aAAa,IAAI,SAAS,SAAS,KAAA,GAAW,KAAK,OAAO,SAAS;GACrF,OAAQ,eAAe;EACzB,CAAC;EAED,MAAM,YAAY,mBAAmB;GACnC,cAAc,mBAAmB;GACjC,YAAY,SAAS;GACrB,cAAc,gBAAgB;GAC9B,QAAQ,UAAU;IAChB,MAAM,KAAK,MAAM,YAAY,CAAC,CAAC,eAAe,KAAK;IACnD,GAAG,QAAQ,SAAS,sBAAsB,OAAO,KAAK,KAAK,CAAC,CAAC,KAAK,GAAG,GAAG;IACxE,GAAG,QAAQ,UAAU,WAAW;IAChC,OAAO,EAAE;IACT,OAAO,mBAAmB;GAC5B;EACF,CAAC;EAED,MAAM,YAAY,mBAAmB;GACnC,cACE,MAAM,QAAQ,IAAK,MAAM,QAAQ,QAAgD,KAAA;GACnF,WAAW,MAAM,UAAU,KAAK;GAChC,YAAY,SAAS;GACrB,cAAc,gBAAgB;GAC9B,QAAQ,UAAU;IAChB,MAAM,KAAK,MAAM,YAAY;IAC7B,KAAK,MAAM,MAAM,MAAM,WAAW,GAAG,OAAO,IAAI,KAAK;IACrD,GAAG,QAAQ,SAAS,aAAa,MAAM,UAAU,KAAK,EAAE,MAAM;IAC9D,OAAO,EAAE;IACT,OAAO,MAAM,QAAQ;GACvB;EACF,CAAC;;EAGD,SAAS,WAAW,SAAmB;GACrC,MAAM,WAAW,MAAM;GACvB,MAAM,QAAQ,QAAQ,UAAU,eAAe,QAAQ,CAAC,CAAC,IAAI,QAAQ,EAAE,CAAC,EAAE,QAAQ,MAAM,IAAI;GAC5F,MAAM,wBAAQ,IAAI,IAAY;GAC9B,MAAM,SAAS,UAA+B;IAC5C,KAAK,MAAM,QAAQ,OAAO;KACxB,IAAI,KAAK,OAAO,QAAQ,MAAM,UAAU,QAAQ,KAAK,MAAM,MAAM,IAAI,KAAK,IAAI;KAC9E,IAAI,YAAY,IAAI,KAAK,CAAC,OAAO,IAAI,GAAG,MAAM,KAAK,QAAQ;IAC7D;GACF;GACA,MAAM,QAAQ,MAAM,WAAW,SAAS,KAAK;GAC7C,OAAO;EACT;EAEA,MAAM,YAAY,gBAA2B,EAC3C,MAAM,CACJ;GACE,YAAY,UAAmB;IAC7B,MAAM,UAAU,KAAK;IACrB,IAAI,CAAC,SAAS,OAAO;IACrB,MAAM,OAAO,OAAO,UAAU,WAAW,MAAM,KAAK,IAAI;IACxD,IAAI,CAAC,MAAM,OAAO,WAAW,QAAQ,SAAS,MAAM,OAAO,OAAO;IAClE,IAAI,WAAW,OAAO,CAAC,CAAC,IAAI,IAAI,GAC9B,OAAO,cAAc,SAAS,MAAM,OAAO,OAAO,EAAE,MAAM,KAAK,CAAC;IAClE,OAAO;GACT;GACA,SAAS;EACX,CACF,EACF,EAAE;EAEF,MAAM,UAAU,eAAe;GAC7B,IAAI,MAAM,QAAQ,GAChB,OAAO;IACL,MAAM;IACN,OAAO,cAAc,SAAS,MAAM,UAAU,UAAU,EAAE,OAAO,MAAM,MAAM,CAAC;IAC9E,MAAM;GACR;GACF,MAAM,UAAU,KAAK;GACrB,IAAI,CAAC,SAAS,OAAO;IAAE,MAAM,KAAA;IAAW,OAAO,SAAS,MAAM,UAAU;IAAM,MAAM;GAAG;GACvF,MAAM,OAAO,QAAQ,QAAQ,MAAM,MAAM,MAAM,IAAI,QAAQ,IAAI,GAAG,SAAS,KAAK;GAChF,MAAM,QAAQ,UAAU,SAAS,MAAM,OAAO,SAAS,KAAK;GAC5D,OAAO;IACL,MAAM,OAAO,QAAQ,MAAM,MAAM,MAAM,IAAI,QAAQ,IAAI,CAAC;IACxD;IACA,MAAM,UAAU,OAAO,KAAK;GAC9B;EACF,CAAC;EAED,MAAM,aAAa,eAAe,KAAK,OAAO,SAAS,UAAU,KAAK,OAAO,SAAS,OAAO;EAC7F,MAAM,UAAU,eAAe;GAC7B,MAAM,MAAM,eAAe,MAAM,QAAQ;GAEzC,OAAO,IADa,IAAI,MAAM,UAAU,KAAK,OAAO,IAAI,IAAI,EAAE,CAAC,EAAE,QAAQ,MAAM,IAAI,CAC5E,CAAA,CAAQ,SAAS,KAAK,CAAC,MAAM,UAAU,MAAM,OAAO,IAAI,IAAI,EAAE,CAAC,EAAE,KAAK,SAAS,MAAM;EAC9F,CAAC;;GAIC,OAAAA,UAAA,GAAAC,mBA0EM,OAAA;IA1EG,SAAA;IAAJ,KAAI;IAAO,OAAM;G,IACpBC,mBAIM,OAJN,YAIM;IAHgC,QAAA,MAAQ,QAA5CF,UAAA,GAAAG,YAA6FC,wBAA7E,QAAA,MAAQ,IAAI,GAAA;;KAAsB,OAAM;;IACxDF,mBAA0E,QAA1E,YAA0EI,gBAAvB,QAAA,MAAQ,KAAK,GAAA,CAAA;IACpD,QAAA,MAAQ,QAApBN,UAAA,GAAAC,mBAA4F,QAA5F,YAA4FK,gBAAtB,QAAA,MAAQ,IAAI,GAAA,CAAA,K;G,IAEpFJ,mBAmEM,OAnEN,YAmEM,CAlEY,MAAA,QAAK,KAArBF,UAAA,GAAAC,mBAgBWM,UAAA,EAAA,KAAA,EAAA,GAAA,CAfTC,YAAoEC,uBAAA;IAArD,MAAMC,MAAA,QAAA;IAAW,OAAOA,MAAA,SAAA;IAAY,QAAQA,MAAA,KAAA;;;;;G,IAC/C,CAAAA,MAAA,KAAA,CAAK,CAAC,YAAlBV,UAAA,GAAAC,mBAaM,OAbN,YAaM;IAZJO,YAGYE,MAAA,SAAA,GAAA;KAHD,MAAK;KAAK,SAAQ;KAAW,SAAK,OAAA,OAAA,OAAA,MAAA,WAAEA,MAAA,KAAA,CAAK,CAAC,UAAS;;KACjD,SAAOC,cAAa,CAAZH,YAAYE,MAAA,QAAA,CAAA,C;KAAW,SAAAC,cAC1C,CAD0CC,gBAAA,MAC1CN,gBAAG,SAAA,MAAS,QAAQ,SAAS,GAAA,CAAA,C;;;IAE/BE,YAGYE,MAAA,SAAA,GAAA;KAHD,MAAK;KAAK,SAAQ;KAAW,UAAQ,CAAG,QAAA;KAAU,SAAK,OAAA,OAAA,OAAA,MAAA,WAAEA,MAAA,KAAA,CAAK,CAAC,KAAI;;KACjE,SAAOC,cAAqB,CAApBH,YAAoBE,MAAA,gBAAA,CAAA,C;KAAW,SAAAC,cAClD,CADkDC,gBAAA,MAClDN,gBAAG,SAAA,MAAS,QAAQ,IAAI,GAAA,CAAA,C;;;IAE1BE,YAGYE,MAAA,SAAA,GAAA;KAHD,MAAK;KAAK,SAAQ;KAAU,MAAK;KAAU,SAAK,OAAA,OAAA,OAAA,MAAA,WAAEA,MAAA,KAAA,CAAK,CAAC,OAAM;;KAC5D,SAAOC,cAAc,CAAbH,YAAaE,MAAA,SAAA,CAAA,C;KAAW,SAAAC,cAC3C,CAD2CC,gBAAA,MAC3CN,gBAAG,SAAA,MAAS,QAAQ,MAAM,GAAA,CAAA,C;;;G,4CAIX,KAAA,SAArBN,UAAA,GAAAC,mBA2CWM,UAAA,EAAA,KAAA,EAAA,GAAA;KA1CTP,UAAA,GAAAG,YAMEM,uBAAA;KALC,KAAK,KAAA,MAAK;KACV,MAAMC,MAAA,QAAA;KACN,OAAOA,MAAA,SAAA;KACP,QAAQ,eAAA;KACR,OAAO,UAAA;;;;;;;IAGF,WAAA,SAAU,CAAKA,MAAA,KAAA,CAAK,CAAC,YAD7BV,UAAA,GAAAG,YASYO,MAAA,SAAA,GAAA;;KAPV,OAAM;KACN,MAAK;KACL,SAAQ;KACP,SAAK,OAAA,OAAA,OAAA,MAAA,WAAEA,MAAA,KAAA,CAAK,CAAC,QAAQ,KAAA,MAAK,EAAE;;KAElB,SAAOC,cAAa,CAAZH,YAAYE,MAAA,QAAA,CAAA,C;KAAW,SAAAC,cAC1C,CAD0CC,gBAAA,MAC1CN,gBAAG,SAAA,MAAS,QAAQ,OAAO,GAAA,CAAA,C;;;IAEbI,MAAA,QAAA,CAAQ,CAAC,MAAM,UAA/BV,UAAA,GAAAC,mBAQWM,UAAA,EAAA,KAAA,EAAA,GAAA,CAPTL,mBAAoF,OAApF,YAAoFI,gBAAhC,SAAA,MAAS,UAAU,IAAI,GAAA,CAAA,IAC3EN,UAAA,GAAAG,YAKEM,uBAAA;KAJC,KAAG,GAAK,KAAA,MAAK,GAAE;KACf,MAAMC,MAAA,QAAA;KACN,OAAOA,MAAA,SAAA;KACP,QAAQ,eAAA;;;;;;IAGGA,MAAA,QAAA,CAAQ,CAAC,MAAM,UAA/BV,UAAA,GAAAC,mBAQWM,UAAA,EAAA,KAAA,EAAA,GAAA,CAPTL,mBAAqF,OAArF,YAAqFI,gBAAjC,SAAA,MAAS,UAAU,KAAK,GAAA,CAAA,IAC5EN,UAAA,GAAAG,YAKEM,uBAAA;KAJC,KAAG,GAAK,KAAA,MAAK,GAAE;KACf,MAAMC,MAAA,QAAA;KACN,OAAOA,MAAA,SAAA;KACP,QAAQ,eAAA;;;;;;IAGbR,mBAAqF,OAArF,YAAqFI,gBAAjC,SAAA,MAAS,UAAU,KAAK,GAAA,CAAA;KAC5EN,UAAA,GAAAG,YAKEM,uBAAA;KAJC,KAAG,GAAK,KAAA,MAAK,GAAE;KACf,MAAMC,MAAA,SAAA;KACN,OAAOA,MAAA,UAAA;KACP,QAAQ,eAAA;;;;;;G,WAGbV,UAAA,GAAAG,YAA2EM,uBAAA;;IAArD,MAAMC,MAAA,QAAA;IAAW,OAAOA,MAAA,SAAA;IAAY,QAAQA,MAAA,KAAA;;;;;G,MAClEV,UAAA,IAAA,GAAAC,mBAGWM,UAAA,MAAAM,WAHiB,SAAA,QAAX,YAAO;I,mDAAoB,KAAA,QAAQ,I,IAClDX,mBAA0E,OAA1E,YAA0EI,gBAAtB,QAAQ,KAAK,GAAA,CAAA,IACjEN,UAAA,GAAAG,YAA4DC,wBAA5C,QAAQ,SAAS,GAAjCU,WAA4D,EAAA,SAAA,KAAA,GAAjB,QAAQ,KAAK,GAAA,MAAA,EAAA,E"}
@@ -0,0 +1,6 @@
1
+ import json_dialog_vue_vue_type_script_setup_true_lang_default from "./json-dialog.vue_vue_type_script_setup_true_lang.js";
2
+ // src/builder/json-dialog.vue
3
+ var json_dialog_default = json_dialog_vue_vue_type_script_setup_true_lang_default;
4
+ export { json_dialog_default as default };
5
+
6
+ //# sourceMappingURL=json-dialog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json-dialog.js","names":["_sfc_main"],"sources":["../../src/builder/json-dialog.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, onBeforeUnmount, shallowRef, useTemplateRef, watch } from 'vue'\nimport { DouButton, DouDialog, DouTextarea, downloadBlob } from 'dou-ui'\nimport { CopyCheckIcon, CopyIcon, DownloadIcon, FileUpIcon, IndentIcon } from '@dou-ui/icons'\nimport { checkDocument, checkDocumentShape, migrateDocument } from '../core/check'\nimport type { DocumentProblem } from '../core/check'\nimport type { FormDocument } from '../core/types'\nimport { formatMessage } from '../locale'\nimport { useBuilderState } from './context'\n\n/**\n * The form as JSON: to read, copy, download, or replace by pasting or\n * opening a file. What is wrong with new text is listed by its path as it\n * is typed; problems that would break the builder keep it from applying.\n */\ndefineOptions({ name: 'DouFormBuilderJson' })\n\nconst open = defineModel<boolean>('open', { default: false })\n\nconst state = useBuilderState()\nconst messages = computed(() => state.messages.json)\n\nconst draft = shallowRef('')\nconst original = shallowRef('')\nwatch(\n open,\n (now) => {\n if (!now) return\n original.value = JSON.stringify(state.document, null, 2)\n draft.value = original.value\n },\n { immediate: true },\n)\n\ninterface Finding {\n path: string\n text: string\n /** Applying it would break the builder. */\n blocking: boolean\n}\n\n/** Problems that leave the builder unable to place nodes; the rest only warn. */\nconst BLOCKING = new Set<DocumentProblem['code']>([\n 'version',\n 'duplicate-id',\n 'misplaced-page',\n 'not-a-page',\n])\n\n/** Where `JSON.parse` stopped, as a line and column, when its message gives the position. */\nfunction syntaxPlace(text: string, error: unknown) {\n const match = /position (\\d+)/.exec(String((error as Error)?.message))\n if (!match) return undefined\n const before = text.slice(0, Number(match[1]))\n const lines = before.split('\\n')\n return { line: lines.length, column: lines[lines.length - 1]!.length + 1 }\n}\n\nconst analysis = computed<{ document?: FormDocument; findings: Finding[] }>(() => {\n const text = draft.value\n const words = messages.value\n let data: unknown\n try {\n data = JSON.parse(text)\n } catch (error) {\n const place = syntaxPlace(text, error)\n return {\n findings: [\n {\n path: '',\n text: place ? formatMessage(words.syntaxAt, place) : words.syntax,\n blocking: true,\n },\n ],\n }\n }\n // Problems of shape block applying, and are listed together with those of content.\n const findings: Finding[] = checkDocumentShape(data).map((problem) => ({\n path: problem.path,\n text:\n (problem.code === 'required' ? words.shape.required : words.shape[problem.expected]) ??\n problem.message,\n blocking: true,\n }))\n let document: FormDocument\n try {\n document = migrateDocument(data)\n } catch {\n if (data === null || typeof data !== 'object' || Array.isArray(data)) return { findings }\n const version = String((data as { version?: unknown }).version)\n findings.push({\n path: 'version',\n text: formatMessage(words.problems.version!, { text: version }),\n blocking: true,\n })\n return { findings }\n }\n let problems: DocumentProblem[] = []\n try {\n problems = checkDocument(document, {\n fields: [...state.fields.values()],\n functions: state.functionNames.value,\n // Names are checked only when the builder was given validators.\n validators: state.validators() ? Object.keys(state.validators()!) : undefined,\n })\n } catch {\n // Content too far off its shape to read; the shape problems say why.\n }\n const expressionWords = state.messages.expression.problems\n for (const problem of problems) {\n const own = problem.expression\n const said = own\n ? formatMessage(expressionWords[own.code] ?? own.message, { text: own.text })\n : formatMessage(words.problems[problem.code] ?? problem.message, { text: problem.text })\n findings.push({ path: problem.path, text: said, blocking: BLOCKING.has(problem.code) })\n }\n return { document: findings.some((f) => f.blocking) ? undefined : document, findings }\n})\n\nconst blocked = computed(() => analysis.value.findings.some((finding) => finding.blocking))\nconst changed = computed(() => draft.value !== original.value)\nconst SHOWN = 8\nconst shownFindings = computed(() => analysis.value.findings.slice(0, SHOWN))\nconst more = computed(() => analysis.value.findings.length - shownFindings.value.length)\n\nfunction apply() {\n const document = analysis.value.document\n if (!document || blocked.value) return\n state.replace(document)\n open.value = false\n}\n\n/** The text parsed, or `undefined` while it is not JSON. */\nconst parsed = computed(() => {\n try {\n return { data: JSON.parse(draft.value) as unknown }\n } catch {\n return undefined\n }\n})\nconst formatted = computed(() =>\n parsed.value ? JSON.stringify(parsed.value.data, null, 2) : undefined,\n)\nfunction format() {\n if (formatted.value !== undefined) draft.value = formatted.value\n}\n\nconst file = useTemplateRef<HTMLInputElement>('file')\nasync function onFile(event: Event) {\n const input = event.target as HTMLInputElement\n const chosen = input.files?.[0]\n input.value = ''\n if (chosen) draft.value = await chosen.text()\n}\n\nconst copied = shallowRef(false)\nlet copiedTimer: ReturnType<typeof setTimeout> | undefined\nonBeforeUnmount(() => clearTimeout(copiedTimer))\nasync function copy() {\n try {\n await navigator.clipboard.writeText(draft.value)\n } catch {\n return\n }\n copied.value = true\n clearTimeout(copiedTimer)\n copiedTimer = setTimeout(() => (copied.value = false), 1500)\n}\n\nfunction download() {\n downloadBlob(new Blob([draft.value], { type: 'application/json' }), 'form.json')\n}\n</script>\n\n<template>\n <DouDialog\n v-model:open=\"open\"\n :title=\"messages.title\"\n width=\"640px\"\n class=\"dou-form-builder__json\"\n destroy-on-close\n >\n <DouTextarea\n v-model=\"draft\"\n :rows=\"16\"\n :invalid=\"blocked\"\n :readonly=\"state.readonly\"\n :aria-label=\"messages.title\"\n spellcheck=\"false\"\n class=\"dou-form-builder__json-text\"\n />\n <div class=\"dou-form-builder__json-status\" aria-live=\"polite\">\n <ul v-if=\"analysis.findings.length\" class=\"dou-form-builder__json-problems\">\n <li\n v-for=\"(finding, index) in shownFindings\"\n :key=\"index\"\n :class=\"['dou-form-builder__json-problem', finding.blocking && 'is-blocking']\"\n >\n <code v-if=\"finding.path\" class=\"dou-form-builder__json-path\">{{ finding.path }}</code>\n <span>{{ finding.text }}</span>\n </li>\n <li v-if=\"more > 0\" class=\"dou-form-builder__json-problem\">\n {{ formatMessage(messages.more, { count: more }) }}\n </li>\n </ul>\n <div v-else class=\"dou-form-builder__json-fine\">{{ messages.fine }}</div>\n </div>\n <template #footer>\n <div class=\"dou-form-builder__json-footer\">\n <input\n ref=\"file\"\n type=\"file\"\n accept=\".json,application/json\"\n class=\"dou-form-builder__json-file\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n @change=\"onFile\"\n />\n <DouButton\n v-if=\"!state.readonly\"\n size=\"sm\"\n variant=\"ghost\"\n :disabled=\"formatted === undefined || formatted === draft\"\n @click=\"format\"\n >\n <template #leading><IndentIcon /></template>\n {{ messages.format }}\n </DouButton>\n <DouButton v-if=\"!state.readonly\" size=\"sm\" variant=\"ghost\" @click=\"file?.click()\">\n <template #leading><FileUpIcon /></template>\n {{ messages.file }}\n </DouButton>\n <DouButton size=\"sm\" variant=\"ghost\" @click=\"download\">\n <template #leading><DownloadIcon /></template>\n {{ messages.download }}\n </DouButton>\n <DouButton size=\"sm\" variant=\"ghost\" @click=\"copy\">\n <template #leading>\n <CopyCheckIcon v-if=\"copied\" />\n <CopyIcon v-else />\n </template>\n {{ copied ? messages.copied : messages.copy }}\n </DouButton>\n <span class=\"dou-form-builder__json-spacer\" />\n <DouButton v-if=\"state.readonly\" size=\"sm\" variant=\"outline\" @click=\"open = false\">\n {{ messages.close }}\n </DouButton>\n <template v-else>\n <DouButton size=\"sm\" variant=\"outline\" @click=\"open = false\">\n {{ messages.cancel }}\n </DouButton>\n <DouButton size=\"sm\" tone=\"primary\" :disabled=\"!changed || blocked\" @click=\"apply\">\n {{ messages.apply }}\n </DouButton>\n </template>\n </div>\n </template>\n </DouDialog>\n</template>\n"],"mappings":""}