@webx-ui/schema 0.5.0 → 0.6.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/dist/ScreenTabs.d.ts +23 -0
- package/dist/index.js +285 -227
- package/dist/index.js.map +1 -1
- package/dist/render.d.ts +7 -2
- package/package.json +2 -2
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
type __VLS_Props = {
|
|
2
|
+
/** The names of the fields under each tab, in the order the tabs are read. */
|
|
3
|
+
fields?: Record<string, string[]>;
|
|
4
|
+
};
|
|
5
|
+
declare function __VLS_template(): {
|
|
6
|
+
attrs: Partial<{}>;
|
|
7
|
+
slots: {
|
|
8
|
+
default?(_: {}): any;
|
|
9
|
+
};
|
|
10
|
+
refs: {};
|
|
11
|
+
rootEl: any;
|
|
12
|
+
};
|
|
13
|
+
type __VLS_TemplateResult = ReturnType<typeof __VLS_template>;
|
|
14
|
+
declare const __VLS_component: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
|
|
15
|
+
fields: Record<string, string[]>;
|
|
16
|
+
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
17
|
+
declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, __VLS_TemplateResult["slots"]>;
|
|
18
|
+
export default _default;
|
|
19
|
+
type __VLS_WithTemplateSlots<T, S> = T & {
|
|
20
|
+
new (): {
|
|
21
|
+
$slots: S;
|
|
22
|
+
};
|
|
23
|
+
};
|
package/dist/index.js
CHANGED
|
@@ -1,106 +1,106 @@
|
|
|
1
|
-
import { WxFormItem as
|
|
2
|
-
import { defineComponent as
|
|
3
|
-
function
|
|
1
|
+
import { WxFormItem as G, WxRepeater as J, WxTabs as Y, WxAlert as Q, WxText as Z, WxHeading as ee, WxCodeEditor as ne, WxTransfer as te, WxTreeSelect as oe, WxCascader as ie, WxIconPicker as re, WxAutocomplete as se, WxTagsInput as ae, WxDateRangePicker as de, WxDateTimePicker as le, WxTimePicker as ce, WxRate as fe, WxSlider as ue, WxSegmented as pe, WxCheckboxGroup as me, WxColorPicker as ye, WxDatePicker as be, WxRadioGroup as xe, WxCheckbox as he, WxSwitch as ge, WxSelect as ke, WxInputNumber as we, WxTextarea as We, WxInput as $e, WxDivider as Se, WxCol as ve, WxRow as Ae, WxCard as je, WxTab as Pe, WxForm as Te } from "@webx-ui/core";
|
|
2
|
+
import { defineComponent as k, h as m, useModel as z, computed as f, useAttrs as Oe, openBlock as P, createBlock as T, unref as b, mergeProps as M, withCtx as O, createVNode as I, mergeModels as S, inject as Re, ref as Ee, watch as D, renderSlot as Ne, provide as Ve, markRaw as Ce, toRaw as ze } from "vue";
|
|
3
|
+
function g(e, t) {
|
|
4
4
|
for (let n = 0; n < e.length; n += 1) {
|
|
5
|
-
const
|
|
6
|
-
if (
|
|
7
|
-
if (
|
|
8
|
-
const
|
|
9
|
-
if (
|
|
5
|
+
const o = e[n];
|
|
6
|
+
if (o.id === t) return { list: e, index: n, node: o };
|
|
7
|
+
if (o.children) {
|
|
8
|
+
const i = g(o.children, t);
|
|
9
|
+
if (i) return i;
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
12
|
return null;
|
|
13
13
|
}
|
|
14
|
-
function
|
|
15
|
-
return
|
|
14
|
+
function en(e, t) {
|
|
15
|
+
return g(e, t)?.node ?? null;
|
|
16
16
|
}
|
|
17
|
-
function
|
|
18
|
-
const t = [], n = (
|
|
19
|
-
for (const
|
|
20
|
-
t.push(
|
|
17
|
+
function W(e) {
|
|
18
|
+
const t = [], n = (o) => {
|
|
19
|
+
for (const i of o)
|
|
20
|
+
t.push(i.id), i.children && n(i.children);
|
|
21
21
|
};
|
|
22
22
|
return n(e), t;
|
|
23
23
|
}
|
|
24
|
-
function
|
|
24
|
+
function E(e, t) {
|
|
25
25
|
if (!t || t === "last") return e.length;
|
|
26
26
|
if (t === "first") return 0;
|
|
27
|
-
const [n,
|
|
28
|
-
return
|
|
27
|
+
const [n, o] = t.split(":", 2), i = e.findIndex((r) => r.id === o);
|
|
28
|
+
return i === -1 ? `no sibling "${o}" to insert ${n}` : n === "before" ? i : i + 1;
|
|
29
29
|
}
|
|
30
|
-
function
|
|
31
|
-
if (Array.isArray(e)) return e.map(
|
|
30
|
+
function y(e) {
|
|
31
|
+
if (Array.isArray(e)) return e.map(y);
|
|
32
32
|
if (e && typeof e == "object") {
|
|
33
33
|
const t = {};
|
|
34
|
-
for (const [n,
|
|
34
|
+
for (const [n, o] of Object.entries(e)) t[n] = y(o);
|
|
35
35
|
return t;
|
|
36
36
|
}
|
|
37
37
|
return e;
|
|
38
38
|
}
|
|
39
|
-
function
|
|
40
|
-
const n =
|
|
41
|
-
return t.forEach((
|
|
42
|
-
const s =
|
|
43
|
-
s &&
|
|
44
|
-
}), { root: n, errors:
|
|
39
|
+
function Me(e, t) {
|
|
40
|
+
const n = y(e), o = [];
|
|
41
|
+
return t.forEach((i, r) => {
|
|
42
|
+
const s = Ie(n, i);
|
|
43
|
+
s && o.push({ index: r, op: i, message: s });
|
|
44
|
+
}), { root: n, errors: o };
|
|
45
45
|
}
|
|
46
|
-
function
|
|
47
|
-
const n =
|
|
46
|
+
function Ie(e, t) {
|
|
47
|
+
const n = g(e, t.target);
|
|
48
48
|
if (!n) return `target "${t.target}" not found`;
|
|
49
49
|
switch (t.op) {
|
|
50
50
|
case "add": {
|
|
51
|
-
const
|
|
52
|
-
if (
|
|
53
|
-
const
|
|
54
|
-
return typeof r == "string" ? r : (
|
|
51
|
+
const o = N(e, t.node);
|
|
52
|
+
if (o) return `id "${o}" already exists in the screen`;
|
|
53
|
+
const i = n.node.children ??= [], r = E(i, t.position);
|
|
54
|
+
return typeof r == "string" ? r : (i.splice(r, 0, y(t.node)), null);
|
|
55
55
|
}
|
|
56
56
|
case "remove":
|
|
57
57
|
return n.list.splice(n.index, 1), null;
|
|
58
58
|
case "replace": {
|
|
59
|
-
const
|
|
60
|
-
return
|
|
59
|
+
const o = e.filter((r) => r !== n.node), i = N(o, t.node, n.node);
|
|
60
|
+
return i ? `id "${i}" already exists in the screen` : (n.list.splice(n.index, 1, y(t.node)), null);
|
|
61
61
|
}
|
|
62
62
|
case "move": {
|
|
63
|
-
let
|
|
63
|
+
let o = n.list;
|
|
64
64
|
if (t.to !== void 0) {
|
|
65
|
-
const r =
|
|
65
|
+
const r = g(e, t.to);
|
|
66
66
|
if (!r) return `destination "${t.to}" not found`;
|
|
67
|
-
if (r.node === n.node ||
|
|
67
|
+
if (r.node === n.node || _(n.node, r.node))
|
|
68
68
|
return `cannot move "${t.target}" into itself`;
|
|
69
|
-
|
|
69
|
+
o = r.node.children ??= [];
|
|
70
70
|
}
|
|
71
71
|
n.list.splice(n.index, 1);
|
|
72
|
-
const
|
|
73
|
-
return typeof
|
|
72
|
+
const i = E(o, t.position);
|
|
73
|
+
return typeof i == "string" ? (n.list.splice(n.index, 0, n.node), i) : (o.splice(i, 0, n.node), null);
|
|
74
74
|
}
|
|
75
75
|
case "set": {
|
|
76
|
-
for (const [
|
|
77
|
-
|
|
76
|
+
for (const [o, i] of Object.entries(t))
|
|
77
|
+
o === "op" || o === "target" || (o === "props" ? n.node.props = { ...n.node.props, ...i } : n.node[o] = y(i));
|
|
78
78
|
return null;
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
|
-
function
|
|
83
|
-
return (e.children ?? []).some((n) => n === t ||
|
|
82
|
+
function _(e, t) {
|
|
83
|
+
return (e.children ?? []).some((n) => n === t || _(n, t));
|
|
84
84
|
}
|
|
85
|
-
function
|
|
86
|
-
const
|
|
87
|
-
if (n) for (const
|
|
88
|
-
return
|
|
85
|
+
function N(e, t, n) {
|
|
86
|
+
const o = new Set(W(e));
|
|
87
|
+
if (n) for (const i of W([n])) o.delete(i);
|
|
88
|
+
return W([t]).find((i) => o.has(i)) ?? null;
|
|
89
89
|
}
|
|
90
|
-
function
|
|
90
|
+
function $(e, t) {
|
|
91
91
|
return e === t ? !0 : e === null || t === null || typeof e != "object" || typeof t != "object" ? !1 : JSON.stringify(e) === JSON.stringify(t);
|
|
92
92
|
}
|
|
93
|
-
function
|
|
94
|
-
if ("all" in e) return e.all.every((
|
|
95
|
-
if ("any" in e) return e.any.some((
|
|
93
|
+
function v(e, t) {
|
|
94
|
+
if ("all" in e) return e.all.every((o) => v(o, t));
|
|
95
|
+
if ("any" in e) return e.any.some((o) => v(o, t));
|
|
96
96
|
const n = t[e.when];
|
|
97
|
-
return "in" in e ? e.in.some((
|
|
97
|
+
return "in" in e ? e.in.some((o) => $(o, n)) : "not" in e ? !$(e.not, n) : $(e.is, n);
|
|
98
98
|
}
|
|
99
|
-
function
|
|
99
|
+
function De(e, t) {
|
|
100
100
|
const { visible: n } = e;
|
|
101
|
-
return n === void 0 || n === !0 ? !0 : n === !1 ? !1 :
|
|
101
|
+
return n === void 0 || n === !0 ? !0 : n === !1 ? !1 : v(n, t);
|
|
102
102
|
}
|
|
103
|
-
const
|
|
103
|
+
const F = /* @__PURE__ */ new Set([
|
|
104
104
|
"id",
|
|
105
105
|
"type",
|
|
106
106
|
"name",
|
|
@@ -112,154 +112,160 @@ const V = /* @__PURE__ */ new Set([
|
|
|
112
112
|
"slot",
|
|
113
113
|
"visible",
|
|
114
114
|
"can"
|
|
115
|
-
]),
|
|
116
|
-
function
|
|
115
|
+
]), _e = /* @__PURE__ */ new Set(["add", "remove", "replace", "move", "set"]);
|
|
116
|
+
function x(e) {
|
|
117
117
|
return typeof e == "object" && e !== null && !Array.isArray(e);
|
|
118
118
|
}
|
|
119
|
-
function
|
|
120
|
-
if (!
|
|
119
|
+
function q(e, t, n) {
|
|
120
|
+
if (!x(e)) {
|
|
121
121
|
n.push({ path: t, message: "visible must be a boolean or a condition object" });
|
|
122
122
|
return;
|
|
123
123
|
}
|
|
124
124
|
if ("all" in e || "any" in e) {
|
|
125
|
-
const
|
|
126
|
-
if (!Array.isArray(
|
|
125
|
+
const i = e.all ?? e.any;
|
|
126
|
+
if (!Array.isArray(i)) {
|
|
127
127
|
n.push({ path: t, message: '"all" / "any" must be an array of conditions' });
|
|
128
128
|
return;
|
|
129
129
|
}
|
|
130
|
-
|
|
130
|
+
i.forEach((r, s) => q(r, `${t}[${s}]`, n));
|
|
131
131
|
return;
|
|
132
132
|
}
|
|
133
133
|
if (typeof e.when != "string") {
|
|
134
134
|
n.push({ path: t, message: 'a condition needs "when": the name of a field' });
|
|
135
135
|
return;
|
|
136
136
|
}
|
|
137
|
-
const
|
|
138
|
-
|
|
137
|
+
const o = ["is", "in", "not"].filter((i) => i in e);
|
|
138
|
+
o.length !== 1 ? n.push({ path: t, message: 'a condition needs exactly one of "is", "in", "not"' }) : o[0] === "in" && !Array.isArray(e.in) && n.push({ path: t, message: '"in" must be an array' });
|
|
139
139
|
}
|
|
140
|
-
function
|
|
141
|
-
if (!
|
|
140
|
+
function R(e, t, n, o) {
|
|
141
|
+
if (!x(e)) {
|
|
142
142
|
n.push({ path: t, message: "a node must be an object" });
|
|
143
143
|
return;
|
|
144
144
|
}
|
|
145
|
-
for (const
|
|
146
|
-
|
|
147
|
-
typeof e.id != "string" || e.id === "" ? n.push({ path: t, message: '"id" is required and must be a non-empty string' }) :
|
|
148
|
-
for (const
|
|
149
|
-
|
|
150
|
-
"localized" in e && typeof e.localized != "boolean" && n.push({ path: t, message: '"localized" must be a boolean' }), "props" in e && !
|
|
151
|
-
(
|
|
145
|
+
for (const i of Object.keys(e))
|
|
146
|
+
F.has(i) || n.push({ path: t, message: `unknown key "${i}"` });
|
|
147
|
+
typeof e.id != "string" || e.id === "" ? n.push({ path: t, message: '"id" is required and must be a non-empty string' }) : o.has(e.id) ? n.push({ path: t, message: `duplicate id "${e.id}"` }) : o.add(e.id), (typeof e.type != "string" || e.type === "") && n.push({ path: t, message: '"type" is required and must be a non-empty string' });
|
|
148
|
+
for (const i of ["name", "label", "help"])
|
|
149
|
+
i in e && typeof e[i] != "string" && n.push({ path: t, message: `"${i}" must be a string` });
|
|
150
|
+
"localized" in e && typeof e.localized != "boolean" && n.push({ path: t, message: '"localized" must be a boolean' }), "props" in e && !x(e.props) && n.push({ path: t, message: '"props" must be an object' }), "slot" in e && e.slot !== null && typeof e.slot != "string" && n.push({ path: t, message: '"slot" must be a string or null' }), "can" in e && e.can !== null && typeof e.can != "string" && n.push({ path: t, message: '"can" must be a string or null' }), "visible" in e && typeof e.visible != "boolean" && q(e.visible, `${t}.visible`, n), "children" in e && (Array.isArray(e.children) ? e.children.forEach(
|
|
151
|
+
(i, r) => R(i, `${t}.children[${r}]`, n, o)
|
|
152
152
|
) : n.push({ path: t, message: '"children" must be an array' }));
|
|
153
153
|
}
|
|
154
|
-
function
|
|
154
|
+
function nn(e) {
|
|
155
155
|
const t = [];
|
|
156
156
|
if (!Array.isArray(e)) return [{ path: "root", message: "root must be an array of nodes" }];
|
|
157
157
|
const n = /* @__PURE__ */ new Set();
|
|
158
|
-
return e.forEach((
|
|
158
|
+
return e.forEach((o, i) => R(o, `root[${i}]`, t, n)), t;
|
|
159
159
|
}
|
|
160
|
-
function
|
|
160
|
+
function tn(e) {
|
|
161
161
|
const t = [];
|
|
162
|
-
return Array.isArray(e) ? (e.forEach((n,
|
|
163
|
-
const
|
|
164
|
-
if (!
|
|
165
|
-
t.push({ path:
|
|
162
|
+
return Array.isArray(e) ? (e.forEach((n, o) => {
|
|
163
|
+
const i = `patch[${o}]`;
|
|
164
|
+
if (!x(n)) {
|
|
165
|
+
t.push({ path: i, message: "an operation must be an object" });
|
|
166
166
|
return;
|
|
167
167
|
}
|
|
168
|
-
if (typeof n.op != "string" || !
|
|
169
|
-
t.push({ path:
|
|
168
|
+
if (typeof n.op != "string" || !_e.has(n.op)) {
|
|
169
|
+
t.push({ path: i, message: '"op" must be one of add, remove, replace, move, set' });
|
|
170
170
|
return;
|
|
171
171
|
}
|
|
172
|
-
if ((typeof n.target != "string" || n.target === "") && t.push({ path:
|
|
172
|
+
if ((typeof n.target != "string" || n.target === "") && t.push({ path: i, message: '"target" is required: the id of a node' }), (n.op === "add" || n.op === "replace") && !x(n.node) ? t.push({ path: i, message: `"${n.op}" needs a "node"` }) : (n.op === "add" || n.op === "replace") && R(n.node, `${i}.node`, t, /* @__PURE__ */ new Set()), "position" in n && !Fe(n.position) && t.push({ path: i, message: '"position" must be first, last, before:<id> or after:<id>' }), n.op === "move" && "to" in n && typeof n.to != "string" && t.push({ path: i, message: '"to" must be the id of the new parent' }), n.op === "set")
|
|
173
173
|
for (const r of Object.keys(n))
|
|
174
|
-
r !== "op" && r !== "target" && (!
|
|
174
|
+
r !== "op" && r !== "target" && (!F.has(r) || r === "id") && t.push({ path: i, message: `"set" cannot change "${r}"` });
|
|
175
175
|
}), t) : [{ path: "patch", message: "a patch must be an array" }];
|
|
176
176
|
}
|
|
177
|
-
function
|
|
177
|
+
function Fe(e) {
|
|
178
178
|
return typeof e == "string" && (e === "first" || e === "last" || e.startsWith("before:") || e.startsWith("after:"));
|
|
179
179
|
}
|
|
180
|
-
const
|
|
181
|
-
function
|
|
182
|
-
return
|
|
180
|
+
const V = "trans::", U = /* @__PURE__ */ Symbol("wx-screen-errors");
|
|
181
|
+
function C(e, t) {
|
|
182
|
+
return e.can && !t.can(e.can) ? !1 : De(e, t.model);
|
|
183
183
|
}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
184
|
+
const qe = (e) => e;
|
|
185
|
+
function A(e, t) {
|
|
186
|
+
return typeof e == "string" && e.startsWith(V) ? t(e.slice(V.length)) : e;
|
|
187
|
+
}
|
|
188
|
+
function j(e, t) {
|
|
189
|
+
if (typeof e == "string") return A(e, t);
|
|
190
|
+
if (Array.isArray(e)) return e.map((n) => j(n, t));
|
|
187
191
|
if (e && typeof e == "object") {
|
|
188
192
|
const n = {};
|
|
189
|
-
for (const [
|
|
193
|
+
for (const [o, i] of Object.entries(e)) n[o] = j(i, t);
|
|
190
194
|
return n;
|
|
191
195
|
}
|
|
192
196
|
return e;
|
|
193
197
|
}
|
|
194
|
-
function
|
|
195
|
-
return
|
|
198
|
+
function Ue(e) {
|
|
199
|
+
return m(
|
|
196
200
|
"div",
|
|
197
201
|
{ key: e.id, class: "wx-screen__unknown", role: "note" },
|
|
198
202
|
`Unknown type: ${e.type}`
|
|
199
203
|
);
|
|
200
204
|
}
|
|
201
|
-
function
|
|
202
|
-
const
|
|
205
|
+
function Be(e, t, n) {
|
|
206
|
+
const o = /* @__PURE__ */ new Map();
|
|
203
207
|
for (const r of e.children ?? []) {
|
|
204
|
-
const s = r.slot ?? t, a =
|
|
205
|
-
a.push(r),
|
|
208
|
+
const s = r.slot ?? t, a = o.get(s) ?? [];
|
|
209
|
+
a.push(r), o.set(s, a);
|
|
206
210
|
}
|
|
207
|
-
const
|
|
208
|
-
for (const [r, s] of
|
|
209
|
-
|
|
210
|
-
return
|
|
211
|
+
const i = {};
|
|
212
|
+
for (const [r, s] of o)
|
|
213
|
+
i[r] = () => B(s, n);
|
|
214
|
+
return i;
|
|
211
215
|
}
|
|
212
|
-
function
|
|
213
|
-
if (
|
|
216
|
+
function Ke(e, t) {
|
|
217
|
+
if (!C(e, t)) return null;
|
|
214
218
|
const n = t.types[e.type];
|
|
215
|
-
if (!n) return
|
|
216
|
-
|
|
219
|
+
if (!n) return Ue(e);
|
|
220
|
+
if (n.kind === "layout" && e.children !== void 0 && !e.children.some((s) => C(s, t)))
|
|
221
|
+
return null;
|
|
222
|
+
const { translate: o } = t, i = {
|
|
217
223
|
key: e.id,
|
|
218
|
-
|
|
224
|
+
...j(e.props ?? {}, o),
|
|
219
225
|
...n.bind?.(e)
|
|
220
|
-
}, r =
|
|
226
|
+
}, r = A(e.label, o);
|
|
221
227
|
if (n.kind === "field") {
|
|
222
|
-
const s = e.name, a =
|
|
223
|
-
...
|
|
228
|
+
const s = e.name, a = m(n.component, {
|
|
229
|
+
...i,
|
|
224
230
|
/* A nested field draws the children itself, so it needs the node and the way down. */
|
|
225
231
|
...n.nested ? { node: e, context: t } : {},
|
|
226
232
|
name: s,
|
|
227
233
|
localized: e.localized || void 0,
|
|
228
234
|
modelValue: s === void 0 ? void 0 : t.model[s],
|
|
229
|
-
"onUpdate:modelValue": (
|
|
230
|
-
s !== void 0 && t.update(s,
|
|
235
|
+
"onUpdate:modelValue": (c) => {
|
|
236
|
+
s !== void 0 && t.update(s, c);
|
|
231
237
|
}
|
|
232
238
|
});
|
|
233
|
-
return
|
|
234
|
-
|
|
235
|
-
{ key: e.id, name: s, label: r, help:
|
|
239
|
+
return m(
|
|
240
|
+
G,
|
|
241
|
+
{ key: e.id, name: s, label: r, help: A(e.help, o), wide: n.wide },
|
|
236
242
|
() => a
|
|
237
243
|
);
|
|
238
244
|
}
|
|
239
|
-
return n.kind === "layout" ? (n.labelProp && r !== void 0 && (
|
|
245
|
+
return n.kind === "layout" ? (n.labelProp && r !== void 0 && (i[n.labelProp] = r), m(n.component, i, Be(e, n.childrenSlot ?? "default", t))) : n.labelProp ? (r !== void 0 && (i[n.labelProp] = r), m(n.component, i)) : m(n.component, i, r === void 0 ? void 0 : () => r);
|
|
240
246
|
}
|
|
241
|
-
function
|
|
247
|
+
function B(e, t) {
|
|
242
248
|
const n = [];
|
|
243
|
-
for (const
|
|
244
|
-
const
|
|
245
|
-
|
|
249
|
+
for (const o of e) {
|
|
250
|
+
const i = Ke(o, t);
|
|
251
|
+
i && n.push(i);
|
|
246
252
|
}
|
|
247
253
|
return n;
|
|
248
254
|
}
|
|
249
|
-
const
|
|
255
|
+
const K = k({
|
|
250
256
|
name: "WxScreenNodes",
|
|
251
257
|
props: {
|
|
252
258
|
nodes: { type: Array, required: !0 },
|
|
253
259
|
context: { type: Object, required: !0 }
|
|
254
260
|
},
|
|
255
261
|
setup(e) {
|
|
256
|
-
return () =>
|
|
262
|
+
return () => B(e.nodes, e.context);
|
|
257
263
|
}
|
|
258
|
-
}),
|
|
264
|
+
}), He = /* @__PURE__ */ k({
|
|
259
265
|
name: "WxScreenRepeater",
|
|
260
266
|
inheritAttrs: !1,
|
|
261
267
|
__name: "ScreenRepeater",
|
|
262
|
-
props: /* @__PURE__ */
|
|
268
|
+
props: /* @__PURE__ */ S({
|
|
263
269
|
node: {},
|
|
264
270
|
context: {},
|
|
265
271
|
name: {},
|
|
@@ -270,133 +276,171 @@ const v = A({
|
|
|
270
276
|
}),
|
|
271
277
|
emits: ["update:modelValue"],
|
|
272
278
|
setup(e) {
|
|
273
|
-
const t = e, n =
|
|
279
|
+
const t = e, n = z(e, "modelValue"), o = f(() => Array.isArray(n.value) ? n.value : []), i = Oe();
|
|
274
280
|
function r(a) {
|
|
275
|
-
const
|
|
276
|
-
return
|
|
281
|
+
const c = t.context.translate(`webx-admin::screens.repeater.${a}`);
|
|
282
|
+
return c.includes("::") ? void 0 : c;
|
|
277
283
|
}
|
|
278
|
-
const s =
|
|
284
|
+
const s = f(() => {
|
|
279
285
|
const a = { collapsed: !0 };
|
|
280
|
-
for (const [
|
|
286
|
+
for (const [c, u] of [
|
|
281
287
|
["addLabel", "add"],
|
|
282
288
|
["removeLabel", "remove"],
|
|
283
289
|
["dragLabel", "reorder"],
|
|
284
290
|
["emptyText", "empty"]
|
|
285
291
|
]) {
|
|
286
|
-
const
|
|
287
|
-
|
|
292
|
+
const p = r(u);
|
|
293
|
+
p !== void 0 && (a[c] = p);
|
|
288
294
|
}
|
|
289
|
-
return { ...a, ...
|
|
295
|
+
return { ...a, ...i };
|
|
290
296
|
});
|
|
291
|
-
return (a,
|
|
292
|
-
"model-value":
|
|
293
|
-
"onUpdate:modelValue":
|
|
297
|
+
return (a, c) => (P(), T(b(J), M(s.value, {
|
|
298
|
+
"model-value": o.value,
|
|
299
|
+
"onUpdate:modelValue": c[0] || (c[0] = (u) => n.value = u)
|
|
294
300
|
}), {
|
|
295
|
-
default:
|
|
296
|
-
|
|
301
|
+
default: O(({ item: u, update: p }) => [
|
|
302
|
+
I(b(K), {
|
|
297
303
|
nodes: e.node.children ?? [],
|
|
298
304
|
context: {
|
|
299
305
|
...e.context,
|
|
300
|
-
model:
|
|
301
|
-
update: (
|
|
306
|
+
model: u,
|
|
307
|
+
update: (l, d) => p({ [l]: d })
|
|
302
308
|
}
|
|
303
309
|
}, null, 8, ["nodes", "context"])
|
|
304
310
|
]),
|
|
305
311
|
_: 1
|
|
306
312
|
}, 16, ["model-value"]));
|
|
307
313
|
}
|
|
308
|
-
}),
|
|
309
|
-
|
|
314
|
+
}), Le = /* @__PURE__ */ k({
|
|
315
|
+
name: "WxScreenTabs",
|
|
316
|
+
inheritAttrs: !1,
|
|
317
|
+
__name: "ScreenTabs",
|
|
318
|
+
props: {
|
|
319
|
+
fields: { default: () => ({}) }
|
|
320
|
+
},
|
|
321
|
+
setup(e) {
|
|
322
|
+
const t = e, n = Re(U, null), o = Ee(void 0), i = f(() => {
|
|
323
|
+
const r = new Set(Object.keys(n?.value ?? {}));
|
|
324
|
+
return Object.entries(t.fields).filter(([, s]) => s.some((a) => r.has(a))).map(([s]) => s);
|
|
325
|
+
});
|
|
326
|
+
return D(i, (r) => {
|
|
327
|
+
const s = r[0];
|
|
328
|
+
s !== void 0 && (o.value !== void 0 && r.includes(String(o.value)) || (o.value = s));
|
|
329
|
+
}), (r, s) => (P(), T(b(Y), M({
|
|
330
|
+
modelValue: o.value,
|
|
331
|
+
"onUpdate:modelValue": s[0] || (s[0] = (a) => o.value = a)
|
|
332
|
+
}, r.$attrs), {
|
|
333
|
+
default: O(() => [
|
|
334
|
+
Ne(r.$slots, "default")
|
|
335
|
+
]),
|
|
336
|
+
_: 3
|
|
337
|
+
}, 16, ["modelValue"]));
|
|
338
|
+
}
|
|
339
|
+
});
|
|
340
|
+
function H(e) {
|
|
341
|
+
return (e.children ?? []).flatMap(
|
|
342
|
+
(t) => t.name === void 0 ? H(t) : [t.name]
|
|
343
|
+
);
|
|
344
|
+
}
|
|
345
|
+
const Xe = {
|
|
346
|
+
"wx-tabs": {
|
|
347
|
+
component: Le,
|
|
348
|
+
kind: "layout",
|
|
349
|
+
// Which fields each tab holds, so a refused save can open the tab it was refused on.
|
|
350
|
+
bind: (e) => ({
|
|
351
|
+
fields: Object.fromEntries((e.children ?? []).map((t) => [t.id, H(t)]))
|
|
352
|
+
})
|
|
353
|
+
},
|
|
310
354
|
"wx-tab": {
|
|
311
|
-
component:
|
|
355
|
+
component: Pe,
|
|
312
356
|
kind: "layout",
|
|
313
357
|
labelProp: "label",
|
|
314
358
|
// A tab is selected by value, and the node's id is the one stable thing it has.
|
|
315
359
|
bind: (e) => ({ value: e.id })
|
|
316
360
|
},
|
|
317
|
-
"wx-card": { component:
|
|
318
|
-
"wx-row": { component:
|
|
361
|
+
"wx-card": { component: je, kind: "layout", labelProp: "title" },
|
|
362
|
+
"wx-row": { component: Ae, kind: "layout" },
|
|
319
363
|
"wx-col": {
|
|
320
|
-
component:
|
|
364
|
+
component: ve,
|
|
321
365
|
kind: "layout",
|
|
322
366
|
// Marked so the renderer can stack what a column holds (see `ScreenRenderer.vue`),
|
|
323
367
|
// without touching a `WxCol` that some field happens to use inside itself.
|
|
324
368
|
bind: (e) => ({ class: ["wx-screen__col", e.props?.class] })
|
|
325
369
|
},
|
|
326
|
-
"wx-divider": { component:
|
|
327
|
-
"wx-input": { component:
|
|
328
|
-
"wx-textarea": { component:
|
|
329
|
-
"wx-input-number": { component:
|
|
330
|
-
"wx-select": { component:
|
|
331
|
-
"wx-switch": { component:
|
|
332
|
-
"wx-checkbox": { component:
|
|
333
|
-
"wx-radio-group": { component:
|
|
334
|
-
"wx-date-picker": { component:
|
|
335
|
-
"wx-color-picker": { component:
|
|
336
|
-
"wx-checkbox-group": { component:
|
|
337
|
-
"wx-segmented": { component:
|
|
338
|
-
"wx-slider": { component:
|
|
339
|
-
"wx-rate": { component:
|
|
340
|
-
"wx-time-picker": { component:
|
|
370
|
+
"wx-divider": { component: Se, kind: "layout", labelProp: "label" },
|
|
371
|
+
"wx-input": { component: $e, kind: "field" },
|
|
372
|
+
"wx-textarea": { component: We, kind: "field" },
|
|
373
|
+
"wx-input-number": { component: we, kind: "field" },
|
|
374
|
+
"wx-select": { component: ke, kind: "field" },
|
|
375
|
+
"wx-switch": { component: ge, kind: "field" },
|
|
376
|
+
"wx-checkbox": { component: he, kind: "field" },
|
|
377
|
+
"wx-radio-group": { component: xe, kind: "field" },
|
|
378
|
+
"wx-date-picker": { component: be, kind: "field" },
|
|
379
|
+
"wx-color-picker": { component: ye, kind: "field" },
|
|
380
|
+
"wx-checkbox-group": { component: me, kind: "field" },
|
|
381
|
+
"wx-segmented": { component: pe, kind: "field" },
|
|
382
|
+
"wx-slider": { component: ue, kind: "field" },
|
|
383
|
+
"wx-rate": { component: fe, kind: "field" },
|
|
384
|
+
"wx-time-picker": { component: ce, kind: "field" },
|
|
341
385
|
"wx-date-time-picker": {
|
|
342
|
-
component:
|
|
386
|
+
component: le,
|
|
343
387
|
kind: "field",
|
|
344
388
|
// A moment, not a wall clock. Without the offset the server reads the hour in its own
|
|
345
389
|
// timezone and the browser in the reader's, and one value shows two different times. Bound
|
|
346
390
|
// over `props` on purpose: the server parses exactly this shape.
|
|
347
391
|
bind: () => ({ valueFormat: "yyyy-MM-dd'T'HH:mm:ssXXX" })
|
|
348
392
|
},
|
|
349
|
-
"wx-date-range-picker": { component:
|
|
350
|
-
"wx-tags-input": { component:
|
|
351
|
-
"wx-autocomplete": { component:
|
|
352
|
-
"wx-icon-picker": { component:
|
|
353
|
-
"wx-cascader": { component:
|
|
354
|
-
"wx-tree-select": { component:
|
|
393
|
+
"wx-date-range-picker": { component: de, kind: "field" },
|
|
394
|
+
"wx-tags-input": { component: ae, kind: "field" },
|
|
395
|
+
"wx-autocomplete": { component: se, kind: "field" },
|
|
396
|
+
"wx-icon-picker": { component: re, kind: "field" },
|
|
397
|
+
"wx-cascader": { component: ie, kind: "field" },
|
|
398
|
+
"wx-tree-select": { component: oe, kind: "field" },
|
|
355
399
|
// Wide: two lists with the buttons between them do not fit in half a form.
|
|
356
|
-
"wx-transfer": { component:
|
|
400
|
+
"wx-transfer": { component: te, kind: "field", wide: !0 },
|
|
357
401
|
// Wide for the reason an editor is: code is read in long lines.
|
|
358
|
-
"wx-code-editor": { component:
|
|
359
|
-
"wx-repeater": { component:
|
|
360
|
-
"wx-heading": { component:
|
|
361
|
-
"wx-text": { component:
|
|
362
|
-
"wx-alert": { component:
|
|
402
|
+
"wx-code-editor": { component: ne, kind: "field", wide: !0 },
|
|
403
|
+
"wx-repeater": { component: He, kind: "field", nested: !0, wide: !0 },
|
|
404
|
+
"wx-heading": { component: ee, kind: "display" },
|
|
405
|
+
"wx-text": { component: Z, kind: "display" },
|
|
406
|
+
"wx-alert": { component: Q, kind: "display", labelProp: "title" }
|
|
363
407
|
};
|
|
364
|
-
function
|
|
408
|
+
function on(e) {
|
|
365
409
|
return e;
|
|
366
410
|
}
|
|
367
|
-
function
|
|
411
|
+
function Ge(e) {
|
|
368
412
|
const t = e.component;
|
|
369
413
|
return t.name ?? t.__name ?? "anonymous";
|
|
370
414
|
}
|
|
371
|
-
function
|
|
415
|
+
function Je(e) {
|
|
372
416
|
return e.kind === "field" ? "form item" : e.labelProp ? `prop \`${e.labelProp}\`` : e.kind === "display" ? "default slot" : "—";
|
|
373
417
|
}
|
|
374
|
-
function
|
|
418
|
+
function Ye(e) {
|
|
375
419
|
return Object.entries(e).map(([t, n]) => ({
|
|
376
420
|
type: t,
|
|
377
421
|
kind: n.kind,
|
|
378
|
-
component:
|
|
379
|
-
label:
|
|
422
|
+
component: Ge(n),
|
|
423
|
+
label: Je(n)
|
|
380
424
|
}));
|
|
381
425
|
}
|
|
382
|
-
function
|
|
383
|
-
const t =
|
|
426
|
+
function rn(e) {
|
|
427
|
+
const t = Ye(e).map((r) => [
|
|
384
428
|
`\`${r.type}\``,
|
|
385
429
|
r.kind,
|
|
386
430
|
`\`${r.component}\``,
|
|
387
431
|
r.label
|
|
388
|
-
]), n = ["Type", "Kind", "Component", "`label` goes to"],
|
|
432
|
+
]), n = ["Type", "Kind", "Component", "`label` goes to"], o = n.map(
|
|
389
433
|
(r, s) => Math.max(r.length, ...t.map((a) => a[s].length))
|
|
390
|
-
),
|
|
391
|
-
return [
|
|
434
|
+
), i = (r) => `| ${r.map((s, a) => s.padEnd(o[a])).join(" | ")} |`;
|
|
435
|
+
return [i(n), i(o.map((r) => "-".repeat(r))), ...t.map(i)].join(
|
|
392
436
|
`
|
|
393
437
|
`
|
|
394
438
|
);
|
|
395
439
|
}
|
|
396
|
-
const
|
|
440
|
+
const sn = /* @__PURE__ */ k({
|
|
397
441
|
name: "WxScreenRenderer",
|
|
398
442
|
__name: "ScreenRenderer",
|
|
399
|
-
props: /* @__PURE__ */
|
|
443
|
+
props: /* @__PURE__ */ S({
|
|
400
444
|
root: {},
|
|
401
445
|
patch: { default: () => [] },
|
|
402
446
|
errors: { default: void 0 },
|
|
@@ -411,47 +455,61 @@ const Xe = /* @__PURE__ */ A({
|
|
|
411
455
|
modelValue: { default: () => ({}) },
|
|
412
456
|
modelModifiers: {}
|
|
413
457
|
}),
|
|
414
|
-
emits: /* @__PURE__ */
|
|
458
|
+
emits: /* @__PURE__ */ S(["patchError"], ["update:modelValue"]),
|
|
415
459
|
setup(e, { expose: t, emit: n }) {
|
|
416
|
-
const
|
|
417
|
-
|
|
460
|
+
const o = e, i = n, r = z(e, "modelValue"), s = f(() => Me(o.root, o.patch));
|
|
461
|
+
function a(l) {
|
|
462
|
+
return l.flatMap(
|
|
463
|
+
(d) => d.name === void 0 ? a(d.children ?? []) : [d.name]
|
|
464
|
+
);
|
|
465
|
+
}
|
|
466
|
+
const c = f(() => {
|
|
467
|
+
if (o.errors === void 0) return;
|
|
468
|
+
const l = a(s.value.root), d = { ...o.errors };
|
|
469
|
+
for (const [h, L] of Object.entries(o.errors)) {
|
|
470
|
+
const w = l.find((X) => h.startsWith(`${X}.`));
|
|
471
|
+
w !== void 0 && d[w] === void 0 && (d[w] = L);
|
|
472
|
+
}
|
|
473
|
+
return d;
|
|
474
|
+
});
|
|
475
|
+
Ve(U, c), D(
|
|
418
476
|
() => s.value.errors,
|
|
419
|
-
(
|
|
420
|
-
for (const
|
|
421
|
-
console.error(`[webx-ui/schema] patch[${
|
|
422
|
-
|
|
477
|
+
(l) => {
|
|
478
|
+
for (const d of l)
|
|
479
|
+
console.error(`[webx-ui/schema] patch[${d.index}] ${d.op.op}: ${d.message}`);
|
|
480
|
+
i("patchError", l);
|
|
423
481
|
},
|
|
424
482
|
{ immediate: !0 }
|
|
425
483
|
);
|
|
426
|
-
const
|
|
427
|
-
const
|
|
428
|
-
for (const [
|
|
429
|
-
d
|
|
430
|
-
return
|
|
431
|
-
}),
|
|
432
|
-
types:
|
|
484
|
+
const u = f(() => {
|
|
485
|
+
const l = {};
|
|
486
|
+
for (const [d, h] of Object.entries({ ...Xe, ...o.types }))
|
|
487
|
+
l[d] = { ...h, component: Ce(ze(h.component)) };
|
|
488
|
+
return l;
|
|
489
|
+
}), p = f(() => ({
|
|
490
|
+
types: u.value,
|
|
433
491
|
model: r.value,
|
|
434
|
-
update: (
|
|
435
|
-
r.value = { ...r.value, [
|
|
492
|
+
update: (l, d) => {
|
|
493
|
+
r.value = { ...r.value, [l]: d };
|
|
436
494
|
},
|
|
437
|
-
translate:
|
|
438
|
-
can:
|
|
495
|
+
translate: o.translate ?? qe,
|
|
496
|
+
can: o.can ?? (() => !0)
|
|
439
497
|
}));
|
|
440
498
|
return t({
|
|
441
499
|
/** The tree after the patch — what is actually on screen. */
|
|
442
|
-
tree:
|
|
443
|
-
}), (
|
|
500
|
+
tree: f(() => s.value.root)
|
|
501
|
+
}), (l, d) => (P(), T(b(Te), {
|
|
444
502
|
class: "wx-screen",
|
|
445
|
-
errors:
|
|
503
|
+
errors: c.value,
|
|
446
504
|
disabled: e.disabled,
|
|
447
505
|
"label-position": e.labelPosition,
|
|
448
506
|
"label-width": e.labelWidth,
|
|
449
507
|
size: e.size
|
|
450
508
|
}, {
|
|
451
|
-
default:
|
|
452
|
-
|
|
509
|
+
default: O(() => [
|
|
510
|
+
I(b(K), {
|
|
453
511
|
nodes: s.value.root,
|
|
454
|
-
context:
|
|
512
|
+
context: p.value
|
|
455
513
|
}, null, 8, ["nodes", "context"])
|
|
456
514
|
]),
|
|
457
515
|
_: 1
|
|
@@ -459,21 +517,21 @@ const Xe = /* @__PURE__ */ A({
|
|
|
459
517
|
}
|
|
460
518
|
});
|
|
461
519
|
export {
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
520
|
+
V as TRANS_MARKER,
|
|
521
|
+
K as WxScreenNodes,
|
|
522
|
+
sn as WxScreenRenderer,
|
|
523
|
+
Me as applyPatch,
|
|
524
|
+
W as collectIds,
|
|
525
|
+
Xe as coreTypes,
|
|
526
|
+
on as defineTypes,
|
|
527
|
+
Ye as describeTypes,
|
|
528
|
+
v as evaluateCondition,
|
|
529
|
+
en as findNode,
|
|
530
|
+
De as isVisible,
|
|
531
|
+
j as translateDeep,
|
|
532
|
+
rn as typesTable,
|
|
533
|
+
tn as validatePatch,
|
|
534
|
+
nn as validateScreen,
|
|
535
|
+
A as words
|
|
478
536
|
};
|
|
479
537
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/patch.ts","../src/visible.ts","../src/validate.ts","../src/render.ts","../src/ScreenRepeater.vue","../src/registry.ts","../src/ScreenRenderer.vue"],"sourcesContent":["import type { Patch, PatchError, PatchOperation, PatchPosition, ScreenNode } from './types'\n\ninterface Located {\n /** The array the node sits in: the root, or a parent's `children`. */\n list: ScreenNode[]\n index: number\n node: ScreenNode\n}\n\n/** Depth-first search by `id`, remembering the array the match lives in. */\nexport function locate(root: ScreenNode[], id: string): Located | null {\n for (let index = 0; index < root.length; index += 1) {\n const node = root[index]!\n if (node.id === id) return { list: root, index, node }\n if (node.children) {\n const found = locate(node.children, id)\n if (found) return found\n }\n }\n return null\n}\n\nexport function findNode(root: ScreenNode[], id: string): ScreenNode | null {\n return locate(root, id)?.node ?? null\n}\n\n/** Every `id` in the tree, in document order. Duplicates are kept, so callers can spot them. */\nexport function collectIds(root: ScreenNode[]): string[] {\n const ids: string[] = []\n const walk = (nodes: ScreenNode[]) => {\n for (const node of nodes) {\n ids.push(node.id)\n if (node.children) walk(node.children)\n }\n }\n walk(root)\n return ids\n}\n\n/** Index a node should be inserted at in `list`, or a message when the anchor is missing. */\nfunction indexFor(list: ScreenNode[], position: PatchPosition | undefined): number | string {\n if (!position || position === 'last') return list.length\n if (position === 'first') return 0\n const [where, anchor] = position.split(':', 2) as ['before' | 'after', string]\n const at = list.findIndex((node) => node.id === anchor)\n if (at === -1) return `no sibling \"${anchor}\" to insert ${where}`\n return where === 'before' ? at : at + 1\n}\n\n/**\n * Deep copy of a JSON value. `structuredClone` refuses a Vue reactive proxy, and a\n * tree that came out of a `ref` is exactly that; reading through the proxy is fine.\n */\nexport function clone<T>(value: T): T {\n if (Array.isArray(value)) return value.map(clone) as T\n if (value && typeof value === 'object') {\n const out: Record<string, unknown> = {}\n for (const [key, item] of Object.entries(value)) out[key] = clone(item)\n return out as T\n }\n return value\n}\n\n/**\n * Applies a patch to a tree and returns the result as a new tree; the input is not\n * touched. An operation that cannot be applied — a `target` that does not exist, an\n * anchor that is missing — is skipped and reported, and the ones after it still run:\n * a project patch that survived a rename in the module must not silence the rest.\n */\nexport function applyPatch(\n root: ScreenNode[],\n patch: Patch,\n): { root: ScreenNode[]; errors: PatchError[] } {\n const tree = clone(root)\n const errors: PatchError[] = []\n\n patch.forEach((op, index) => {\n const message = apply(tree, op)\n if (message) errors.push({ index, op, message })\n })\n\n return { root: tree, errors }\n}\n\n/** Mutates `tree`; returns a message when the operation was refused. */\nfunction apply(tree: ScreenNode[], op: PatchOperation): string | null {\n const found = locate(tree, op.target)\n if (!found) return `target \"${op.target}\" not found`\n\n switch (op.op) {\n case 'add': {\n const clash = duplicateIn(tree, op.node)\n if (clash) return `id \"${clash}\" already exists in the screen`\n const list = (found.node.children ??= [])\n const at = indexFor(list, op.position)\n if (typeof at === 'string') return at\n list.splice(at, 0, clone(op.node))\n return null\n }\n case 'remove':\n found.list.splice(found.index, 1)\n return null\n case 'replace': {\n // The replaced node's own ids are gone, so only the rest of the tree can clash.\n const others = tree.filter((node) => node !== found.node)\n const clash = duplicateIn(others, op.node, found.node)\n if (clash) return `id \"${clash}\" already exists in the screen`\n found.list.splice(found.index, 1, clone(op.node))\n return null\n }\n case 'move': {\n let list = found.list\n if (op.to !== undefined) {\n const parent = locate(tree, op.to)\n if (!parent) return `destination \"${op.to}\" not found`\n if (parent.node === found.node || contains(found.node, parent.node)) {\n return `cannot move \"${op.target}\" into itself`\n }\n list = parent.node.children ??= []\n }\n found.list.splice(found.index, 1)\n const at = indexFor(list, op.position)\n if (typeof at === 'string') {\n // Put it back where it was: a refused move leaves the tree untouched.\n found.list.splice(found.index, 0, found.node)\n return at\n }\n list.splice(at, 0, found.node)\n return null\n }\n case 'set': {\n for (const [key, value] of Object.entries(op)) {\n if (key === 'op' || key === 'target') continue\n if (key === 'props') {\n found.node.props = { ...found.node.props, ...(value as Record<string, unknown>) }\n } else {\n ;(found.node as unknown as Record<string, unknown>)[key] = clone(value)\n }\n }\n return null\n }\n }\n}\n\nfunction contains(ancestor: ScreenNode, node: ScreenNode): boolean {\n return (ancestor.children ?? []).some((child) => child === node || contains(child, node))\n}\n\n/** First id of `incoming` that already exists in `tree`, ignoring `except`'s own subtree. */\nfunction duplicateIn(tree: ScreenNode[], incoming: ScreenNode, except?: ScreenNode): string | null {\n const existing = new Set(collectIds(tree))\n if (except) for (const id of collectIds([except])) existing.delete(id)\n return collectIds([incoming]).find((id) => existing.has(id)) ?? null\n}\n","import type { ScreenModel, ScreenNode, VisibilityCondition } from './types'\n\n/** Loose enough for `{ \"is\": 1 }` to match a numeric input, strict enough for `\"1\"` not to. */\nfunction same(a: unknown, b: unknown): boolean {\n if (a === b) return true\n if (a === null || b === null || typeof a !== 'object' || typeof b !== 'object') return false\n return JSON.stringify(a) === JSON.stringify(b)\n}\n\nexport function evaluateCondition(condition: VisibilityCondition, model: ScreenModel): boolean {\n if ('all' in condition) return condition.all.every((item) => evaluateCondition(item, model))\n if ('any' in condition) return condition.any.some((item) => evaluateCondition(item, model))\n\n const value = model[condition.when]\n if ('in' in condition) return condition.in.some((item) => same(item, value))\n if ('not' in condition) return !same(condition.not, value)\n return same(condition.is, value)\n}\n\n/** Whether a node should render, given the current model. Absent `visible` means yes. */\nexport function isVisible(node: ScreenNode, model: ScreenModel): boolean {\n const { visible } = node\n if (visible === undefined || visible === true) return true\n if (visible === false) return false\n return evaluateCondition(visible, model)\n}\n","import type { Patch, ScreenError, ScreenNode, VisibilityCondition } from './types'\n\nconst NODE_KEYS = new Set([\n 'id',\n 'type',\n 'name',\n 'label',\n 'help',\n 'localized',\n 'props',\n 'children',\n 'slot',\n 'visible',\n 'can',\n])\n\nconst OPS = new Set(['add', 'remove', 'replace', 'move', 'set'])\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nfunction checkCondition(value: unknown, path: string, errors: ScreenError[]): void {\n if (!isRecord(value)) {\n errors.push({ path, message: 'visible must be a boolean or a condition object' })\n return\n }\n if ('all' in value || 'any' in value) {\n const list = (value.all ?? value.any) as unknown\n if (!Array.isArray(list)) {\n errors.push({ path, message: '\"all\" / \"any\" must be an array of conditions' })\n return\n }\n list.forEach((item, index) => checkCondition(item, `${path}[${index}]`, errors))\n return\n }\n if (typeof value.when !== 'string') {\n errors.push({ path, message: 'a condition needs \"when\": the name of a field' })\n return\n }\n const forms = ['is', 'in', 'not'].filter((key) => key in value)\n if (forms.length !== 1) {\n errors.push({ path, message: 'a condition needs exactly one of \"is\", \"in\", \"not\"' })\n } else if (forms[0] === 'in' && !Array.isArray(value.in)) {\n errors.push({ path, message: '\"in\" must be an array' })\n }\n}\n\nfunction checkNode(value: unknown, path: string, errors: ScreenError[], seen: Set<string>): void {\n if (!isRecord(value)) {\n errors.push({ path, message: 'a node must be an object' })\n return\n }\n\n for (const key of Object.keys(value)) {\n if (!NODE_KEYS.has(key)) errors.push({ path, message: `unknown key \"${key}\"` })\n }\n\n if (typeof value.id !== 'string' || value.id === '') {\n errors.push({ path, message: '\"id\" is required and must be a non-empty string' })\n } else if (seen.has(value.id)) {\n errors.push({ path, message: `duplicate id \"${value.id}\"` })\n } else {\n seen.add(value.id)\n }\n\n if (typeof value.type !== 'string' || value.type === '') {\n errors.push({ path, message: '\"type\" is required and must be a non-empty string' })\n }\n\n for (const key of ['name', 'label', 'help'] as const) {\n if (key in value && typeof value[key] !== 'string') {\n errors.push({ path, message: `\"${key}\" must be a string` })\n }\n }\n if ('localized' in value && typeof value.localized !== 'boolean') {\n errors.push({ path, message: '\"localized\" must be a boolean' })\n }\n if ('props' in value && !isRecord(value.props)) {\n errors.push({ path, message: '\"props\" must be an object' })\n }\n if ('slot' in value && value.slot !== null && typeof value.slot !== 'string') {\n errors.push({ path, message: '\"slot\" must be a string or null' })\n }\n if ('can' in value && value.can !== null && typeof value.can !== 'string') {\n errors.push({ path, message: '\"can\" must be a string or null' })\n }\n if ('visible' in value && typeof value.visible !== 'boolean') {\n checkCondition(value.visible as VisibilityCondition, `${path}.visible`, errors)\n }\n\n if ('children' in value) {\n if (!Array.isArray(value.children)) {\n errors.push({ path, message: '\"children\" must be an array' })\n } else {\n value.children.forEach((child, index) =>\n checkNode(child, `${path}.children[${index}]`, errors, seen),\n )\n }\n }\n}\n\n/**\n * Checks a tree the way the JSON schema would, without a schema library: required\n * keys, closed key set, value types, and — what a schema cannot say — unique ids.\n * An empty list means the tree is sound.\n */\nexport function validateScreen(root: unknown): ScreenError[] {\n const errors: ScreenError[] = []\n if (!Array.isArray(root)) return [{ path: 'root', message: 'root must be an array of nodes' }]\n const seen = new Set<string>()\n root.forEach((node, index) => checkNode(node, `root[${index}]`, errors, seen))\n return errors\n}\n\n/** Same for a patch: each operation has the keys its `op` calls for. */\nexport function validatePatch(patch: unknown): ScreenError[] {\n const errors: ScreenError[] = []\n if (!Array.isArray(patch)) return [{ path: 'patch', message: 'a patch must be an array' }]\n\n patch.forEach((op, index) => {\n const path = `patch[${index}]`\n if (!isRecord(op)) {\n errors.push({ path, message: 'an operation must be an object' })\n return\n }\n if (typeof op.op !== 'string' || !OPS.has(op.op)) {\n errors.push({ path, message: '\"op\" must be one of add, remove, replace, move, set' })\n return\n }\n if (typeof op.target !== 'string' || op.target === '') {\n errors.push({ path, message: '\"target\" is required: the id of a node' })\n }\n if ((op.op === 'add' || op.op === 'replace') && !isRecord(op.node)) {\n errors.push({ path, message: `\"${op.op}\" needs a \"node\"` })\n } else if (op.op === 'add' || op.op === 'replace') {\n checkNode(op.node, `${path}.node`, errors, new Set())\n }\n if ('position' in op && !isPosition(op.position)) {\n errors.push({ path, message: '\"position\" must be first, last, before:<id> or after:<id>' })\n }\n if (op.op === 'move' && 'to' in op && typeof op.to !== 'string') {\n errors.push({ path, message: '\"to\" must be the id of the new parent' })\n }\n if (op.op === 'set') {\n for (const key of Object.keys(op)) {\n if (key !== 'op' && key !== 'target' && (!NODE_KEYS.has(key) || key === 'id')) {\n errors.push({ path, message: `\"set\" cannot change \"${key}\"` })\n }\n }\n }\n })\n\n return errors\n}\n\nfunction isPosition(value: unknown): boolean {\n return (\n typeof value === 'string' &&\n (value === 'first' ||\n value === 'last' ||\n value.startsWith('before:') ||\n value.startsWith('after:'))\n )\n}\n\nexport type { Patch, ScreenNode }\n","import { defineComponent, h, type PropType, type VNode } from 'vue'\nimport { WxFormItem } from '@webx-ui/core'\nimport { isVisible } from './visible'\nimport type { ScreenModel, ScreenNode, Translate, TypeRegistry } from './types'\n\nexport const TRANS_MARKER = 'trans::'\n\n/** What the recursive renderer needs at every level. */\nexport interface RenderContext {\n types: TypeRegistry\n model: ScreenModel\n update: (name: string, value: unknown) => void\n translate: Translate\n can: (permission: string) => boolean\n}\n\n/** Without a dictionary the key itself shows — honest, and easy to spot in a screenshot. */\nexport const keyAsIs: Translate = (key) => key\n\n/** Translates a marked string; anything else — including `undefined` — passes through. */\nexport function words<T>(value: T, translate: Translate): T {\n if (typeof value === 'string' && value.startsWith(TRANS_MARKER)) {\n return translate(value.slice(TRANS_MARKER.length)) as T\n }\n return value\n}\n\n/** Same, through arrays and objects: `props.options[].label` is the common case. */\nexport function translateDeep<T>(value: T, translate: Translate): T {\n if (typeof value === 'string') return words(value, translate)\n if (Array.isArray(value)) return value.map((item) => translateDeep(item, translate)) as T\n if (value && typeof value === 'object') {\n const out: Record<string, unknown> = {}\n for (const [key, item] of Object.entries(value)) out[key] = translateDeep(item, translate)\n return out as T\n }\n return value\n}\n\nfunction renderUnknown(node: ScreenNode): VNode {\n return h(\n 'div',\n { key: node.id, class: 'wx-screen__unknown', role: 'note' },\n `Unknown type: ${node.type}`,\n )\n}\n\n/** Children grouped by the slot they asked for. */\nfunction childSlots(\n node: ScreenNode,\n defaultSlot: string,\n context: RenderContext,\n): Record<string, () => VNode[]> {\n const groups = new Map<string, ScreenNode[]>()\n for (const child of node.children ?? []) {\n const name = child.slot ?? defaultSlot\n const list = groups.get(name) ?? []\n list.push(child)\n groups.set(name, list)\n }\n const slots: Record<string, () => VNode[]> = {}\n for (const [name, children] of groups) {\n slots[name] = () => renderNodes(children, context)\n }\n return slots\n}\n\nexport function renderNode(node: ScreenNode, context: RenderContext): VNode | null {\n if (node.can && !context.can(node.can)) return null\n if (!isVisible(node, context.model)) return null\n\n const entry = context.types[node.type]\n if (!entry) return renderUnknown(node)\n\n const { translate } = context\n const props: Record<string, unknown> = {\n key: node.id,\n ...translateDeep(node.props ?? {}, translate),\n ...entry.bind?.(node),\n }\n const label = words(node.label, translate)\n\n if (entry.kind === 'field') {\n const name = node.name\n const control = h(entry.component, {\n ...props,\n /* A nested field draws the children itself, so it needs the node and the way down. */\n ...(entry.nested ? { node, context } : {}),\n name,\n localized: node.localized || undefined,\n modelValue: name === undefined ? undefined : context.model[name],\n 'onUpdate:modelValue': (value: unknown) => {\n if (name !== undefined) context.update(name, value)\n },\n })\n return h(\n WxFormItem,\n { key: node.id, name, label, help: words(node.help, translate), wide: entry.wide },\n () => control,\n )\n }\n\n if (entry.kind === 'layout') {\n if (entry.labelProp && label !== undefined) props[entry.labelProp] = label\n return h(entry.component, props, childSlots(node, entry.childrenSlot ?? 'default', context))\n }\n\n // display\n if (entry.labelProp) {\n if (label !== undefined) props[entry.labelProp] = label\n return h(entry.component, props)\n }\n return h(entry.component, props, label === undefined ? undefined : () => label)\n}\n\nexport function renderNodes(nodes: ScreenNode[], context: RenderContext): VNode[] {\n const out: VNode[] = []\n for (const node of nodes) {\n const rendered = renderNode(node, context)\n if (rendered) out.push(rendered)\n }\n return out\n}\n\n/** A list of nodes as a component, so the tree can recurse through slots. */\nexport const WxScreenNodes = defineComponent({\n name: 'WxScreenNodes',\n props: {\n nodes: { type: Array as PropType<ScreenNode[]>, required: true },\n context: { type: Object as PropType<RenderContext>, required: true },\n },\n setup(props) {\n return () => renderNodes(props.nodes, props.context)\n },\n})\n","<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue'\nimport { WxRepeater } from '@webx-ui/core'\nimport { WxScreenNodes, type RenderContext } from './render'\nimport type { ScreenModel, ScreenNode } from './types'\n\ndefineOptions({ name: 'WxScreenRepeater', inheritAttrs: false })\n\n/**\n * The one type with a nested model: the value is a list of records, and the node's\n * children are the fields of one of them. Every child is bound by its own `name` to a key\n * of the item, which is why a repeater is the only place where a name means nesting.\n *\n * Nothing of `WxRepeater`'s own is declared here — `title`, `itemLabel`, `min` and the\n * rest ride in as attributes, so a prop the screen did not set stays unset instead of\n * arriving as `false`.\n */\nconst props = defineProps<{\n /** The node being drawn — its children are one item's fields. */\n node: ScreenNode\n /** The renderer's context; each row gets a copy bound to its own item. */\n context: RenderContext\n /** The renderer hands every field these two. A repeater has no use for either. */\n name?: string\n localized?: boolean\n}>()\n\nconst model = defineModel<ScreenModel[]>({ default: () => [] })\n\nconst items = computed<ScreenModel[]>(() => (Array.isArray(model.value) ? model.value : []))\n\nconst attrs = useAttrs()\n\n/**\n * The panel's words, where the core has only English defaults: the core does not know the\n * panel's dictionary, and a translated form with \"Add\" and \"Remove\" in the middle of it is what\n * that looks like. A key the dictionary does not have — a renderer without one — comes back as\n * itself, and then the core's own word is the better answer.\n */\nfunction word(key: string): string | undefined {\n const line = props.context.translate(`webx-admin::screens.repeater.${key}`)\n\n return line.includes('::') ? undefined : line\n}\n\n/**\n * Folded unless the node says otherwise: a list of records opened all at once is a form a\n * kilometre long, and the header of each row already says which one it is. A row added now is\n * the core's business and opens anyway.\n */\nconst bound = computed(() => {\n const defaults: Record<string, unknown> = { collapsed: true }\n\n for (const [prop, key] of [\n ['addLabel', 'add'],\n ['removeLabel', 'remove'],\n ['dragLabel', 'reorder'],\n ['emptyText', 'empty'],\n ] as const) {\n const line = word(key)\n if (line !== undefined) defaults[prop] = line\n }\n\n return { ...defaults, ...attrs }\n})\n</script>\n\n<template>\n <wx-repeater v-bind=\"bound\" :model-value=\"items\" @update:model-value=\"model = $event\">\n <template #default=\"{ item, update }\">\n <wx-screen-nodes\n :nodes=\"node.children ?? []\"\n :context=\"{\n ...context,\n model: item,\n update: (key: string, value: unknown) => update({ [key]: value }),\n }\"\n />\n </template>\n </wx-repeater>\n</template>\n","import {\n WxAlert,\n WxAutocomplete,\n WxCard,\n WxCascader,\n WxCheckbox,\n WxCheckboxGroup,\n WxCodeEditor,\n WxCol,\n WxColorPicker,\n WxDatePicker,\n WxDateRangePicker,\n WxDateTimePicker,\n WxDivider,\n WxHeading,\n WxIconPicker,\n WxInput,\n WxInputNumber,\n WxRadioGroup,\n WxRate,\n WxRow,\n WxSegmented,\n WxSelect,\n WxSlider,\n WxSwitch,\n WxTab,\n WxTabs,\n WxTagsInput,\n WxText,\n WxTextarea,\n WxTimePicker,\n WxTransfer,\n WxTreeSelect,\n} from '@webx-ui/core'\nimport ScreenRepeater from './ScreenRepeater.vue'\nimport type { NodeKind, TypeEntry, TypeRegistry } from './types'\n\n/**\n * The types every panel has: the core's layout, form and display components under\n * their full names. A module or a project adds its own the same way — `wx-media` comes\n * from `module-media`, `map` from whoever has a map.\n */\nexport const coreTypes: TypeRegistry = {\n 'wx-tabs': { component: WxTabs, kind: 'layout' },\n 'wx-tab': {\n component: WxTab,\n kind: 'layout',\n labelProp: 'label',\n // A tab is selected by value, and the node's id is the one stable thing it has.\n bind: (node) => ({ value: node.id }),\n },\n 'wx-card': { component: WxCard, kind: 'layout', labelProp: 'title' },\n 'wx-row': { component: WxRow, kind: 'layout' },\n 'wx-col': {\n component: WxCol,\n kind: 'layout',\n // Marked so the renderer can stack what a column holds (see `ScreenRenderer.vue`),\n // without touching a `WxCol` that some field happens to use inside itself.\n bind: (node) => ({ class: ['wx-screen__col', node.props?.class] }),\n },\n 'wx-divider': { component: WxDivider, kind: 'layout', labelProp: 'label' },\n\n 'wx-input': { component: WxInput, kind: 'field' },\n 'wx-textarea': { component: WxTextarea, kind: 'field' },\n 'wx-input-number': { component: WxInputNumber, kind: 'field' },\n 'wx-select': { component: WxSelect, kind: 'field' },\n 'wx-switch': { component: WxSwitch, kind: 'field' },\n 'wx-checkbox': { component: WxCheckbox, kind: 'field' },\n 'wx-radio-group': { component: WxRadioGroup, kind: 'field' },\n 'wx-date-picker': { component: WxDatePicker, kind: 'field' },\n 'wx-color-picker': { component: WxColorPicker, kind: 'field' },\n 'wx-checkbox-group': { component: WxCheckboxGroup, kind: 'field' },\n 'wx-segmented': { component: WxSegmented, kind: 'field' },\n 'wx-slider': { component: WxSlider, kind: 'field' },\n 'wx-rate': { component: WxRate, kind: 'field' },\n 'wx-time-picker': { component: WxTimePicker, kind: 'field' },\n 'wx-date-time-picker': {\n component: WxDateTimePicker,\n kind: 'field',\n // A moment, not a wall clock. Without the offset the server reads the hour in its own\n // timezone and the browser in the reader's, and one value shows two different times. Bound\n // over `props` on purpose: the server parses exactly this shape.\n bind: () => ({ valueFormat: \"yyyy-MM-dd'T'HH:mm:ssXXX\" }),\n },\n 'wx-date-range-picker': { component: WxDateRangePicker, kind: 'field' },\n 'wx-tags-input': { component: WxTagsInput, kind: 'field' },\n 'wx-autocomplete': { component: WxAutocomplete, kind: 'field' },\n 'wx-icon-picker': { component: WxIconPicker, kind: 'field' },\n 'wx-cascader': { component: WxCascader, kind: 'field' },\n 'wx-tree-select': { component: WxTreeSelect, kind: 'field' },\n // Wide: two lists with the buttons between them do not fit in half a form.\n 'wx-transfer': { component: WxTransfer, kind: 'field', wide: true },\n // Wide for the reason an editor is: code is read in long lines.\n 'wx-code-editor': { component: WxCodeEditor, kind: 'field', wide: true },\n 'wx-repeater': { component: ScreenRepeater, kind: 'field', nested: true, wide: true },\n\n 'wx-heading': { component: WxHeading, kind: 'display' },\n 'wx-text': { component: WxText, kind: 'display' },\n 'wx-alert': { component: WxAlert, kind: 'display', labelProp: 'title' },\n}\n\n/** Identity with a type: keeps a project's registry object checked without an import of the type. */\nexport function defineTypes<T extends TypeRegistry>(types: T): T {\n return types\n}\n\nexport interface TypeDescription {\n type: string\n kind: NodeKind\n component: string\n /** Where the node's `label` ends up, in words. */\n label: string\n}\n\nfunction componentName(entry: TypeEntry): string {\n const component = entry.component as { name?: string; __name?: string }\n return component.name ?? component.__name ?? 'anonymous'\n}\n\nfunction labelDestination(entry: TypeEntry): string {\n if (entry.kind === 'field') return 'form item'\n if (entry.labelProp) return `prop \\`${entry.labelProp}\\``\n return entry.kind === 'display' ? 'default slot' : '—'\n}\n\n/** One row per type, in registry order — what the documentation table is made of. */\nexport function describeTypes(types: TypeRegistry): TypeDescription[] {\n return Object.entries(types).map(([type, entry]) => ({\n type,\n kind: entry.kind,\n component: componentName(entry),\n label: labelDestination(entry),\n }))\n}\n\n/**\n * The registry as a Markdown table, padded the way Prettier pads one, so the generated\n * block in the guide survives `prettier --check` and a test can compare it verbatim.\n */\nexport function typesTable(types: TypeRegistry): string {\n const rows = describeTypes(types).map((row) => [\n `\\`${row.type}\\``,\n row.kind,\n `\\`${row.component}\\``,\n row.label,\n ])\n const header = ['Type', 'Kind', 'Component', '`label` goes to']\n const widths = header.map((cell, column) =>\n Math.max(cell.length, ...rows.map((row) => row[column]!.length)),\n )\n const line = (cells: string[]) =>\n `| ${cells.map((cell, column) => cell.padEnd(widths[column]!)).join(' | ')} |`\n return [line(header), line(widths.map((width) => '-'.repeat(width))), ...rows.map(line)].join(\n '\\n',\n )\n}\n","<script setup lang=\"ts\">\nimport { computed, markRaw, toRaw, watch } from 'vue'\nimport { WxForm } from '@webx-ui/core'\nimport { applyPatch } from './patch'\nimport { coreTypes } from './registry'\nimport { keyAsIs, WxScreenNodes, type RenderContext } from './render'\nimport type {\n Patch,\n PatchError,\n ScreenModel,\n ScreenNode,\n Translate,\n TypeRegistry,\n ValidationErrors,\n} from './types'\n\ndefineOptions({ name: 'WxScreenRenderer' })\n\nconst props = withDefaults(\n defineProps<{\n /** The tree to draw — a module's screen, already patched by the server. */\n root: ScreenNode[]\n /** Client-side patch applied on top, in order. */\n patch?: Patch\n /** Server-side validation errors, keyed by field name; shown under the fields. */\n errors?: ValidationErrors\n /** Project types, merged over the core ones. */\n types?: TypeRegistry\n /** Turns `trans::` strings into words. Without it the key shows. */\n translate?: Translate\n /** Decides `can`. Without it every node is allowed. */\n can?: (permission: string) => boolean\n disabled?: boolean\n labelPosition?: 'top' | 'left'\n labelWidth?: string\n size?: 'sm' | 'md' | 'lg'\n }>(),\n {\n patch: () => [],\n errors: undefined,\n types: undefined,\n translate: undefined,\n can: undefined,\n disabled: false,\n labelPosition: undefined,\n labelWidth: undefined,\n size: undefined,\n },\n)\n\nconst emit = defineEmits<{\n /** Operations that could not be applied. Also reported to the console. */\n patchError: [errors: PatchError[]]\n}>()\n\nconst model = defineModel<ScreenModel>({ default: () => ({}) })\n\nconst applied = computed(() => applyPatch(props.root, props.patch))\n\nwatch(\n () => applied.value.errors,\n (errors) => {\n for (const error of errors) {\n console.error(`[webx-ui/schema] patch[${error.index}] ${error.op.op}: ${error.message}`)\n }\n emit('patchError', errors)\n },\n { immediate: true },\n)\n\n/**\n * A registry kept in a `ref` arrives as a reactive proxy, and Vue warns about a\n * component that is one; the raw component is what `h()` wants anyway.\n */\nconst registry = computed<TypeRegistry>(() => {\n const merged: TypeRegistry = {}\n for (const [type, entry] of Object.entries({ ...coreTypes, ...props.types })) {\n merged[type] = { ...entry, component: markRaw(toRaw(entry.component)) }\n }\n return merged\n})\n\nconst context = computed<RenderContext>(() => ({\n types: registry.value,\n model: model.value,\n update: (name, value) => {\n model.value = { ...model.value, [name]: value }\n },\n translate: props.translate ?? keyAsIs,\n can: props.can ?? (() => true),\n}))\n\ndefineExpose({\n /** The tree after the patch — what is actually on screen. */\n tree: computed(() => applied.value.root),\n})\n</script>\n\n<template>\n <wx-form\n class=\"wx-screen\"\n :errors=\"errors\"\n :disabled=\"disabled\"\n :label-position=\"labelPosition\"\n :label-width=\"labelWidth\"\n :size=\"size\"\n >\n <wx-screen-nodes :nodes=\"applied.root\" :context=\"context\" />\n </wx-form>\n</template>\n\n<style>\n/*\n * A column is a stack of fields, like a card's body. The form's own gap reaches only its\n * direct children, so two fields dropped into one `wx-col` stood flush: the label of the\n * second read as the hint of the first. Same step as the form and the card.\n */\n.wx-screen__col {\n display: flex;\n flex-direction: column;\n gap: var(--wx-gap, var(--wx-space-16));\n}\n\n/* Global on purpose: the placeholder is created by a render function, outside any scope. */\n.wx-screen__unknown {\n padding: var(--wx-space-8) var(--wx-space-12);\n border: 1px dashed var(--wx-color-danger);\n border-radius: var(--wx-radius-control);\n background: var(--wx-color-danger-soft);\n color: var(--wx-color-danger);\n font-family: var(--wx-font-family-mono);\n font-size: var(--wx-font-size-sm);\n}\n</style>\n"],"names":["locate","root","id","index","node","found","findNode","collectIds","ids","walk","nodes","indexFor","list","position","where","anchor","at","clone","value","out","key","item","applyPatch","patch","tree","errors","op","message","apply","clash","duplicateIn","others","parent","contains","ancestor","child","incoming","except","existing","same","a","b","evaluateCondition","condition","model","isVisible","visible","NODE_KEYS","OPS","isRecord","checkCondition","path","forms","checkNode","seen","validateScreen","validatePatch","isPosition","TRANS_MARKER","keyAsIs","words","translate","translateDeep","renderUnknown","h","childSlots","defaultSlot","context","groups","name","slots","children","renderNodes","renderNode","entry","props","label","control","WxFormItem","rendered","WxScreenNodes","defineComponent","__props","_useModel","items","computed","attrs","useAttrs","word","line","bound","defaults","prop","_createBlock","_unref","WxRepeater","_mergeProps","_cache","$event","_withCtx","update","_createVNode","coreTypes","WxTabs","WxTab","WxCard","WxRow","WxCol","WxDivider","WxInput","WxTextarea","WxInputNumber","WxSelect","WxSwitch","WxCheckbox","WxRadioGroup","WxDatePicker","WxColorPicker","WxCheckboxGroup","WxSegmented","WxSlider","WxRate","WxTimePicker","WxDateTimePicker","WxDateRangePicker","WxTagsInput","WxAutocomplete","WxIconPicker","WxCascader","WxTreeSelect","WxTransfer","WxCodeEditor","ScreenRepeater","WxHeading","WxText","WxAlert","defineTypes","types","componentName","component","labelDestination","describeTypes","type","typesTable","rows","row","header","widths","cell","column","cells","width","emit","__emit","applied","watch","error","registry","merged","markRaw","toRaw","__expose","WxForm"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/patch.ts","../src/visible.ts","../src/validate.ts","../src/render.ts","../src/ScreenRepeater.vue","../src/ScreenTabs.vue","../src/registry.ts","../src/ScreenRenderer.vue"],"sourcesContent":["import type { Patch, PatchError, PatchOperation, PatchPosition, ScreenNode } from './types'\n\ninterface Located {\n /** The array the node sits in: the root, or a parent's `children`. */\n list: ScreenNode[]\n index: number\n node: ScreenNode\n}\n\n/** Depth-first search by `id`, remembering the array the match lives in. */\nexport function locate(root: ScreenNode[], id: string): Located | null {\n for (let index = 0; index < root.length; index += 1) {\n const node = root[index]!\n if (node.id === id) return { list: root, index, node }\n if (node.children) {\n const found = locate(node.children, id)\n if (found) return found\n }\n }\n return null\n}\n\nexport function findNode(root: ScreenNode[], id: string): ScreenNode | null {\n return locate(root, id)?.node ?? null\n}\n\n/** Every `id` in the tree, in document order. Duplicates are kept, so callers can spot them. */\nexport function collectIds(root: ScreenNode[]): string[] {\n const ids: string[] = []\n const walk = (nodes: ScreenNode[]) => {\n for (const node of nodes) {\n ids.push(node.id)\n if (node.children) walk(node.children)\n }\n }\n walk(root)\n return ids\n}\n\n/** Index a node should be inserted at in `list`, or a message when the anchor is missing. */\nfunction indexFor(list: ScreenNode[], position: PatchPosition | undefined): number | string {\n if (!position || position === 'last') return list.length\n if (position === 'first') return 0\n const [where, anchor] = position.split(':', 2) as ['before' | 'after', string]\n const at = list.findIndex((node) => node.id === anchor)\n if (at === -1) return `no sibling \"${anchor}\" to insert ${where}`\n return where === 'before' ? at : at + 1\n}\n\n/**\n * Deep copy of a JSON value. `structuredClone` refuses a Vue reactive proxy, and a\n * tree that came out of a `ref` is exactly that; reading through the proxy is fine.\n */\nexport function clone<T>(value: T): T {\n if (Array.isArray(value)) return value.map(clone) as T\n if (value && typeof value === 'object') {\n const out: Record<string, unknown> = {}\n for (const [key, item] of Object.entries(value)) out[key] = clone(item)\n return out as T\n }\n return value\n}\n\n/**\n * Applies a patch to a tree and returns the result as a new tree; the input is not\n * touched. An operation that cannot be applied — a `target` that does not exist, an\n * anchor that is missing — is skipped and reported, and the ones after it still run:\n * a project patch that survived a rename in the module must not silence the rest.\n */\nexport function applyPatch(\n root: ScreenNode[],\n patch: Patch,\n): { root: ScreenNode[]; errors: PatchError[] } {\n const tree = clone(root)\n const errors: PatchError[] = []\n\n patch.forEach((op, index) => {\n const message = apply(tree, op)\n if (message) errors.push({ index, op, message })\n })\n\n return { root: tree, errors }\n}\n\n/** Mutates `tree`; returns a message when the operation was refused. */\nfunction apply(tree: ScreenNode[], op: PatchOperation): string | null {\n const found = locate(tree, op.target)\n if (!found) return `target \"${op.target}\" not found`\n\n switch (op.op) {\n case 'add': {\n const clash = duplicateIn(tree, op.node)\n if (clash) return `id \"${clash}\" already exists in the screen`\n const list = (found.node.children ??= [])\n const at = indexFor(list, op.position)\n if (typeof at === 'string') return at\n list.splice(at, 0, clone(op.node))\n return null\n }\n case 'remove':\n found.list.splice(found.index, 1)\n return null\n case 'replace': {\n // The replaced node's own ids are gone, so only the rest of the tree can clash.\n const others = tree.filter((node) => node !== found.node)\n const clash = duplicateIn(others, op.node, found.node)\n if (clash) return `id \"${clash}\" already exists in the screen`\n found.list.splice(found.index, 1, clone(op.node))\n return null\n }\n case 'move': {\n let list = found.list\n if (op.to !== undefined) {\n const parent = locate(tree, op.to)\n if (!parent) return `destination \"${op.to}\" not found`\n if (parent.node === found.node || contains(found.node, parent.node)) {\n return `cannot move \"${op.target}\" into itself`\n }\n list = parent.node.children ??= []\n }\n found.list.splice(found.index, 1)\n const at = indexFor(list, op.position)\n if (typeof at === 'string') {\n // Put it back where it was: a refused move leaves the tree untouched.\n found.list.splice(found.index, 0, found.node)\n return at\n }\n list.splice(at, 0, found.node)\n return null\n }\n case 'set': {\n for (const [key, value] of Object.entries(op)) {\n if (key === 'op' || key === 'target') continue\n if (key === 'props') {\n found.node.props = { ...found.node.props, ...(value as Record<string, unknown>) }\n } else {\n ;(found.node as unknown as Record<string, unknown>)[key] = clone(value)\n }\n }\n return null\n }\n }\n}\n\nfunction contains(ancestor: ScreenNode, node: ScreenNode): boolean {\n return (ancestor.children ?? []).some((child) => child === node || contains(child, node))\n}\n\n/** First id of `incoming` that already exists in `tree`, ignoring `except`'s own subtree. */\nfunction duplicateIn(tree: ScreenNode[], incoming: ScreenNode, except?: ScreenNode): string | null {\n const existing = new Set(collectIds(tree))\n if (except) for (const id of collectIds([except])) existing.delete(id)\n return collectIds([incoming]).find((id) => existing.has(id)) ?? null\n}\n","import type { ScreenModel, ScreenNode, VisibilityCondition } from './types'\n\n/** Loose enough for `{ \"is\": 1 }` to match a numeric input, strict enough for `\"1\"` not to. */\nfunction same(a: unknown, b: unknown): boolean {\n if (a === b) return true\n if (a === null || b === null || typeof a !== 'object' || typeof b !== 'object') return false\n return JSON.stringify(a) === JSON.stringify(b)\n}\n\nexport function evaluateCondition(condition: VisibilityCondition, model: ScreenModel): boolean {\n if ('all' in condition) return condition.all.every((item) => evaluateCondition(item, model))\n if ('any' in condition) return condition.any.some((item) => evaluateCondition(item, model))\n\n const value = model[condition.when]\n if ('in' in condition) return condition.in.some((item) => same(item, value))\n if ('not' in condition) return !same(condition.not, value)\n return same(condition.is, value)\n}\n\n/** Whether a node should render, given the current model. Absent `visible` means yes. */\nexport function isVisible(node: ScreenNode, model: ScreenModel): boolean {\n const { visible } = node\n if (visible === undefined || visible === true) return true\n if (visible === false) return false\n return evaluateCondition(visible, model)\n}\n","import type { Patch, ScreenError, ScreenNode, VisibilityCondition } from './types'\n\nconst NODE_KEYS = new Set([\n 'id',\n 'type',\n 'name',\n 'label',\n 'help',\n 'localized',\n 'props',\n 'children',\n 'slot',\n 'visible',\n 'can',\n])\n\nconst OPS = new Set(['add', 'remove', 'replace', 'move', 'set'])\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nfunction checkCondition(value: unknown, path: string, errors: ScreenError[]): void {\n if (!isRecord(value)) {\n errors.push({ path, message: 'visible must be a boolean or a condition object' })\n return\n }\n if ('all' in value || 'any' in value) {\n const list = (value.all ?? value.any) as unknown\n if (!Array.isArray(list)) {\n errors.push({ path, message: '\"all\" / \"any\" must be an array of conditions' })\n return\n }\n list.forEach((item, index) => checkCondition(item, `${path}[${index}]`, errors))\n return\n }\n if (typeof value.when !== 'string') {\n errors.push({ path, message: 'a condition needs \"when\": the name of a field' })\n return\n }\n const forms = ['is', 'in', 'not'].filter((key) => key in value)\n if (forms.length !== 1) {\n errors.push({ path, message: 'a condition needs exactly one of \"is\", \"in\", \"not\"' })\n } else if (forms[0] === 'in' && !Array.isArray(value.in)) {\n errors.push({ path, message: '\"in\" must be an array' })\n }\n}\n\nfunction checkNode(value: unknown, path: string, errors: ScreenError[], seen: Set<string>): void {\n if (!isRecord(value)) {\n errors.push({ path, message: 'a node must be an object' })\n return\n }\n\n for (const key of Object.keys(value)) {\n if (!NODE_KEYS.has(key)) errors.push({ path, message: `unknown key \"${key}\"` })\n }\n\n if (typeof value.id !== 'string' || value.id === '') {\n errors.push({ path, message: '\"id\" is required and must be a non-empty string' })\n } else if (seen.has(value.id)) {\n errors.push({ path, message: `duplicate id \"${value.id}\"` })\n } else {\n seen.add(value.id)\n }\n\n if (typeof value.type !== 'string' || value.type === '') {\n errors.push({ path, message: '\"type\" is required and must be a non-empty string' })\n }\n\n for (const key of ['name', 'label', 'help'] as const) {\n if (key in value && typeof value[key] !== 'string') {\n errors.push({ path, message: `\"${key}\" must be a string` })\n }\n }\n if ('localized' in value && typeof value.localized !== 'boolean') {\n errors.push({ path, message: '\"localized\" must be a boolean' })\n }\n if ('props' in value && !isRecord(value.props)) {\n errors.push({ path, message: '\"props\" must be an object' })\n }\n if ('slot' in value && value.slot !== null && typeof value.slot !== 'string') {\n errors.push({ path, message: '\"slot\" must be a string or null' })\n }\n if ('can' in value && value.can !== null && typeof value.can !== 'string') {\n errors.push({ path, message: '\"can\" must be a string or null' })\n }\n if ('visible' in value && typeof value.visible !== 'boolean') {\n checkCondition(value.visible as VisibilityCondition, `${path}.visible`, errors)\n }\n\n if ('children' in value) {\n if (!Array.isArray(value.children)) {\n errors.push({ path, message: '\"children\" must be an array' })\n } else {\n value.children.forEach((child, index) =>\n checkNode(child, `${path}.children[${index}]`, errors, seen),\n )\n }\n }\n}\n\n/**\n * Checks a tree the way the JSON schema would, without a schema library: required\n * keys, closed key set, value types, and — what a schema cannot say — unique ids.\n * An empty list means the tree is sound.\n */\nexport function validateScreen(root: unknown): ScreenError[] {\n const errors: ScreenError[] = []\n if (!Array.isArray(root)) return [{ path: 'root', message: 'root must be an array of nodes' }]\n const seen = new Set<string>()\n root.forEach((node, index) => checkNode(node, `root[${index}]`, errors, seen))\n return errors\n}\n\n/** Same for a patch: each operation has the keys its `op` calls for. */\nexport function validatePatch(patch: unknown): ScreenError[] {\n const errors: ScreenError[] = []\n if (!Array.isArray(patch)) return [{ path: 'patch', message: 'a patch must be an array' }]\n\n patch.forEach((op, index) => {\n const path = `patch[${index}]`\n if (!isRecord(op)) {\n errors.push({ path, message: 'an operation must be an object' })\n return\n }\n if (typeof op.op !== 'string' || !OPS.has(op.op)) {\n errors.push({ path, message: '\"op\" must be one of add, remove, replace, move, set' })\n return\n }\n if (typeof op.target !== 'string' || op.target === '') {\n errors.push({ path, message: '\"target\" is required: the id of a node' })\n }\n if ((op.op === 'add' || op.op === 'replace') && !isRecord(op.node)) {\n errors.push({ path, message: `\"${op.op}\" needs a \"node\"` })\n } else if (op.op === 'add' || op.op === 'replace') {\n checkNode(op.node, `${path}.node`, errors, new Set())\n }\n if ('position' in op && !isPosition(op.position)) {\n errors.push({ path, message: '\"position\" must be first, last, before:<id> or after:<id>' })\n }\n if (op.op === 'move' && 'to' in op && typeof op.to !== 'string') {\n errors.push({ path, message: '\"to\" must be the id of the new parent' })\n }\n if (op.op === 'set') {\n for (const key of Object.keys(op)) {\n if (key !== 'op' && key !== 'target' && (!NODE_KEYS.has(key) || key === 'id')) {\n errors.push({ path, message: `\"set\" cannot change \"${key}\"` })\n }\n }\n }\n })\n\n return errors\n}\n\nfunction isPosition(value: unknown): boolean {\n return (\n typeof value === 'string' &&\n (value === 'first' ||\n value === 'last' ||\n value.startsWith('before:') ||\n value.startsWith('after:'))\n )\n}\n\nexport type { Patch, ScreenNode }\n","import { defineComponent, h, type InjectionKey, type PropType, type Ref, type VNode } from 'vue'\nimport { WxFormItem } from '@webx-ui/core'\nimport { isVisible } from './visible'\nimport type { ScreenModel, ScreenNode, Translate, TypeRegistry, ValidationErrors } from './types'\n\nexport const TRANS_MARKER = 'trans::'\n\n/** What the recursive renderer needs at every level. */\nexport interface RenderContext {\n types: TypeRegistry\n model: ScreenModel\n update: (name: string, value: unknown) => void\n translate: Translate\n can: (permission: string) => boolean\n}\n\n/**\n * The refusal of the last save, for the nodes that have to act on it rather than only draw it:\n * the tabs, which open the one the failing field is on. Fields draw theirs through `WxForm`.\n */\nexport const screenErrorsKey: InjectionKey<Ref<ValidationErrors | undefined>> =\n Symbol('wx-screen-errors')\n\n/** Whether a node would draw anything at all for this administrator and these values. */\nfunction shown(node: ScreenNode, context: RenderContext): boolean {\n if (node.can && !context.can(node.can)) return false\n return isVisible(node, context.model)\n}\n\n/** Without a dictionary the key itself shows — honest, and easy to spot in a screenshot. */\nexport const keyAsIs: Translate = (key) => key\n\n/** Translates a marked string; anything else — including `undefined` — passes through. */\nexport function words<T>(value: T, translate: Translate): T {\n if (typeof value === 'string' && value.startsWith(TRANS_MARKER)) {\n return translate(value.slice(TRANS_MARKER.length)) as T\n }\n return value\n}\n\n/** Same, through arrays and objects: `props.options[].label` is the common case. */\nexport function translateDeep<T>(value: T, translate: Translate): T {\n if (typeof value === 'string') return words(value, translate)\n if (Array.isArray(value)) return value.map((item) => translateDeep(item, translate)) as T\n if (value && typeof value === 'object') {\n const out: Record<string, unknown> = {}\n for (const [key, item] of Object.entries(value)) out[key] = translateDeep(item, translate)\n return out as T\n }\n return value\n}\n\nfunction renderUnknown(node: ScreenNode): VNode {\n return h(\n 'div',\n { key: node.id, class: 'wx-screen__unknown', role: 'note' },\n `Unknown type: ${node.type}`,\n )\n}\n\n/** Children grouped by the slot they asked for. */\nfunction childSlots(\n node: ScreenNode,\n defaultSlot: string,\n context: RenderContext,\n): Record<string, () => VNode[]> {\n const groups = new Map<string, ScreenNode[]>()\n for (const child of node.children ?? []) {\n const name = child.slot ?? defaultSlot\n const list = groups.get(name) ?? []\n list.push(child)\n groups.set(name, list)\n }\n const slots: Record<string, () => VNode[]> = {}\n for (const [name, children] of groups) {\n slots[name] = () => renderNodes(children, context)\n }\n return slots\n}\n\nexport function renderNode(node: ScreenNode, context: RenderContext): VNode | null {\n if (!shown(node, context)) return null\n\n const entry = context.types[node.type]\n if (!entry) return renderUnknown(node)\n\n /*\n * A container with nothing in it is not drawn. A screen declares the card the fields of a\n * project go into (`project-fields`) so that a patch knows where to stand, and on every site\n * that patches nothing it was an empty card with a heading — a promise of fields that are not\n * there. Only a container that has children to lose: one described without any is a component\n * that draws itself.\n */\n if (\n entry.kind === 'layout' &&\n node.children !== undefined &&\n !node.children.some((child) => shown(child, context))\n ) {\n return null\n }\n\n const { translate } = context\n const props: Record<string, unknown> = {\n key: node.id,\n ...translateDeep(node.props ?? {}, translate),\n ...entry.bind?.(node),\n }\n const label = words(node.label, translate)\n\n if (entry.kind === 'field') {\n const name = node.name\n const control = h(entry.component, {\n ...props,\n /* A nested field draws the children itself, so it needs the node and the way down. */\n ...(entry.nested ? { node, context } : {}),\n name,\n localized: node.localized || undefined,\n modelValue: name === undefined ? undefined : context.model[name],\n 'onUpdate:modelValue': (value: unknown) => {\n if (name !== undefined) context.update(name, value)\n },\n })\n return h(\n WxFormItem,\n { key: node.id, name, label, help: words(node.help, translate), wide: entry.wide },\n () => control,\n )\n }\n\n if (entry.kind === 'layout') {\n if (entry.labelProp && label !== undefined) props[entry.labelProp] = label\n return h(entry.component, props, childSlots(node, entry.childrenSlot ?? 'default', context))\n }\n\n // display\n if (entry.labelProp) {\n if (label !== undefined) props[entry.labelProp] = label\n return h(entry.component, props)\n }\n return h(entry.component, props, label === undefined ? undefined : () => label)\n}\n\nexport function renderNodes(nodes: ScreenNode[], context: RenderContext): VNode[] {\n const out: VNode[] = []\n for (const node of nodes) {\n const rendered = renderNode(node, context)\n if (rendered) out.push(rendered)\n }\n return out\n}\n\n/** A list of nodes as a component, so the tree can recurse through slots. */\nexport const WxScreenNodes = defineComponent({\n name: 'WxScreenNodes',\n props: {\n nodes: { type: Array as PropType<ScreenNode[]>, required: true },\n context: { type: Object as PropType<RenderContext>, required: true },\n },\n setup(props) {\n return () => renderNodes(props.nodes, props.context)\n },\n})\n","<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue'\nimport { WxRepeater } from '@webx-ui/core'\nimport { WxScreenNodes, type RenderContext } from './render'\nimport type { ScreenModel, ScreenNode } from './types'\n\ndefineOptions({ name: 'WxScreenRepeater', inheritAttrs: false })\n\n/**\n * The one type with a nested model: the value is a list of records, and the node's\n * children are the fields of one of them. Every child is bound by its own `name` to a key\n * of the item, which is why a repeater is the only place where a name means nesting.\n *\n * Nothing of `WxRepeater`'s own is declared here — `title`, `itemLabel`, `min` and the\n * rest ride in as attributes, so a prop the screen did not set stays unset instead of\n * arriving as `false`.\n */\nconst props = defineProps<{\n /** The node being drawn — its children are one item's fields. */\n node: ScreenNode\n /** The renderer's context; each row gets a copy bound to its own item. */\n context: RenderContext\n /** The renderer hands every field these two. A repeater has no use for either. */\n name?: string\n localized?: boolean\n}>()\n\nconst model = defineModel<ScreenModel[]>({ default: () => [] })\n\nconst items = computed<ScreenModel[]>(() => (Array.isArray(model.value) ? model.value : []))\n\nconst attrs = useAttrs()\n\n/**\n * The panel's words, where the core has only English defaults: the core does not know the\n * panel's dictionary, and a translated form with \"Add\" and \"Remove\" in the middle of it is what\n * that looks like. A key the dictionary does not have — a renderer without one — comes back as\n * itself, and then the core's own word is the better answer.\n */\nfunction word(key: string): string | undefined {\n const line = props.context.translate(`webx-admin::screens.repeater.${key}`)\n\n return line.includes('::') ? undefined : line\n}\n\n/**\n * Folded unless the node says otherwise: a list of records opened all at once is a form a\n * kilometre long, and the header of each row already says which one it is. A row added now is\n * the core's business and opens anyway.\n */\nconst bound = computed(() => {\n const defaults: Record<string, unknown> = { collapsed: true }\n\n for (const [prop, key] of [\n ['addLabel', 'add'],\n ['removeLabel', 'remove'],\n ['dragLabel', 'reorder'],\n ['emptyText', 'empty'],\n ] as const) {\n const line = word(key)\n if (line !== undefined) defaults[prop] = line\n }\n\n return { ...defaults, ...attrs }\n})\n</script>\n\n<template>\n <wx-repeater v-bind=\"bound\" :model-value=\"items\" @update:model-value=\"model = $event\">\n <template #default=\"{ item, update }\">\n <wx-screen-nodes\n :nodes=\"node.children ?? []\"\n :context=\"{\n ...context,\n model: item,\n update: (key: string, value: unknown) => update({ [key]: value }),\n }\"\n />\n </template>\n </wx-repeater>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, inject, ref, watch } from 'vue'\nimport { WxTabs, type TabValue } from '@webx-ui/core'\nimport { screenErrorsKey } from './render'\n\n/**\n * The tabs of a described screen: `WxTabs`, and the one thing a form of tabs needs that a strip\n * of tabs does not — a refused save opens the tab the refusal is on.\n *\n * Without it a 422 can land on a tab nobody is looking at: the message is drawn under a field\n * that is not on screen, and the form looks as if it refused for no reason. A page hosting a\n * screen cannot do this itself, because the tabs are the description's and the page never sees\n * which field sits on which of them; the registry does, and hands the answer in as `fields`.\n *\n * The tab being looked at wins when it has a failing field of its own: the editor is already\n * where the problem is, and moving them would be moving them away from it.\n */\ndefineOptions({ name: 'WxScreenTabs', inheritAttrs: false })\n\nconst props = withDefaults(\n defineProps<{\n /** The names of the fields under each tab, in the order the tabs are read. */\n fields?: Record<string, string[]>\n }>(),\n { fields: () => ({}) },\n)\n\nconst errors = inject(screenErrorsKey, null)\n\nconst active = ref<TabValue | undefined>(undefined)\n\n/** The tabs holding a failing field, in the order they are read. The renderer has already put\n `slug.en` under `slug`, so a name is looked up as it is. */\nconst failing = computed<string[]>(() => {\n const names = new Set(Object.keys(errors?.value ?? {}))\n\n return Object.entries(props.fields)\n .filter(([, fields]) => fields.some((field) => names.has(field)))\n .map(([tab]) => tab)\n})\n\nwatch(failing, (tabs) => {\n const first = tabs[0]\n\n if (first === undefined) return\n if (active.value !== undefined && tabs.includes(String(active.value))) return\n\n active.value = first\n})\n</script>\n\n<template>\n <wx-tabs v-model=\"active\" v-bind=\"$attrs\">\n <slot />\n </wx-tabs>\n</template>\n","import {\n WxAlert,\n WxAutocomplete,\n WxCard,\n WxCascader,\n WxCheckbox,\n WxCheckboxGroup,\n WxCodeEditor,\n WxCol,\n WxColorPicker,\n WxDatePicker,\n WxDateRangePicker,\n WxDateTimePicker,\n WxDivider,\n WxHeading,\n WxIconPicker,\n WxInput,\n WxInputNumber,\n WxRadioGroup,\n WxRate,\n WxRow,\n WxSegmented,\n WxSelect,\n WxSlider,\n WxSwitch,\n WxTab,\n WxTagsInput,\n WxText,\n WxTextarea,\n WxTimePicker,\n WxTransfer,\n WxTreeSelect,\n} from '@webx-ui/core'\nimport ScreenRepeater from './ScreenRepeater.vue'\nimport ScreenTabs from './ScreenTabs.vue'\nimport type { NodeKind, ScreenNode, TypeEntry, TypeRegistry } from './types'\n\n/** Every field name under a node, however deep — what a tab has to open for. */\nfunction fieldNames(node: ScreenNode): string[] {\n return (node.children ?? []).flatMap((child) =>\n child.name === undefined ? fieldNames(child) : [child.name],\n )\n}\n\n/**\n * The types every panel has: the core's layout, form and display components under\n * their full names. A module or a project adds its own the same way — `wx-media` comes\n * from `module-media`, `map` from whoever has a map.\n */\nexport const coreTypes: TypeRegistry = {\n 'wx-tabs': {\n component: ScreenTabs,\n kind: 'layout',\n // Which fields each tab holds, so a refused save can open the tab it was refused on.\n bind: (node) => ({\n fields: Object.fromEntries((node.children ?? []).map((tab) => [tab.id, fieldNames(tab)])),\n }),\n },\n 'wx-tab': {\n component: WxTab,\n kind: 'layout',\n labelProp: 'label',\n // A tab is selected by value, and the node's id is the one stable thing it has.\n bind: (node) => ({ value: node.id }),\n },\n 'wx-card': { component: WxCard, kind: 'layout', labelProp: 'title' },\n 'wx-row': { component: WxRow, kind: 'layout' },\n 'wx-col': {\n component: WxCol,\n kind: 'layout',\n // Marked so the renderer can stack what a column holds (see `ScreenRenderer.vue`),\n // without touching a `WxCol` that some field happens to use inside itself.\n bind: (node) => ({ class: ['wx-screen__col', node.props?.class] }),\n },\n 'wx-divider': { component: WxDivider, kind: 'layout', labelProp: 'label' },\n\n 'wx-input': { component: WxInput, kind: 'field' },\n 'wx-textarea': { component: WxTextarea, kind: 'field' },\n 'wx-input-number': { component: WxInputNumber, kind: 'field' },\n 'wx-select': { component: WxSelect, kind: 'field' },\n 'wx-switch': { component: WxSwitch, kind: 'field' },\n 'wx-checkbox': { component: WxCheckbox, kind: 'field' },\n 'wx-radio-group': { component: WxRadioGroup, kind: 'field' },\n 'wx-date-picker': { component: WxDatePicker, kind: 'field' },\n 'wx-color-picker': { component: WxColorPicker, kind: 'field' },\n 'wx-checkbox-group': { component: WxCheckboxGroup, kind: 'field' },\n 'wx-segmented': { component: WxSegmented, kind: 'field' },\n 'wx-slider': { component: WxSlider, kind: 'field' },\n 'wx-rate': { component: WxRate, kind: 'field' },\n 'wx-time-picker': { component: WxTimePicker, kind: 'field' },\n 'wx-date-time-picker': {\n component: WxDateTimePicker,\n kind: 'field',\n // A moment, not a wall clock. Without the offset the server reads the hour in its own\n // timezone and the browser in the reader's, and one value shows two different times. Bound\n // over `props` on purpose: the server parses exactly this shape.\n bind: () => ({ valueFormat: \"yyyy-MM-dd'T'HH:mm:ssXXX\" }),\n },\n 'wx-date-range-picker': { component: WxDateRangePicker, kind: 'field' },\n 'wx-tags-input': { component: WxTagsInput, kind: 'field' },\n 'wx-autocomplete': { component: WxAutocomplete, kind: 'field' },\n 'wx-icon-picker': { component: WxIconPicker, kind: 'field' },\n 'wx-cascader': { component: WxCascader, kind: 'field' },\n 'wx-tree-select': { component: WxTreeSelect, kind: 'field' },\n // Wide: two lists with the buttons between them do not fit in half a form.\n 'wx-transfer': { component: WxTransfer, kind: 'field', wide: true },\n // Wide for the reason an editor is: code is read in long lines.\n 'wx-code-editor': { component: WxCodeEditor, kind: 'field', wide: true },\n 'wx-repeater': { component: ScreenRepeater, kind: 'field', nested: true, wide: true },\n\n 'wx-heading': { component: WxHeading, kind: 'display' },\n 'wx-text': { component: WxText, kind: 'display' },\n 'wx-alert': { component: WxAlert, kind: 'display', labelProp: 'title' },\n}\n\n/** Identity with a type: keeps a project's registry object checked without an import of the type. */\nexport function defineTypes<T extends TypeRegistry>(types: T): T {\n return types\n}\n\nexport interface TypeDescription {\n type: string\n kind: NodeKind\n component: string\n /** Where the node's `label` ends up, in words. */\n label: string\n}\n\nfunction componentName(entry: TypeEntry): string {\n const component = entry.component as { name?: string; __name?: string }\n return component.name ?? component.__name ?? 'anonymous'\n}\n\nfunction labelDestination(entry: TypeEntry): string {\n if (entry.kind === 'field') return 'form item'\n if (entry.labelProp) return `prop \\`${entry.labelProp}\\``\n return entry.kind === 'display' ? 'default slot' : '—'\n}\n\n/** One row per type, in registry order — what the documentation table is made of. */\nexport function describeTypes(types: TypeRegistry): TypeDescription[] {\n return Object.entries(types).map(([type, entry]) => ({\n type,\n kind: entry.kind,\n component: componentName(entry),\n label: labelDestination(entry),\n }))\n}\n\n/**\n * The registry as a Markdown table, padded the way Prettier pads one, so the generated\n * block in the guide survives `prettier --check` and a test can compare it verbatim.\n */\nexport function typesTable(types: TypeRegistry): string {\n const rows = describeTypes(types).map((row) => [\n `\\`${row.type}\\``,\n row.kind,\n `\\`${row.component}\\``,\n row.label,\n ])\n const header = ['Type', 'Kind', 'Component', '`label` goes to']\n const widths = header.map((cell, column) =>\n Math.max(cell.length, ...rows.map((row) => row[column]!.length)),\n )\n const line = (cells: string[]) =>\n `| ${cells.map((cell, column) => cell.padEnd(widths[column]!)).join(' | ')} |`\n return [line(header), line(widths.map((width) => '-'.repeat(width))), ...rows.map(line)].join(\n '\\n',\n )\n}\n","<script setup lang=\"ts\">\nimport { computed, markRaw, provide, toRaw, watch } from 'vue'\nimport { WxForm } from '@webx-ui/core'\nimport { applyPatch } from './patch'\nimport { coreTypes } from './registry'\nimport { keyAsIs, screenErrorsKey, WxScreenNodes, type RenderContext } from './render'\nimport type {\n Patch,\n PatchError,\n ScreenModel,\n ScreenNode,\n Translate,\n TypeRegistry,\n ValidationErrors,\n} from './types'\n\ndefineOptions({ name: 'WxScreenRenderer' })\n\nconst props = withDefaults(\n defineProps<{\n /** The tree to draw — a module's screen, already patched by the server. */\n root: ScreenNode[]\n /** Client-side patch applied on top, in order. */\n patch?: Patch\n /** Server-side validation errors, keyed by field name; shown under the fields. */\n errors?: ValidationErrors\n /** Project types, merged over the core ones. */\n types?: TypeRegistry\n /** Turns `trans::` strings into words. Without it the key shows. */\n translate?: Translate\n /** Decides `can`. Without it every node is allowed. */\n can?: (permission: string) => boolean\n disabled?: boolean\n labelPosition?: 'top' | 'left'\n labelWidth?: string\n size?: 'sm' | 'md' | 'lg'\n }>(),\n {\n patch: () => [],\n errors: undefined,\n types: undefined,\n translate: undefined,\n can: undefined,\n disabled: false,\n labelPosition: undefined,\n labelWidth: undefined,\n size: undefined,\n },\n)\n\nconst emit = defineEmits<{\n /** Operations that could not be applied. Also reported to the console. */\n patchError: [errors: PatchError[]]\n}>()\n\nconst model = defineModel<ScreenModel>({ default: () => ({}) })\n\nconst applied = computed(() => applyPatch(props.root, props.patch))\n\n/** Every field name on the screen, however deep — a repeater is one field, not its items. */\nfunction names(nodes: ScreenNode[]): string[] {\n return nodes.flatMap((node) =>\n node.name === undefined ? names(node.children ?? []) : [node.name],\n )\n}\n\n/**\n * The refusal, under the names the fields answer to.\n *\n * Laravel names the language that failed — `slug.en` — and `WxFormItem` looks its error up by\n * the field's own name, so a refused translated field showed nothing at all: the save failed and\n * every field looked fine. A key is matched against the field names rather than cut at its first\n * dot, because a name may carry a dot of its own (`general.project-name`, CLAUDE.md §4).\n */\nconst fieldErrors = computed<ValidationErrors | undefined>(() => {\n if (props.errors === undefined) return undefined\n\n const fields = names(applied.value.root)\n const out: ValidationErrors = { ...props.errors }\n\n for (const [key, messages] of Object.entries(props.errors)) {\n const field = fields.find((name) => key.startsWith(`${name}.`))\n\n if (field !== undefined && out[field] === undefined) out[field] = messages\n }\n\n return out\n})\n\n// For the nodes that act on a refusal rather than only draw it — the tabs (`ScreenTabs.vue`).\nprovide(screenErrorsKey, fieldErrors)\n\nwatch(\n () => applied.value.errors,\n (errors) => {\n for (const error of errors) {\n console.error(`[webx-ui/schema] patch[${error.index}] ${error.op.op}: ${error.message}`)\n }\n emit('patchError', errors)\n },\n { immediate: true },\n)\n\n/**\n * A registry kept in a `ref` arrives as a reactive proxy, and Vue warns about a\n * component that is one; the raw component is what `h()` wants anyway.\n */\nconst registry = computed<TypeRegistry>(() => {\n const merged: TypeRegistry = {}\n for (const [type, entry] of Object.entries({ ...coreTypes, ...props.types })) {\n merged[type] = { ...entry, component: markRaw(toRaw(entry.component)) }\n }\n return merged\n})\n\nconst context = computed<RenderContext>(() => ({\n types: registry.value,\n model: model.value,\n update: (name, value) => {\n model.value = { ...model.value, [name]: value }\n },\n translate: props.translate ?? keyAsIs,\n can: props.can ?? (() => true),\n}))\n\ndefineExpose({\n /** The tree after the patch — what is actually on screen. */\n tree: computed(() => applied.value.root),\n})\n</script>\n\n<template>\n <wx-form\n class=\"wx-screen\"\n :errors=\"fieldErrors\"\n :disabled=\"disabled\"\n :label-position=\"labelPosition\"\n :label-width=\"labelWidth\"\n :size=\"size\"\n >\n <wx-screen-nodes :nodes=\"applied.root\" :context=\"context\" />\n </wx-form>\n</template>\n\n<style>\n/*\n * A column is a stack of fields, like a card's body. The form's own gap reaches only its\n * direct children, so two fields dropped into one `wx-col` stood flush: the label of the\n * second read as the hint of the first. Same step as the form and the card.\n */\n.wx-screen__col {\n display: flex;\n flex-direction: column;\n gap: var(--wx-gap, var(--wx-space-16));\n}\n\n/* Global on purpose: the placeholder is created by a render function, outside any scope. */\n.wx-screen__unknown {\n padding: var(--wx-space-8) var(--wx-space-12);\n border: 1px dashed var(--wx-color-danger);\n border-radius: var(--wx-radius-control);\n background: var(--wx-color-danger-soft);\n color: var(--wx-color-danger);\n font-family: var(--wx-font-family-mono);\n font-size: var(--wx-font-size-sm);\n}\n</style>\n"],"names":["locate","root","id","index","node","found","findNode","collectIds","ids","walk","nodes","indexFor","list","position","where","anchor","at","clone","value","out","key","item","applyPatch","patch","tree","errors","op","message","apply","clash","duplicateIn","others","parent","contains","ancestor","child","incoming","except","existing","same","a","b","evaluateCondition","condition","model","isVisible","visible","NODE_KEYS","OPS","isRecord","checkCondition","path","forms","checkNode","seen","validateScreen","validatePatch","isPosition","TRANS_MARKER","screenErrorsKey","shown","context","keyAsIs","words","translate","translateDeep","renderUnknown","h","childSlots","defaultSlot","groups","name","slots","children","renderNodes","renderNode","entry","props","label","control","WxFormItem","rendered","WxScreenNodes","defineComponent","__props","_useModel","items","computed","attrs","useAttrs","word","line","bound","defaults","prop","_createBlock","_unref","WxRepeater","_mergeProps","_cache","$event","_withCtx","update","_createVNode","inject","active","ref","failing","names","fields","field","tab","watch","tabs","first","_openBlock","$attrs","_renderSlot","_ctx","fieldNames","coreTypes","ScreenTabs","WxTab","WxCard","WxRow","WxCol","WxDivider","WxInput","WxTextarea","WxInputNumber","WxSelect","WxSwitch","WxCheckbox","WxRadioGroup","WxDatePicker","WxColorPicker","WxCheckboxGroup","WxSegmented","WxSlider","WxRate","WxTimePicker","WxDateTimePicker","WxDateRangePicker","WxTagsInput","WxAutocomplete","WxIconPicker","WxCascader","WxTreeSelect","WxTransfer","WxCodeEditor","ScreenRepeater","WxHeading","WxText","WxAlert","defineTypes","types","componentName","component","labelDestination","describeTypes","type","typesTable","rows","row","header","widths","cell","column","cells","width","emit","__emit","applied","fieldErrors","messages","provide","error","registry","merged","markRaw","toRaw","__expose","WxForm"],"mappings":"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"}
|
package/dist/render.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { PropType, VNode } from 'vue';
|
|
2
|
-
import { ScreenModel, ScreenNode, Translate, TypeRegistry } from './types';
|
|
1
|
+
import { InjectionKey, PropType, Ref, VNode } from 'vue';
|
|
2
|
+
import { ScreenModel, ScreenNode, Translate, TypeRegistry, ValidationErrors } from './types';
|
|
3
3
|
export declare const TRANS_MARKER = "trans::";
|
|
4
4
|
/** What the recursive renderer needs at every level. */
|
|
5
5
|
export interface RenderContext {
|
|
@@ -9,6 +9,11 @@ export interface RenderContext {
|
|
|
9
9
|
translate: Translate;
|
|
10
10
|
can: (permission: string) => boolean;
|
|
11
11
|
}
|
|
12
|
+
/**
|
|
13
|
+
* The refusal of the last save, for the nodes that have to act on it rather than only draw it:
|
|
14
|
+
* the tabs, which open the one the failing field is on. Fields draw theirs through `WxForm`.
|
|
15
|
+
*/
|
|
16
|
+
export declare const screenErrorsKey: InjectionKey<Ref<ValidationErrors | undefined>>;
|
|
12
17
|
/** Without a dictionary the key itself shows — honest, and easy to spot in a screenshot. */
|
|
13
18
|
export declare const keyAsIs: Translate;
|
|
14
19
|
/** Translates a marked string; anything else — including `undefined` — passes through. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webx-ui/schema",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Screens as JSON for WebX UI admin panels: the node format, patches, the type registry and the renderer.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"vue": "^3.5.0"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@webx-ui/core": "^0.
|
|
47
|
+
"@webx-ui/core": "^0.33.0"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@types/node": "^24.10.1",
|