@dou-ui/form-builder 0.0.0-stage → 0.1.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +10 -2
- package/dist/builder/canvas.js +695 -0
- package/dist/builder/canvas.js.map +1 -0
- package/dist/builder/completion.js +49 -0
- package/dist/builder/completion.js.map +1 -0
- package/dist/builder/condition-editor.js +6 -0
- package/dist/builder/condition-editor.js.map +1 -0
- package/dist/builder/condition-editor.vue_vue_type_script_setup_true_lang.js +410 -0
- package/dist/builder/condition-editor.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/builder/condition.js +159 -0
- package/dist/builder/condition.js.map +1 -0
- package/dist/builder/context.js +477 -0
- package/dist/builder/context.js.map +1 -0
- package/dist/builder/core/commands.js +373 -0
- package/dist/builder/core/commands.js.map +1 -0
- package/dist/builder/core/history.js +76 -0
- package/dist/builder/core/history.js.map +1 -0
- package/dist/builder/core/transaction.js +298 -0
- package/dist/builder/core/transaction.js.map +1 -0
- package/dist/builder/drag.js +466 -0
- package/dist/builder/drag.js.map +1 -0
- package/dist/builder/expression-box.js +19 -0
- package/dist/builder/expression-box.js.map +1 -0
- package/dist/builder/expression-input.js +6 -0
- package/dist/builder/expression-input.js.map +1 -0
- package/dist/builder/expression-input.vue_vue_type_script_setup_true_lang.js +117 -0
- package/dist/builder/expression-input.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/builder/extension.js +47 -0
- package/dist/builder/extension.js.map +1 -0
- package/dist/builder/form-builder.js +6 -0
- package/dist/builder/form-builder.js.map +1 -0
- package/dist/builder/form-builder.vue_vue_type_script_setup_true_lang.js +450 -0
- package/dist/builder/form-builder.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/builder/index.js +22 -0
- package/dist/builder/index.js.map +1 -0
- package/dist/builder/inspector.js +6 -0
- package/dist/builder/inspector.js.map +1 -0
- package/dist/builder/inspector.vue_vue_type_script_setup_true_lang.js +442 -0
- package/dist/builder/inspector.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/builder/json-dialog.js +6 -0
- package/dist/builder/json-dialog.js.map +1 -0
- package/dist/builder/json-dialog.vue_vue_type_script_setup_true_lang.js +281 -0
- package/dist/builder/json-dialog.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/builder/locale.js +1271 -0
- package/dist/builder/locale.js.map +1 -0
- package/dist/builder/logic-fields.js +18 -0
- package/dist/builder/logic-fields.js.map +1 -0
- package/dist/builder/logic.js +332 -0
- package/dist/builder/logic.js.map +1 -0
- package/dist/builder/menu.js +92 -0
- package/dist/builder/menu.js.map +1 -0
- package/dist/builder/outline-row.js +6 -0
- package/dist/builder/outline-row.js.map +1 -0
- package/dist/builder/outline-row.vue_vue_type_script_setup_true_lang.js +88 -0
- package/dist/builder/outline-row.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/builder/outline.js +6 -0
- package/dist/builder/outline.js.map +1 -0
- package/dist/builder/outline.vue_vue_type_script_setup_true_lang.js +111 -0
- package/dist/builder/outline.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/builder/palette.js +6 -0
- package/dist/builder/palette.js.map +1 -0
- package/dist/builder/palette.vue_vue_type_script_setup_true_lang.js +96 -0
- package/dist/builder/palette.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/builder/preview.js +6 -0
- package/dist/builder/preview.js.map +1 -0
- package/dist/builder/preview.vue_vue_type_script_setup_true_lang.js +111 -0
- package/dist/builder/preview.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/builder/settings-binding.js +57 -0
- package/dist/builder/settings-binding.js.map +1 -0
- package/dist/builder/settings.js +487 -0
- package/dist/builder/settings.js.map +1 -0
- package/dist/builder/span-field.js +104 -0
- package/dist/builder/span-field.js.map +1 -0
- package/dist/code/expression-input.js +6 -0
- package/dist/code/expression-input.js.map +1 -0
- package/dist/code/expression-input.vue_vue_type_script_setup_true_lang.js +88 -0
- package/dist/code/expression-input.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/code/extension.js +202 -0
- package/dist/code/extension.js.map +1 -0
- package/dist/code/index.js +19 -0
- package/dist/code/index.js.map +1 -0
- package/dist/code/language.js +43 -0
- package/dist/code/language.js.map +1 -0
- package/dist/collaboration/index.js +382 -0
- package/dist/collaboration/index.js.map +1 -0
- package/dist/collaboration/order.js +88 -0
- package/dist/collaboration/order.js.map +1 -0
- package/dist/core/check.js +314 -0
- package/dist/core/check.js.map +1 -0
- package/dist/core/document.js +112 -0
- package/dist/core/document.js.map +1 -0
- package/dist/core/expression.js +854 -0
- package/dist/core/expression.js.map +1 -0
- package/dist/core/formulas.js +242 -0
- package/dist/core/formulas.js.map +1 -0
- package/dist/core/rules.js +83 -0
- package/dist/core/rules.js.map +1 -0
- package/dist/core/values.js +80 -0
- package/dist/core/values.js.map +1 -0
- package/dist/fields/builtin.js +167 -0
- package/dist/fields/builtin.js.map +1 -0
- package/dist/fields/components.js +155 -0
- package/dist/fields/components.js.map +1 -0
- package/dist/fields/define.js +44 -0
- package/dist/fields/define.js.map +1 -0
- package/dist/fields/format.js +125 -0
- package/dist/fields/format.js.map +1 -0
- package/dist/fields/options.js +54 -0
- package/dist/fields/options.js.map +1 -0
- package/dist/index.js +20 -0
- package/dist/locale.js +161 -0
- package/dist/locale.js.map +1 -0
- package/dist/renderer/containers.js +430 -0
- package/dist/renderer/containers.js.map +1 -0
- package/dist/renderer/context.js +21 -0
- package/dist/renderer/context.js.map +1 -0
- package/dist/renderer/form-renderer.js +6 -0
- package/dist/renderer/form-renderer.js.map +1 -0
- package/dist/renderer/form-renderer.vue_vue_type_script_setup_true_lang.js +272 -0
- package/dist/renderer/form-renderer.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/renderer/index.js +19 -0
- package/dist/renderer/index.js.map +1 -0
- package/dist/renderer/node-view.js +385 -0
- package/dist/renderer/node-view.js.map +1 -0
- package/dist/style.css +1 -0
- package/dist/style.d.ts +1 -0
- package/dist/style.js +27 -0
- package/dist/types/builder/canvas.d.ts +5 -0
- package/dist/types/builder/completion.d.ts +35 -0
- package/dist/types/builder/condition-editor.vue.d.ts +17 -0
- package/dist/types/builder/condition.d.ts +37 -0
- package/dist/types/builder/context.d.ts +149 -0
- package/dist/types/builder/core/commands.d.ts +74 -0
- package/dist/types/builder/core/history.d.ts +23 -0
- package/dist/types/builder/core/transaction.d.ts +108 -0
- package/dist/types/builder/drag.d.ts +52 -0
- package/dist/types/builder/expression-box.d.ts +8 -0
- package/dist/types/builder/expression-input.vue.d.ts +29 -0
- package/dist/types/builder/extension.d.ts +149 -0
- package/dist/types/builder/form-builder.vue.d.ts +24 -0
- package/dist/types/builder/index.d.ts +76 -0
- package/dist/types/builder/inspector.vue.d.ts +3 -0
- package/dist/types/builder/json-dialog.vue.d.ts +10 -0
- package/dist/types/builder/locale.d.ts +195 -0
- package/dist/types/builder/logic-fields.d.ts +2 -0
- package/dist/types/builder/logic.d.ts +57 -0
- package/dist/types/builder/menu.d.ts +23 -0
- package/dist/types/builder/outline-row.vue.d.ts +19 -0
- package/dist/types/builder/outline.vue.d.ts +3 -0
- package/dist/types/builder/palette.vue.d.ts +3 -0
- package/dist/types/builder/preview.vue.d.ts +3 -0
- package/dist/types/builder/settings-binding.d.ts +23 -0
- package/dist/types/builder/settings.d.ts +49 -0
- package/dist/types/builder/span-field.d.ts +4 -0
- package/dist/types/builder/types.d.ts +59 -0
- package/dist/types/code/expression-input.vue.d.ts +23 -0
- package/dist/types/code/extension.d.ts +45 -0
- package/dist/types/code/index.d.ts +12 -0
- package/dist/types/code/language.d.ts +6 -0
- package/dist/types/collaboration/index.d.ts +64 -0
- package/dist/types/collaboration/order.d.ts +20 -0
- package/dist/types/core/check.d.ts +68 -0
- package/dist/types/core/document.d.ts +36 -0
- package/dist/types/core/expression.d.ts +175 -0
- package/dist/types/core/formulas.d.ts +44 -0
- package/dist/types/core/rules.d.ts +23 -0
- package/dist/types/core/types.d.ts +211 -0
- package/dist/types/core/values.d.ts +22 -0
- package/dist/types/fields/builtin.d.ts +9 -0
- package/dist/types/fields/components.d.ts +177 -0
- package/dist/types/fields/define.d.ts +93 -0
- package/dist/types/fields/format.d.ts +76 -0
- package/dist/types/fields/options.d.ts +11 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/locale.d.ts +45 -0
- package/dist/types/renderer/containers.d.ts +20 -0
- package/dist/types/renderer/context.d.ts +186 -0
- package/dist/types/renderer/form-renderer.vue.d.ts +25 -0
- package/dist/types/renderer/index.d.ts +81 -0
- package/dist/types/renderer/node-view.d.ts +56 -0
- package/package.json +88 -4
|
@@ -0,0 +1,487 @@
|
|
|
1
|
+
import { markRaw } from "vue";
|
|
2
|
+
import { CalendarIcon, CheckSquareIcon, ChevronDownSquareIcon, ClockIcon, HashIcon, InfoSquareIcon, LayoutIcon, LayoutListIcon, ListChecksIcon, ListTreeIcon, OtpIcon, PaletteIcon, RadioIcon, SegmentedControlIcon, SeparatorHorizontalIcon, SlidersIcon, SquareDashedIcon, StarIcon, StepsIcon, TabsIcon, TagsIcon, TextAlignLeftIcon, TextCursorIcon, ToggleRightIcon, TreeStructureIcon, TypeIcon, UploadIcon } from "@dou-ui/icons";
|
|
3
|
+
// src/builder/settings.ts
|
|
4
|
+
/** The palette groups in the order they are listed; groups of other names follow. */
|
|
5
|
+
var paletteGroups = [
|
|
6
|
+
"input",
|
|
7
|
+
"choice",
|
|
8
|
+
"more",
|
|
9
|
+
"display",
|
|
10
|
+
"layout"
|
|
11
|
+
];
|
|
12
|
+
var raw = (icon) => markRaw(icon);
|
|
13
|
+
/** Icons and groups of the built-in types, kept out of the renderer's entry. */
|
|
14
|
+
var builtinLooks = {
|
|
15
|
+
input: {
|
|
16
|
+
icon: raw(TextCursorIcon),
|
|
17
|
+
group: "input"
|
|
18
|
+
},
|
|
19
|
+
textarea: {
|
|
20
|
+
icon: raw(TextAlignLeftIcon),
|
|
21
|
+
group: "input"
|
|
22
|
+
},
|
|
23
|
+
"input-number": {
|
|
24
|
+
icon: raw(HashIcon),
|
|
25
|
+
group: "input"
|
|
26
|
+
},
|
|
27
|
+
"input-tag": {
|
|
28
|
+
icon: raw(TagsIcon),
|
|
29
|
+
group: "input"
|
|
30
|
+
},
|
|
31
|
+
"input-otp": {
|
|
32
|
+
icon: raw(OtpIcon),
|
|
33
|
+
group: "input"
|
|
34
|
+
},
|
|
35
|
+
select: {
|
|
36
|
+
icon: raw(ChevronDownSquareIcon),
|
|
37
|
+
group: "choice"
|
|
38
|
+
},
|
|
39
|
+
"radio-group": {
|
|
40
|
+
icon: raw(RadioIcon),
|
|
41
|
+
group: "choice"
|
|
42
|
+
},
|
|
43
|
+
"checkbox-group": {
|
|
44
|
+
icon: raw(ListChecksIcon),
|
|
45
|
+
group: "choice"
|
|
46
|
+
},
|
|
47
|
+
checkbox: {
|
|
48
|
+
icon: raw(CheckSquareIcon),
|
|
49
|
+
group: "choice"
|
|
50
|
+
},
|
|
51
|
+
switch: {
|
|
52
|
+
icon: raw(ToggleRightIcon),
|
|
53
|
+
group: "choice"
|
|
54
|
+
},
|
|
55
|
+
"segmented-control": {
|
|
56
|
+
icon: raw(SegmentedControlIcon),
|
|
57
|
+
group: "choice"
|
|
58
|
+
},
|
|
59
|
+
cascader: {
|
|
60
|
+
icon: raw(ListTreeIcon),
|
|
61
|
+
group: "choice"
|
|
62
|
+
},
|
|
63
|
+
"tree-select": {
|
|
64
|
+
icon: raw(TreeStructureIcon),
|
|
65
|
+
group: "choice"
|
|
66
|
+
},
|
|
67
|
+
slider: {
|
|
68
|
+
icon: raw(SlidersIcon),
|
|
69
|
+
group: "more"
|
|
70
|
+
},
|
|
71
|
+
rate: {
|
|
72
|
+
icon: raw(StarIcon),
|
|
73
|
+
group: "more"
|
|
74
|
+
},
|
|
75
|
+
"date-picker": {
|
|
76
|
+
icon: raw(CalendarIcon),
|
|
77
|
+
group: "more"
|
|
78
|
+
},
|
|
79
|
+
"time-picker": {
|
|
80
|
+
icon: raw(ClockIcon),
|
|
81
|
+
group: "more"
|
|
82
|
+
},
|
|
83
|
+
"color-picker": {
|
|
84
|
+
icon: raw(PaletteIcon),
|
|
85
|
+
group: "more"
|
|
86
|
+
},
|
|
87
|
+
upload: {
|
|
88
|
+
icon: raw(UploadIcon),
|
|
89
|
+
group: "more"
|
|
90
|
+
},
|
|
91
|
+
text: {
|
|
92
|
+
icon: raw(TypeIcon),
|
|
93
|
+
group: "display"
|
|
94
|
+
},
|
|
95
|
+
divider: {
|
|
96
|
+
icon: raw(SeparatorHorizontalIcon),
|
|
97
|
+
group: "display"
|
|
98
|
+
},
|
|
99
|
+
alert: {
|
|
100
|
+
icon: raw(InfoSquareIcon),
|
|
101
|
+
group: "display"
|
|
102
|
+
},
|
|
103
|
+
section: {
|
|
104
|
+
icon: raw(SquareDashedIcon),
|
|
105
|
+
group: "layout"
|
|
106
|
+
},
|
|
107
|
+
tabs: {
|
|
108
|
+
icon: raw(TabsIcon),
|
|
109
|
+
group: "layout"
|
|
110
|
+
},
|
|
111
|
+
steps: {
|
|
112
|
+
icon: raw(StepsIcon),
|
|
113
|
+
group: "layout"
|
|
114
|
+
},
|
|
115
|
+
list: {
|
|
116
|
+
icon: raw(LayoutListIcon),
|
|
117
|
+
group: "layout"
|
|
118
|
+
},
|
|
119
|
+
page: {
|
|
120
|
+
icon: raw(LayoutIcon),
|
|
121
|
+
group: "layout"
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
/** The containers the palette offers, after the field types. */
|
|
125
|
+
var containerTypes = [
|
|
126
|
+
"section",
|
|
127
|
+
"tabs",
|
|
128
|
+
"steps",
|
|
129
|
+
"list"
|
|
130
|
+
];
|
|
131
|
+
/** A type's icon: its own, else the built-in one, else a plain box. */
|
|
132
|
+
function iconOf(type, spec) {
|
|
133
|
+
return spec?.icon ?? builtinLooks[type]?.icon ?? builtinLooks.section.icon;
|
|
134
|
+
}
|
|
135
|
+
function groupOf(type, spec) {
|
|
136
|
+
return spec?.group ?? builtinLooks[type]?.group ?? "more";
|
|
137
|
+
}
|
|
138
|
+
/** A type's name for people: its own `label`, else the locale's. */
|
|
139
|
+
function labelOf(type, spec, messages) {
|
|
140
|
+
return spec?.label ?? messages.types[type] ?? type;
|
|
141
|
+
}
|
|
142
|
+
/** What a node is called in the outline and the inspector's heading. */
|
|
143
|
+
function nodeTitle(node, fields, messages) {
|
|
144
|
+
const record = node;
|
|
145
|
+
const own = record.label ?? record.title;
|
|
146
|
+
if (own) return own;
|
|
147
|
+
if ("name" in node && node.name) return node.name;
|
|
148
|
+
return labelOf(node.type, fields.get(node.type), messages);
|
|
149
|
+
}
|
|
150
|
+
var field = (type, name, label, extra = {}) => ({
|
|
151
|
+
id: `setting-${name}`,
|
|
152
|
+
type,
|
|
153
|
+
name,
|
|
154
|
+
label,
|
|
155
|
+
...extra
|
|
156
|
+
});
|
|
157
|
+
var sw = (name, label, extra = {}) => field("switch", name, label, extra);
|
|
158
|
+
var text = (name, label, extra = {}) => field("input", name, label, {
|
|
159
|
+
...extra,
|
|
160
|
+
props: {
|
|
161
|
+
clearable: true,
|
|
162
|
+
...extra.props
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
var number = (name, label, props = {}, extra = {}) => field("input-number", name, label, {
|
|
166
|
+
...extra,
|
|
167
|
+
props: {
|
|
168
|
+
controls: false,
|
|
169
|
+
...props
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
function choices(messages, key, values) {
|
|
173
|
+
const labels = messages.choices[key] ?? {};
|
|
174
|
+
return values.map((value) => ({
|
|
175
|
+
value,
|
|
176
|
+
label: labels[String(value)] ?? String(value)
|
|
177
|
+
}));
|
|
178
|
+
}
|
|
179
|
+
var segmented = (messages, name, values, fallback, extra = {}, key = name) => field("segmented-control", name, messages.settings[key] ?? name, {
|
|
180
|
+
default: fallback,
|
|
181
|
+
props: {
|
|
182
|
+
options: choices(messages, key, values),
|
|
183
|
+
block: true
|
|
184
|
+
},
|
|
185
|
+
...extra
|
|
186
|
+
});
|
|
187
|
+
function optionList(messages, name = "options") {
|
|
188
|
+
const s = messages.settings;
|
|
189
|
+
return {
|
|
190
|
+
id: `setting-${name}`,
|
|
191
|
+
type: "list",
|
|
192
|
+
name,
|
|
193
|
+
label: s.options,
|
|
194
|
+
columns: 12,
|
|
195
|
+
children: [field("input", "label", s.optionLabel, { span: 6 }), field("input", "value", s.optionValue, { span: 6 })]
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
/** Settings of the built-in types, edited in a node's `props`. */
|
|
199
|
+
function builtinSettings(type, messages) {
|
|
200
|
+
const s = messages.settings;
|
|
201
|
+
const placeholder = text("placeholder", s.placeholder);
|
|
202
|
+
const clearable = sw("clearable", s.clearable);
|
|
203
|
+
const multiple = sw("multiple", s.multiple);
|
|
204
|
+
const filterable = sw("filterable", s.filterable);
|
|
205
|
+
const options = optionList(messages);
|
|
206
|
+
const direction = segmented(messages, "direction", ["horizontal", "vertical"], "horizontal");
|
|
207
|
+
switch (type) {
|
|
208
|
+
case "input": return [
|
|
209
|
+
placeholder,
|
|
210
|
+
clearable,
|
|
211
|
+
number("maxlength", s.maxlength, { min: 1 }),
|
|
212
|
+
sw("showCount", s.showCount)
|
|
213
|
+
];
|
|
214
|
+
case "textarea": return [
|
|
215
|
+
placeholder,
|
|
216
|
+
number("rows", s.rows, {
|
|
217
|
+
min: 1,
|
|
218
|
+
placeholder: "3"
|
|
219
|
+
}),
|
|
220
|
+
sw("autosize", s.autosize),
|
|
221
|
+
number("maxlength", s.maxlength, { min: 1 }),
|
|
222
|
+
sw("showCount", s.showCount)
|
|
223
|
+
];
|
|
224
|
+
case "input-number": return [
|
|
225
|
+
placeholder,
|
|
226
|
+
number("min", s.min, {}, { span: 6 }),
|
|
227
|
+
number("max", s.max, {}, { span: 6 }),
|
|
228
|
+
number("step", s.step, {
|
|
229
|
+
min: 0,
|
|
230
|
+
placeholder: "1"
|
|
231
|
+
}, { span: 6 }),
|
|
232
|
+
number("precision", s.precision, {
|
|
233
|
+
min: 0,
|
|
234
|
+
precision: 0
|
|
235
|
+
}, { span: 6 }),
|
|
236
|
+
sw("controls", s.controls, { default: true })
|
|
237
|
+
];
|
|
238
|
+
case "select": return [
|
|
239
|
+
options,
|
|
240
|
+
placeholder,
|
|
241
|
+
multiple,
|
|
242
|
+
filterable,
|
|
243
|
+
clearable
|
|
244
|
+
];
|
|
245
|
+
case "radio-group":
|
|
246
|
+
case "checkbox-group": return [options, direction];
|
|
247
|
+
case "segmented-control": return [options];
|
|
248
|
+
case "checkbox": return [text("text", s.text)];
|
|
249
|
+
case "slider": return [
|
|
250
|
+
number("min", s.min, {}, {
|
|
251
|
+
span: 6,
|
|
252
|
+
default: 0
|
|
253
|
+
}),
|
|
254
|
+
number("max", s.max, {}, {
|
|
255
|
+
span: 6,
|
|
256
|
+
default: 100
|
|
257
|
+
}),
|
|
258
|
+
number("step", s.step, { min: 0 }, { default: 1 }),
|
|
259
|
+
sw("range", s.range)
|
|
260
|
+
];
|
|
261
|
+
case "rate": return [number("max", s.count, {
|
|
262
|
+
min: 1,
|
|
263
|
+
max: 10,
|
|
264
|
+
precision: 0
|
|
265
|
+
}, { default: 5 }), sw("allowHalf", s.allowHalf)];
|
|
266
|
+
case "date-picker": return [
|
|
267
|
+
field("select", "type", s.dateType, {
|
|
268
|
+
default: "date",
|
|
269
|
+
props: { options: choices(messages, "dateType", [
|
|
270
|
+
"date",
|
|
271
|
+
"week",
|
|
272
|
+
"month",
|
|
273
|
+
"quarter",
|
|
274
|
+
"year",
|
|
275
|
+
"datetime"
|
|
276
|
+
]) }
|
|
277
|
+
}),
|
|
278
|
+
sw("range", s.range, { visibleWhen: "values.type != 'week'" }),
|
|
279
|
+
placeholder,
|
|
280
|
+
clearable
|
|
281
|
+
];
|
|
282
|
+
case "time-picker": return [
|
|
283
|
+
sw("range", s.range),
|
|
284
|
+
placeholder,
|
|
285
|
+
clearable
|
|
286
|
+
];
|
|
287
|
+
case "color-picker": return [sw("showAlpha", s.showAlpha), clearable];
|
|
288
|
+
case "cascader":
|
|
289
|
+
case "tree-select": return [
|
|
290
|
+
placeholder,
|
|
291
|
+
multiple,
|
|
292
|
+
filterable,
|
|
293
|
+
clearable
|
|
294
|
+
];
|
|
295
|
+
case "input-tag": return [
|
|
296
|
+
placeholder,
|
|
297
|
+
number("max", s.maxTags, {
|
|
298
|
+
min: 1,
|
|
299
|
+
precision: 0
|
|
300
|
+
}),
|
|
301
|
+
clearable
|
|
302
|
+
];
|
|
303
|
+
case "input-otp": return [number("length", s.length, {
|
|
304
|
+
min: 1,
|
|
305
|
+
max: 12,
|
|
306
|
+
precision: 0
|
|
307
|
+
}, { default: 6 }), sw("mask", s.mask)];
|
|
308
|
+
case "upload": return [
|
|
309
|
+
text("accept", s.accept, { props: { placeholder: "image/*, .pdf" } }),
|
|
310
|
+
multiple,
|
|
311
|
+
number("maxCount", s.maxCount, {
|
|
312
|
+
min: 1,
|
|
313
|
+
precision: 0
|
|
314
|
+
}),
|
|
315
|
+
sw("dropzone", s.dropzone)
|
|
316
|
+
];
|
|
317
|
+
case "text": return [field("textarea", "content", s.content, { props: { autosize: {
|
|
318
|
+
minRows: 2,
|
|
319
|
+
maxRows: 8
|
|
320
|
+
} } }), segmented(messages, "variant", [
|
|
321
|
+
"title",
|
|
322
|
+
"body",
|
|
323
|
+
"caption"
|
|
324
|
+
], "body")];
|
|
325
|
+
case "divider": return [text("text", s.content), sw("dashed", s.dashed)];
|
|
326
|
+
case "alert": return [
|
|
327
|
+
field("select", "tone", s.tone, {
|
|
328
|
+
default: "neutral",
|
|
329
|
+
props: { options: choices(messages, "tone", [
|
|
330
|
+
"neutral",
|
|
331
|
+
"primary",
|
|
332
|
+
"success",
|
|
333
|
+
"warning",
|
|
334
|
+
"danger"
|
|
335
|
+
]) }
|
|
336
|
+
}),
|
|
337
|
+
text("title", s.title),
|
|
338
|
+
field("textarea", "content", s.content, { props: { autosize: {
|
|
339
|
+
minRows: 2,
|
|
340
|
+
maxRows: 8
|
|
341
|
+
} } })
|
|
342
|
+
];
|
|
343
|
+
default: return [];
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
/** The builder's own type for a node's width: a number of columns, or one per breakpoint. */
|
|
347
|
+
var SPAN_TYPE = "dou-builder-span";
|
|
348
|
+
/** The builder's own type for expression text, with completions and problems. */
|
|
349
|
+
var EXPRESSION_TYPE = "dou-builder-expression";
|
|
350
|
+
/** The builder's own type for a condition, edited as rows or as text. */
|
|
351
|
+
var CONDITION_TYPE = "dou-builder-condition";
|
|
352
|
+
function spanSetting(context) {
|
|
353
|
+
const node = field(SPAN_TYPE, "span", "", {
|
|
354
|
+
default: context.columns,
|
|
355
|
+
props: { columns: context.columns }
|
|
356
|
+
});
|
|
357
|
+
delete node.label;
|
|
358
|
+
return node;
|
|
359
|
+
}
|
|
360
|
+
/** The settings of a node itself, besides its type's: name, label, width and so on. */
|
|
361
|
+
function nodeSettings(node, context) {
|
|
362
|
+
const s = context.messages.settings;
|
|
363
|
+
const span = spanSetting(context);
|
|
364
|
+
const name = text("name", context.inItem ? s.itemName : s.name, {
|
|
365
|
+
help: context.inItem ? s.itemNameHelp : s.nameHelp,
|
|
366
|
+
props: { clearable: false }
|
|
367
|
+
});
|
|
368
|
+
const columns = number("columns", s.columns, {
|
|
369
|
+
min: 1,
|
|
370
|
+
max: 24,
|
|
371
|
+
precision: 0,
|
|
372
|
+
placeholder: String(context.columns)
|
|
373
|
+
});
|
|
374
|
+
switch (node.type) {
|
|
375
|
+
case "section": return [
|
|
376
|
+
text("title", s.title),
|
|
377
|
+
field("textarea", "description", s.description, { props: { autosize: {
|
|
378
|
+
minRows: 1,
|
|
379
|
+
maxRows: 6
|
|
380
|
+
} } }),
|
|
381
|
+
sw("bordered", s.bordered),
|
|
382
|
+
columns,
|
|
383
|
+
span
|
|
384
|
+
];
|
|
385
|
+
case "page": return [
|
|
386
|
+
text("title", s.title),
|
|
387
|
+
field("textarea", "description", s.description, { props: { autosize: {
|
|
388
|
+
minRows: 1,
|
|
389
|
+
maxRows: 6
|
|
390
|
+
} } }),
|
|
391
|
+
columns
|
|
392
|
+
];
|
|
393
|
+
case "tabs":
|
|
394
|
+
case "steps": return [span];
|
|
395
|
+
case "list": return [
|
|
396
|
+
name,
|
|
397
|
+
text("label", s.label),
|
|
398
|
+
text("help", s.help),
|
|
399
|
+
span,
|
|
400
|
+
number("min", s.minItems, {
|
|
401
|
+
min: 0,
|
|
402
|
+
precision: 0
|
|
403
|
+
}, { span: 6 }),
|
|
404
|
+
number("max", s.maxItems, {
|
|
405
|
+
min: 1,
|
|
406
|
+
precision: 0
|
|
407
|
+
}, { span: 6 }),
|
|
408
|
+
text("addText", s.addText),
|
|
409
|
+
sw("sortable", s.sortable, { default: true }),
|
|
410
|
+
sw("required", s.required),
|
|
411
|
+
columns
|
|
412
|
+
];
|
|
413
|
+
default: {
|
|
414
|
+
const type = context.type;
|
|
415
|
+
if (type?.kind === "display") return [span];
|
|
416
|
+
const own = node;
|
|
417
|
+
const result = [
|
|
418
|
+
name,
|
|
419
|
+
text("label", s.label),
|
|
420
|
+
text("help", s.help),
|
|
421
|
+
span
|
|
422
|
+
];
|
|
423
|
+
if (type && own.type !== "upload") result.push({
|
|
424
|
+
id: "setting-default",
|
|
425
|
+
type: own.type,
|
|
426
|
+
name: "default",
|
|
427
|
+
label: s.default,
|
|
428
|
+
props: own.props
|
|
429
|
+
});
|
|
430
|
+
result.push(sw("required", s.required));
|
|
431
|
+
return result;
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
/** The settings of the document itself. */
|
|
436
|
+
function documentSettings(messages) {
|
|
437
|
+
const s = messages.settings;
|
|
438
|
+
const horizontal = "values.layout == 'horizontal'";
|
|
439
|
+
return [
|
|
440
|
+
segmented(messages, "layout", [
|
|
441
|
+
"vertical",
|
|
442
|
+
"horizontal",
|
|
443
|
+
"inline"
|
|
444
|
+
], "vertical"),
|
|
445
|
+
segmented(messages, "labelAlign", ["start", "end"], "start", { visibleWhen: horizontal }),
|
|
446
|
+
number("labelWidth", s.labelWidth, {
|
|
447
|
+
min: 40,
|
|
448
|
+
max: 400,
|
|
449
|
+
step: 8,
|
|
450
|
+
precision: 0
|
|
451
|
+
}, {
|
|
452
|
+
default: 96,
|
|
453
|
+
visibleWhen: horizontal
|
|
454
|
+
}),
|
|
455
|
+
segmented(messages, "size", [
|
|
456
|
+
"sm",
|
|
457
|
+
"md",
|
|
458
|
+
"lg"
|
|
459
|
+
], "md"),
|
|
460
|
+
field("radio-group", "requiredMark", s.requiredMark, {
|
|
461
|
+
default: true,
|
|
462
|
+
props: { options: choices(messages, "requiredMark", [
|
|
463
|
+
true,
|
|
464
|
+
"optional",
|
|
465
|
+
false
|
|
466
|
+
]) }
|
|
467
|
+
}),
|
|
468
|
+
number("columns", s.columns, {
|
|
469
|
+
min: 1,
|
|
470
|
+
max: 24,
|
|
471
|
+
precision: 0
|
|
472
|
+
}, { default: 12 })
|
|
473
|
+
];
|
|
474
|
+
}
|
|
475
|
+
/** A settings form: the nodes in a vertical, compact document. */
|
|
476
|
+
function settingsDocument(nodes) {
|
|
477
|
+
return {
|
|
478
|
+
version: 1,
|
|
479
|
+
size: "sm",
|
|
480
|
+
columns: 12,
|
|
481
|
+
requiredMark: false,
|
|
482
|
+
nodes
|
|
483
|
+
};
|
|
484
|
+
}
|
|
485
|
+
export { CONDITION_TYPE, EXPRESSION_TYPE, SPAN_TYPE, builtinSettings, choices, containerTypes, documentSettings, field, groupOf, iconOf, labelOf, nodeSettings, nodeTitle, number, paletteGroups, segmented, settingsDocument, text };
|
|
486
|
+
|
|
487
|
+
//# sourceMappingURL=settings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settings.js","names":[],"sources":["../../src/builder/settings.ts"],"sourcesContent":["import {\n CalendarIcon,\n CheckSquareIcon,\n ChevronDownSquareIcon,\n ClockIcon,\n HashIcon,\n InfoSquareIcon,\n LayoutIcon,\n LayoutListIcon,\n ListChecksIcon,\n ListTreeIcon,\n OtpIcon,\n PaletteIcon,\n RadioIcon,\n SegmentedControlIcon,\n SeparatorHorizontalIcon,\n SlidersIcon,\n SquareDashedIcon,\n StarIcon,\n StepsIcon,\n TabsIcon,\n TagsIcon,\n TextAlignLeftIcon,\n TextCursorIcon,\n ToggleRightIcon,\n TreeStructureIcon,\n TypeIcon,\n UploadIcon,\n} from '@dou-ui/icons'\nimport { markRaw } from 'vue'\nimport type { Component } from 'vue'\nimport type { FormDocument, FormFieldNode, FormListNode, FormNode } from '../core/types'\nimport type { FormFieldType } from '../fields/define'\nimport type { FormBuilderMessages } from './locale'\n\n/** The palette groups in the order they are listed; groups of other names follow. */\nexport const paletteGroups = ['input', 'choice', 'more', 'display', 'layout']\n\nconst raw = (icon: Component) => markRaw(icon)\n\n/** Icons and groups of the built-in types, kept out of the renderer's entry. */\nconst builtinLooks: Record<string, { icon: Component; group: string }> = {\n input: { icon: raw(TextCursorIcon), group: 'input' },\n textarea: { icon: raw(TextAlignLeftIcon), group: 'input' },\n 'input-number': { icon: raw(HashIcon), group: 'input' },\n 'input-tag': { icon: raw(TagsIcon), group: 'input' },\n 'input-otp': { icon: raw(OtpIcon), group: 'input' },\n select: { icon: raw(ChevronDownSquareIcon), group: 'choice' },\n 'radio-group': { icon: raw(RadioIcon), group: 'choice' },\n 'checkbox-group': { icon: raw(ListChecksIcon), group: 'choice' },\n checkbox: { icon: raw(CheckSquareIcon), group: 'choice' },\n switch: { icon: raw(ToggleRightIcon), group: 'choice' },\n 'segmented-control': { icon: raw(SegmentedControlIcon), group: 'choice' },\n cascader: { icon: raw(ListTreeIcon), group: 'choice' },\n 'tree-select': { icon: raw(TreeStructureIcon), group: 'choice' },\n slider: { icon: raw(SlidersIcon), group: 'more' },\n rate: { icon: raw(StarIcon), group: 'more' },\n 'date-picker': { icon: raw(CalendarIcon), group: 'more' },\n 'time-picker': { icon: raw(ClockIcon), group: 'more' },\n 'color-picker': { icon: raw(PaletteIcon), group: 'more' },\n upload: { icon: raw(UploadIcon), group: 'more' },\n text: { icon: raw(TypeIcon), group: 'display' },\n divider: { icon: raw(SeparatorHorizontalIcon), group: 'display' },\n alert: { icon: raw(InfoSquareIcon), group: 'display' },\n section: { icon: raw(SquareDashedIcon), group: 'layout' },\n tabs: { icon: raw(TabsIcon), group: 'layout' },\n steps: { icon: raw(StepsIcon), group: 'layout' },\n list: { icon: raw(LayoutListIcon), group: 'layout' },\n page: { icon: raw(LayoutIcon), group: 'layout' },\n}\n\n/** The containers the palette offers, after the field types. */\nexport const containerTypes = ['section', 'tabs', 'steps', 'list']\n\n/** A type's icon: its own, else the built-in one, else a plain box. */\nexport function iconOf(type: string, spec?: FormFieldType): Component {\n return spec?.icon ?? builtinLooks[type]?.icon ?? builtinLooks.section!.icon\n}\n\nexport function groupOf(type: string, spec?: FormFieldType): string {\n return spec?.group ?? builtinLooks[type]?.group ?? 'more'\n}\n\n/** A type's name for people: its own `label`, else the locale's. */\nexport function labelOf(\n type: string,\n spec: FormFieldType | undefined,\n messages: FormBuilderMessages,\n) {\n return spec?.label ?? messages.types[type] ?? type\n}\n\n/** What a node is called in the outline and the inspector's heading. */\nexport function nodeTitle(\n node: FormNode,\n fields: ReadonlyMap<string, FormFieldType>,\n messages: FormBuilderMessages,\n): string {\n const record = node as unknown as Record<string, unknown>\n const own = (record.label ?? record.title) as string | undefined\n if (own) return own\n if ('name' in node && node.name) return node.name\n return labelOf(node.type, fields.get(node.type), messages)\n}\n\n// Settings ----------------------------------------------------------------------\n\ntype Setting = Record<string, unknown>\n\nexport const field = (type: string, name: string, label: string, extra: Setting = {}): FormNode =>\n ({ id: `setting-${name}`, type, name, label, ...extra }) as FormFieldNode\n\nconst sw = (name: string, label: string, extra: Setting = {}) => field('switch', name, label, extra)\nexport const text = (name: string, label: string, extra: Setting = {}) =>\n field('input', name, label, { ...extra, props: { clearable: true, ...(extra.props as Setting) } })\nexport const number = (name: string, label: string, props: Setting = {}, extra: Setting = {}) =>\n field('input-number', name, label, { ...extra, props: { controls: false, ...props } })\n\nexport function choices(\n messages: FormBuilderMessages,\n key: string,\n values: readonly (string | boolean)[],\n): { value: string | boolean; label: string }[] {\n const labels = messages.choices[key] ?? {}\n return values.map((value) => ({ value, label: labels[String(value)] ?? String(value) }))\n}\n\nexport const segmented = (\n messages: FormBuilderMessages,\n name: string,\n values: readonly string[],\n fallback: string,\n extra: Setting = {},\n key = name,\n) =>\n field('segmented-control', name, messages.settings[key] ?? name, {\n default: fallback,\n props: { options: choices(messages, key, values), block: true },\n ...extra,\n })\n\nfunction optionList(messages: FormBuilderMessages, name = 'options'): FormListNode {\n const s = messages.settings\n return {\n id: `setting-${name}`,\n type: 'list',\n name,\n label: s.options,\n columns: 12,\n children: [\n field('input', 'label', s.optionLabel!, { span: 6 }),\n field('input', 'value', s.optionValue!, { span: 6 }),\n ],\n }\n}\n\n/** Settings of the built-in types, edited in a node's `props`. */\nexport function builtinSettings(type: string, messages: FormBuilderMessages): FormNode[] {\n const s = messages.settings as Record<string, string>\n const placeholder = text('placeholder', s.placeholder!)\n const clearable = sw('clearable', s.clearable!)\n const multiple = sw('multiple', s.multiple!)\n const filterable = sw('filterable', s.filterable!)\n const options = optionList(messages)\n const direction = segmented(messages, 'direction', ['horizontal', 'vertical'], 'horizontal')\n switch (type) {\n case 'input':\n return [\n placeholder,\n clearable,\n number('maxlength', s.maxlength!, { min: 1 }),\n sw('showCount', s.showCount!),\n ]\n case 'textarea':\n return [\n placeholder,\n number('rows', s.rows!, { min: 1, placeholder: '3' }),\n sw('autosize', s.autosize!),\n number('maxlength', s.maxlength!, { min: 1 }),\n sw('showCount', s.showCount!),\n ]\n case 'input-number':\n return [\n placeholder,\n number('min', s.min!, {}, { span: 6 }),\n number('max', s.max!, {}, { span: 6 }),\n number('step', s.step!, { min: 0, placeholder: '1' }, { span: 6 }),\n number('precision', s.precision!, { min: 0, precision: 0 }, { span: 6 }),\n sw('controls', s.controls!, { default: true }),\n ]\n case 'select':\n return [options, placeholder, multiple, filterable, clearable]\n case 'radio-group':\n case 'checkbox-group':\n return [options, direction]\n case 'segmented-control':\n return [options]\n case 'checkbox':\n return [text('text', s.text!)]\n case 'slider':\n return [\n number('min', s.min!, {}, { span: 6, default: 0 }),\n number('max', s.max!, {}, { span: 6, default: 100 }),\n number('step', s.step!, { min: 0 }, { default: 1 }),\n sw('range', s.range!),\n ]\n case 'rate':\n return [\n number('max', s.count!, { min: 1, max: 10, precision: 0 }, { default: 5 }),\n sw('allowHalf', s.allowHalf!),\n ]\n case 'date-picker':\n return [\n field('select', 'type', s.dateType!, {\n default: 'date',\n props: {\n options: choices(messages, 'dateType', [\n 'date',\n 'week',\n 'month',\n 'quarter',\n 'year',\n 'datetime',\n ]),\n },\n }),\n sw('range', s.range!, { visibleWhen: \"values.type != 'week'\" }),\n placeholder,\n clearable,\n ]\n case 'time-picker':\n return [sw('range', s.range!), placeholder, clearable]\n case 'color-picker':\n return [sw('showAlpha', s.showAlpha!), clearable]\n case 'cascader':\n case 'tree-select':\n return [placeholder, multiple, filterable, clearable]\n case 'input-tag':\n return [placeholder, number('max', s.maxTags!, { min: 1, precision: 0 }), clearable]\n case 'input-otp':\n return [\n number('length', s.length!, { min: 1, max: 12, precision: 0 }, { default: 6 }),\n sw('mask', s.mask!),\n ]\n case 'upload':\n return [\n text('accept', s.accept!, { props: { placeholder: 'image/*, .pdf' } }),\n multiple,\n number('maxCount', s.maxCount!, { min: 1, precision: 0 }),\n sw('dropzone', s.dropzone!),\n ]\n case 'text':\n return [\n field('textarea', 'content', s.content!, {\n props: { autosize: { minRows: 2, maxRows: 8 } },\n }),\n segmented(messages, 'variant', ['title', 'body', 'caption'], 'body'),\n ]\n case 'divider':\n return [text('text', s.content!), sw('dashed', s.dashed!)]\n case 'alert':\n return [\n field('select', 'tone', s.tone!, {\n default: 'neutral',\n props: {\n options: choices(messages, 'tone', [\n 'neutral',\n 'primary',\n 'success',\n 'warning',\n 'danger',\n ]),\n },\n }),\n text('title', s.title!),\n field('textarea', 'content', s.content!, {\n props: { autosize: { minRows: 2, maxRows: 8 } },\n }),\n ]\n default:\n return []\n }\n}\n\n/** What the node-level settings of a node depend on. */\nexport interface NodeSettingsContext {\n messages: FormBuilderMessages\n /** Columns of the grid the node sits on. */\n columns: number\n /** Whether the node sits in a list item, so its name is a key of the item. */\n inItem: boolean\n /** The node's type, for a field. */\n type?: FormFieldType\n}\n\n/** The builder's own type for a node's width: a number of columns, or one per breakpoint. */\nexport const SPAN_TYPE = 'dou-builder-span'\n/** The builder's own type for expression text, with completions and problems. */\nexport const EXPRESSION_TYPE = 'dou-builder-expression'\n/** The builder's own type for a condition, edited as rows or as text. */\nexport const CONDITION_TYPE = 'dou-builder-condition'\n\nfunction spanSetting(context: NodeSettingsContext): FormNode {\n // The field draws its own label, with the \"by form width\" switch on the same row.\n const node = field(SPAN_TYPE, 'span', '', {\n default: context.columns,\n props: { columns: context.columns },\n }) as FormFieldNode\n delete node.label\n return node\n}\n\n/** The settings of a node itself, besides its type's: name, label, width and so on. */\nexport function nodeSettings(node: FormNode, context: NodeSettingsContext): FormNode[] {\n const s = context.messages.settings as Record<string, string>\n const span = spanSetting(context)\n const name = text('name', context.inItem ? s.itemName! : s.name!, {\n help: context.inItem ? s.itemNameHelp : s.nameHelp,\n props: { clearable: false },\n })\n const columns = number('columns', s.columns!, {\n min: 1,\n max: 24,\n precision: 0,\n placeholder: String(context.columns),\n })\n switch (node.type) {\n case 'section':\n return [\n text('title', s.title!),\n field('textarea', 'description', s.description!, {\n props: { autosize: { minRows: 1, maxRows: 6 } },\n }),\n sw('bordered', s.bordered!),\n columns,\n span,\n ]\n case 'page':\n return [\n text('title', s.title!),\n field('textarea', 'description', s.description!, {\n props: { autosize: { minRows: 1, maxRows: 6 } },\n }),\n columns,\n ]\n case 'tabs':\n case 'steps':\n return [span]\n case 'list':\n return [\n name,\n text('label', s.label!),\n text('help', s.help!),\n span,\n number('min', s.minItems!, { min: 0, precision: 0 }, { span: 6 }),\n number('max', s.maxItems!, { min: 1, precision: 0 }, { span: 6 }),\n text('addText', s.addText!),\n sw('sortable', s.sortable!, { default: true }),\n sw('required', s.required!),\n columns,\n ]\n default: {\n const type = context.type\n if (type?.kind === 'display') return [span]\n const own = node as FormFieldNode\n const result: FormNode[] = [name, text('label', s.label!), text('help', s.help!), span]\n if (type && own.type !== 'upload')\n result.push({\n id: 'setting-default',\n type: own.type,\n name: 'default',\n label: s.default,\n props: own.props,\n } as FormFieldNode)\n result.push(sw('required', s.required!))\n return result\n }\n }\n}\n\n/** The settings of the document itself. */\nexport function documentSettings(messages: FormBuilderMessages): FormNode[] {\n const s = messages.settings as Record<string, string>\n const horizontal = \"values.layout == 'horizontal'\"\n return [\n segmented(messages, 'layout', ['vertical', 'horizontal', 'inline'], 'vertical'),\n segmented(messages, 'labelAlign', ['start', 'end'], 'start', { visibleWhen: horizontal }),\n number(\n 'labelWidth',\n s.labelWidth!,\n { min: 40, max: 400, step: 8, precision: 0 },\n { default: 96, visibleWhen: horizontal },\n ),\n segmented(messages, 'size', ['sm', 'md', 'lg'], 'md'),\n field('radio-group', 'requiredMark', s.requiredMark!, {\n default: true,\n props: { options: choices(messages, 'requiredMark', [true, 'optional', false]) },\n }),\n number('columns', s.columns!, { min: 1, max: 24, precision: 0 }, { default: 12 }),\n ]\n}\n\n/** A settings form: the nodes in a vertical, compact document. */\nexport function settingsDocument(nodes: FormNode[]): FormDocument {\n return { version: 1, size: 'sm', columns: 12, requiredMark: false, nodes }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { defineFormField } from "../fields/define.js";
|
|
2
|
+
import { SPAN_TYPE } from "./settings.js";
|
|
3
|
+
import { useBuilderState } from "./context.js";
|
|
4
|
+
import { DouCheckbox, DouInputNumber } from "dou-ui";
|
|
5
|
+
import { computed, defineComponent, h, useId } from "vue";
|
|
6
|
+
// src/builder/span-field.ts
|
|
7
|
+
var breakpoints = [
|
|
8
|
+
"base",
|
|
9
|
+
"sm",
|
|
10
|
+
"md",
|
|
11
|
+
"lg",
|
|
12
|
+
"xl"
|
|
13
|
+
];
|
|
14
|
+
/**
|
|
15
|
+
* A node's width in columns: one number, or one per form width when
|
|
16
|
+
* "by form width" is on. A width left empty takes the next narrower one.
|
|
17
|
+
*/
|
|
18
|
+
var SpanInput = defineComponent({
|
|
19
|
+
name: "DouFormBuilderSpan",
|
|
20
|
+
props: {
|
|
21
|
+
modelValue: {
|
|
22
|
+
type: [Number, Object],
|
|
23
|
+
default: void 0
|
|
24
|
+
},
|
|
25
|
+
columns: {
|
|
26
|
+
type: Number,
|
|
27
|
+
default: 12
|
|
28
|
+
},
|
|
29
|
+
disabled: Boolean
|
|
30
|
+
},
|
|
31
|
+
emits: { "update:modelValue": (_value) => true },
|
|
32
|
+
setup(props, { emit }) {
|
|
33
|
+
const state = useBuilderState();
|
|
34
|
+
const labelId = `dou-form-builder-span-${useId()}`;
|
|
35
|
+
const responsive = computed(() => typeof props.modelValue === "object" && props.modelValue !== null);
|
|
36
|
+
const whole = computed(() => {
|
|
37
|
+
const value = props.modelValue;
|
|
38
|
+
if (typeof value === "number") return value;
|
|
39
|
+
if (value && typeof value === "object") return value.base ?? props.columns;
|
|
40
|
+
return props.columns;
|
|
41
|
+
});
|
|
42
|
+
const clamp = (value) => Math.min(Math.max(1, Math.round(value)), props.columns);
|
|
43
|
+
function setOne(value) {
|
|
44
|
+
emit("update:modelValue", value === null ? props.columns : clamp(value));
|
|
45
|
+
}
|
|
46
|
+
function setAt(key, value) {
|
|
47
|
+
const current = { ...props.modelValue };
|
|
48
|
+
if (value === null) delete current[key];
|
|
49
|
+
else current[key] = clamp(value);
|
|
50
|
+
emit("update:modelValue", current);
|
|
51
|
+
}
|
|
52
|
+
function toggle(on) {
|
|
53
|
+
emit("update:modelValue", on ? { base: whole.value } : whole.value);
|
|
54
|
+
}
|
|
55
|
+
return () => {
|
|
56
|
+
const messages = state.messages;
|
|
57
|
+
const choices = messages.choices.breakpoint ?? {};
|
|
58
|
+
const input = (value, set, label, placeholder) => h(DouInputNumber, {
|
|
59
|
+
modelValue: value ?? null,
|
|
60
|
+
min: 1,
|
|
61
|
+
max: props.columns,
|
|
62
|
+
precision: 0,
|
|
63
|
+
size: "sm",
|
|
64
|
+
controls: false,
|
|
65
|
+
disabled: props.disabled,
|
|
66
|
+
placeholder,
|
|
67
|
+
"aria-label": label,
|
|
68
|
+
"onUpdate:modelValue": set
|
|
69
|
+
});
|
|
70
|
+
const rows = responsive.value ? breakpoints.map((key, index) => {
|
|
71
|
+
const value = props.modelValue[key];
|
|
72
|
+
let inherited;
|
|
73
|
+
for (let at = index - 1; at >= 0 && inherited === void 0; at--) inherited = props.modelValue[breakpoints[at]];
|
|
74
|
+
return h("label", {
|
|
75
|
+
key,
|
|
76
|
+
class: "dou-form-builder__span-row"
|
|
77
|
+
}, [h("span", { class: "dou-form-builder__span-label" }, choices[key] ?? key), input(value, (next) => setAt(key, next), choices[key] ?? key, String(inherited ?? props.columns))]);
|
|
78
|
+
}) : [h("div", { class: "dou-form-builder__span-row" }, [input(whole.value, setOne, messages.settings.span ?? "span"), h("span", { class: "dou-form-builder__span-label" }, `/ ${props.columns}`)])];
|
|
79
|
+
return h("div", {
|
|
80
|
+
class: "dou-form-builder__span",
|
|
81
|
+
role: "group",
|
|
82
|
+
"aria-labelledby": labelId
|
|
83
|
+
}, [h("div", { class: "dou-form-builder__span-head" }, [h("div", {
|
|
84
|
+
id: labelId,
|
|
85
|
+
class: "dou-form-item__label"
|
|
86
|
+
}, h("span", { class: "dou-form-item__label-text" }, messages.settings.span)), h(DouCheckbox, {
|
|
87
|
+
modelValue: responsive.value,
|
|
88
|
+
disabled: props.disabled,
|
|
89
|
+
size: "sm",
|
|
90
|
+
class: "dou-form-builder__span-toggle",
|
|
91
|
+
"onUpdate:modelValue": (on) => toggle(on === true)
|
|
92
|
+
}, () => messages.settings.spanResponsive)]), ...rows]);
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
/** The width setting of the inspector, a field type of the builder's own. */
|
|
97
|
+
var spanField = defineFormField({
|
|
98
|
+
type: SPAN_TYPE,
|
|
99
|
+
component: SpanInput,
|
|
100
|
+
empty: (props) => props.columns ?? 12
|
|
101
|
+
});
|
|
102
|
+
export { spanField };
|
|
103
|
+
|
|
104
|
+
//# sourceMappingURL=span-field.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"span-field.js","names":[],"sources":["../../src/builder/span-field.ts"],"sourcesContent":["import { computed, defineComponent, h, useId } from 'vue'\nimport type { PropType } from 'vue'\nimport { DouCheckbox, DouInputNumber } from 'dou-ui'\nimport type { FormResponsive } from '../core/types'\nimport { defineFormField } from '../fields/define'\nimport { useBuilderState } from './context'\nimport { SPAN_TYPE } from './settings'\n\nconst breakpoints = ['base', 'sm', 'md', 'lg', 'xl'] as const\ntype Breakpoint = (typeof breakpoints)[number]\ntype Span = FormResponsive<number>\n\n/**\n * A node's width in columns: one number, or one per form width when\n * \"by form width\" is on. A width left empty takes the next narrower one.\n */\nconst SpanInput = defineComponent({\n name: 'DouFormBuilderSpan',\n props: {\n modelValue: { type: [Number, Object] as PropType<Span | null>, default: undefined },\n columns: { type: Number, default: 12 },\n disabled: Boolean,\n },\n emits: { 'update:modelValue': (_value: Span) => true },\n setup(props, { emit }) {\n const state = useBuilderState()\n const labelId = `dou-form-builder-span-${useId()}`\n const responsive = computed(\n () => typeof props.modelValue === 'object' && props.modelValue !== null,\n )\n const whole = computed(() => {\n const value = props.modelValue\n if (typeof value === 'number') return value\n if (value && typeof value === 'object') return value.base ?? props.columns\n return props.columns\n })\n const clamp = (value: number) => Math.min(Math.max(1, Math.round(value)), props.columns)\n\n function setOne(value: number | null) {\n emit('update:modelValue', value === null ? props.columns : clamp(value))\n }\n function setAt(key: Breakpoint, value: number | null) {\n const current = { ...(props.modelValue as Partial<Record<Breakpoint, number>>) }\n if (value === null) delete current[key]\n else current[key] = clamp(value)\n emit('update:modelValue', current)\n }\n function toggle(on: boolean) {\n emit('update:modelValue', on ? { base: whole.value } : whole.value)\n }\n\n return () => {\n const messages = state.messages\n const choices = messages.choices.breakpoint ?? {}\n const input = (\n value: number | null | undefined,\n set: (value: number | null) => void,\n label: string,\n placeholder?: string,\n ) =>\n h(DouInputNumber, {\n modelValue: value ?? null,\n min: 1,\n max: props.columns,\n precision: 0,\n size: 'sm',\n controls: false,\n disabled: props.disabled,\n placeholder,\n 'aria-label': label,\n 'onUpdate:modelValue': set,\n })\n const rows = responsive.value\n ? breakpoints.map((key, index) => {\n const value = (props.modelValue as Partial<Record<Breakpoint, number>>)[key]\n // An empty width shows the one it takes over from.\n let inherited: number | undefined\n for (let at = index - 1; at >= 0 && inherited === undefined; at--)\n inherited = (props.modelValue as Partial<Record<Breakpoint, number>>)[\n breakpoints[at]!\n ]\n return h('label', { key, class: 'dou-form-builder__span-row' }, [\n h('span', { class: 'dou-form-builder__span-label' }, choices[key] ?? key),\n input(\n value,\n (next) => setAt(key, next),\n choices[key] ?? key,\n String(inherited ?? props.columns),\n ),\n ])\n })\n : [\n h('div', { class: 'dou-form-builder__span-row' }, [\n input(whole.value, setOne, messages.settings.span ?? 'span'),\n h('span', { class: 'dou-form-builder__span-label' }, `/ ${props.columns}`),\n ]),\n ]\n return h(\n 'div',\n { class: 'dou-form-builder__span', role: 'group', 'aria-labelledby': labelId },\n [\n h('div', { class: 'dou-form-builder__span-head' }, [\n h(\n 'div',\n { id: labelId, class: 'dou-form-item__label' },\n h('span', { class: 'dou-form-item__label-text' }, messages.settings.span),\n ),\n h(\n DouCheckbox,\n {\n modelValue: responsive.value,\n disabled: props.disabled,\n size: 'sm',\n class: 'dou-form-builder__span-toggle',\n 'onUpdate:modelValue': (on: unknown) => toggle(on === true),\n },\n () => messages.settings.spanResponsive,\n ),\n ]),\n ...rows,\n ],\n )\n }\n },\n})\n\n/** The width setting of the inspector, a field type of the builder's own. */\nexport const spanField = defineFormField({\n type: SPAN_TYPE,\n component: SpanInput,\n empty: (props: { columns?: number }) => props.columns ?? 12,\n})\n"],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import expression_input_vue_vue_type_script_setup_true_lang_default from "./expression-input.vue_vue_type_script_setup_true_lang.js";
|
|
2
|
+
// src/code/expression-input.vue
|
|
3
|
+
var expression_input_default = expression_input_vue_vue_type_script_setup_true_lang_default;
|
|
4
|
+
export { expression_input_default as default };
|
|
5
|
+
|
|
6
|
+
//# sourceMappingURL=expression-input.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"expression-input.js","names":["_sfc_main"],"sources":["../../src/code/expression-input.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { DouCodeInput } from '@dou-ui/code'\nimport { computed, useId } from 'vue'\nimport { builtinFunctions, checkExpression } from '../core/expression'\nimport { formatMessage } from '../locale'\nimport { useBuilderState } from '../builder/context'\nimport { expressionCodeExtension } from './extension'\nimport type { ExpressionName } from './extension'\nimport { formExpression } from './language'\n\n/**\n * The builder's expression box as a code input: colored, with completions\n * of field paths and functions, parameter hints, and problems underlined\n * as well as written under it.\n */\ndefineOptions({ name: 'DouFormBuilderCodeExpression', inheritAttrs: false })\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string | null\n names?: ExpressionName[]\n itemNames?: ExpressionName[]\n readsValue?: boolean\n placeholder?: string\n disabled?: boolean\n /** Shown and selectable, but not changed; also when the form around is read-only. */\n readonly?: boolean\n }>(),\n { modelValue: '', names: () => [], itemNames: undefined, placeholder: undefined },\n)\nconst emit = defineEmits<{ 'update:modelValue': [value: string] }>()\n\nconst state = useBuilderState()\nconst errorId = `dou-form-builder-expression-${useId()}`\nconst words = computed(() => state.messages.expression)\n\nconst problemMessage = (problem: { code: string; message: string; text: string }) =>\n formatMessage(words.value.problems[problem.code] ?? problem.message, { text: problem.text })\n\nconst extensions = [\n expressionCodeExtension({\n names: () => props.names,\n itemNames: () => props.itemNames,\n readsValue: () => !!props.readsValue,\n functions: () => state.functionNames.value,\n functionInfo: () => words.value.functions,\n labels: () => words.value,\n problemMessage,\n }),\n]\n\nconst text = computed(() => props.modelValue ?? '')\n\n// The first problem in words too, for screen readers and at a glance.\nconst problem = computed(() => {\n if (!text.value.trim()) return undefined\n const found = checkExpression(text.value, {\n fields: props.names.map((name) => name.path),\n itemFields: props.itemNames ? props.itemNames.map((name) => name.path) : [],\n functions: [...new Set([...Object.keys(builtinFunctions), ...state.functionNames.value])],\n })[0]\n return found && problemMessage(found)\n})\n</script>\n\n<template>\n <div class=\"dou-form-builder__expression\">\n <DouCodeInput\n v-bind=\"$attrs\"\n :model-value=\"text\"\n :language=\"formExpression\"\n :extensions=\"extensions\"\n :placeholder=\"placeholder\"\n :disabled=\"disabled\"\n :readonly=\"readonly\"\n :invalid=\"!!problem\"\n :aria-describedby=\"problem ? errorId : undefined\"\n multiline\n :autosize=\"{ maxRows: 4 }\"\n size=\"sm\"\n class=\"dou-form-builder__expression-input\"\n @update:model-value=\"emit('update:modelValue', $event)\"\n />\n <div v-if=\"problem\" :id=\"errorId\" class=\"dou-form-builder__expression-error\">\n {{ problem }}\n </div>\n </div>\n</template>\n"],"mappings":""}
|