@stonecrop/desktop 0.30.0 → 0.32.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/README.md +1 -1
- package/dist/assets/index.css +394 -0
- package/dist/desktop.js +933 -833
- package/dist/desktop.js.map +1 -1
- package/dist/src/components/ActionSet.vue.d.ts +12 -0
- package/dist/src/components/ActionSet.vue.d.ts.map +1 -0
- package/dist/src/components/CommandPalette.vue.d.ts +35 -0
- package/dist/src/components/CommandPalette.vue.d.ts.map +1 -0
- package/dist/src/components/Desktop.vue.d.ts +26 -0
- package/dist/src/components/Desktop.vue.d.ts.map +1 -0
- package/dist/src/components/SheetNav.vue.d.ts +10 -0
- package/dist/src/components/SheetNav.vue.d.ts.map +1 -0
- package/dist/{tsdoc-metadata.json → src/tsdoc-metadata.json} +1 -1
- package/package.json +37 -31
- package/dist/desktop.css +0 -1
- package/dist/desktop.d.ts +0 -119
- package/dist/desktop.tsbuildinfo +0 -1
- package/dist/src/index.js +0 -6
- package/dist/src/plugins/index.js +0 -17
- package/dist/src/types/index.js +0 -0
- package/src/components/ActionSet.vue +0 -211
- package/src/components/CommandPalette.vue +0 -235
- package/src/components/Desktop.vue +0 -982
- package/src/components/SheetNav.vue +0 -297
- package/src/index.ts +0 -9
- package/src/plugins/index.ts +0 -21
- package/src/shims-vue.d.ts +0 -5
- package/src/types/index.ts +0 -107
package/dist/desktop.js
CHANGED
|
@@ -1,835 +1,935 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { AForm
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
}, tt = ["onClick", "onMouseover"], at = { class: "result-title" }, ot = { class: "result-content" }, rt = {
|
|
92
|
-
key: 1,
|
|
93
|
-
class: "command-palette-no-results"
|
|
94
|
-
}, fe = /* @__PURE__ */ q({
|
|
95
|
-
__name: "CommandPalette",
|
|
96
|
-
props: {
|
|
97
|
-
search: { type: Function },
|
|
98
|
-
isOpen: { type: Boolean, default: !1 },
|
|
99
|
-
placeholder: { default: "Type a command or search..." },
|
|
100
|
-
maxResults: { default: 10 }
|
|
101
|
-
},
|
|
102
|
-
emits: ["select", "close"],
|
|
103
|
-
setup(c, { emit: A }) {
|
|
104
|
-
const y = A, a = _(""), u = _(0), x = se("input"), w = R(() => a.value ? c.search(a.value).slice(0, c.maxResults) : []);
|
|
105
|
-
K(
|
|
106
|
-
() => c.isOpen,
|
|
107
|
-
async (v) => {
|
|
108
|
-
v && (a.value = "", u.value = 0, await ce(), x.value?.focus());
|
|
109
|
-
}
|
|
110
|
-
), K(w, () => {
|
|
111
|
-
u.value = 0;
|
|
112
|
-
});
|
|
113
|
-
const b = () => {
|
|
114
|
-
y("close");
|
|
115
|
-
}, S = (v) => {
|
|
116
|
-
switch (v.key) {
|
|
117
|
-
case "Escape":
|
|
118
|
-
b();
|
|
119
|
-
break;
|
|
120
|
-
case "ArrowDown":
|
|
121
|
-
v.preventDefault(), w.value.length && (u.value = (u.value + 1) % w.value.length);
|
|
122
|
-
break;
|
|
123
|
-
case "ArrowUp":
|
|
124
|
-
v.preventDefault(), w.value.length && (u.value = (u.value - 1 + w.value.length) % w.value.length);
|
|
125
|
-
break;
|
|
126
|
-
case "Enter":
|
|
127
|
-
w.value.length && u.value >= 0 && D(w.value[u.value]);
|
|
128
|
-
break;
|
|
129
|
-
}
|
|
130
|
-
}, D = (v) => {
|
|
131
|
-
y("select", v), b();
|
|
132
|
-
};
|
|
133
|
-
return (v, r) => (h(), ie(_e, { to: "body" }, [
|
|
134
|
-
B(xe, { name: "fade" }, {
|
|
135
|
-
default: j(() => [
|
|
136
|
-
c.isOpen ? (h(), g("div", {
|
|
137
|
-
key: 0,
|
|
138
|
-
class: "command-palette-overlay",
|
|
139
|
-
onClick: b
|
|
140
|
-
}, [
|
|
141
|
-
i("div", {
|
|
142
|
-
class: "command-palette",
|
|
143
|
-
onClick: r[1] || (r[1] = ue(() => {
|
|
144
|
-
}, ["stop"]))
|
|
145
|
-
}, [
|
|
146
|
-
i("div", Ye, [
|
|
147
|
-
z(i("input", {
|
|
148
|
-
ref: "input",
|
|
149
|
-
"onUpdate:modelValue": r[0] || (r[0] = (s) => a.value = s),
|
|
150
|
-
type: "text",
|
|
151
|
-
class: "command-palette-input",
|
|
152
|
-
placeholder: c.placeholder,
|
|
153
|
-
autofocus: "",
|
|
154
|
-
onKeydown: S
|
|
155
|
-
}, null, 40, Ze), [
|
|
156
|
-
[de, a.value]
|
|
157
|
-
])
|
|
158
|
-
]),
|
|
159
|
-
w.value.length ? (h(), g("div", et, [
|
|
160
|
-
(h(!0), g(H, null, U(w.value, (s, o) => (h(), g("div", {
|
|
161
|
-
key: o,
|
|
162
|
-
class: O(["command-palette-result", { selected: o === u.value }]),
|
|
163
|
-
onClick: (n) => D(s),
|
|
164
|
-
onMouseover: (n) => u.value = o
|
|
165
|
-
}, [
|
|
166
|
-
i("div", at, [
|
|
167
|
-
G(v.$slots, "title", { result: s })
|
|
168
|
-
]),
|
|
169
|
-
i("div", ot, [
|
|
170
|
-
G(v.$slots, "content", { result: s })
|
|
171
|
-
])
|
|
172
|
-
], 42, tt))), 128))
|
|
173
|
-
])) : a.value && !w.value.length ? (h(), g("div", rt, [
|
|
174
|
-
G(v.$slots, "empty", {}, () => [
|
|
175
|
-
W(' No results found for "' + N(a.value) + '" ', 1)
|
|
176
|
-
])
|
|
177
|
-
])) : P("", !0)
|
|
178
|
-
])
|
|
179
|
-
])) : P("", !0)
|
|
180
|
-
]),
|
|
181
|
-
_: 3
|
|
182
|
-
})
|
|
183
|
-
]));
|
|
184
|
-
}
|
|
185
|
-
}), nt = { class: "tabs" }, lt = { tabindex: "0" }, st = { tabindex: "0" }, ct = /* @__PURE__ */ q({
|
|
186
|
-
__name: "SheetNav",
|
|
187
|
-
props: {
|
|
188
|
-
breadcrumbs: { default: () => [] }
|
|
189
|
-
},
|
|
190
|
-
setup(c) {
|
|
191
|
-
const A = _(!0), y = _(!1), a = _(""), u = se("searchinput"), x = R(() => A.value ? "unrotated" : "rotated"), w = () => {
|
|
192
|
-
A.value = !A.value;
|
|
193
|
-
}, b = async () => {
|
|
194
|
-
y.value = !y.value, await ce(() => {
|
|
195
|
-
u.value?.focus();
|
|
196
|
-
});
|
|
197
|
-
}, S = (r) => {
|
|
198
|
-
r.preventDefault(), r.stopPropagation();
|
|
199
|
-
}, D = async (r) => {
|
|
200
|
-
r.preventDefault(), r.stopPropagation(), await b();
|
|
201
|
-
}, v = () => {
|
|
202
|
-
};
|
|
203
|
-
return (r, s) => {
|
|
204
|
-
const o = Ne("router-link");
|
|
205
|
-
return h(), g("footer", null, [
|
|
206
|
-
i("ul", nt, [
|
|
207
|
-
i("li", {
|
|
208
|
-
class: "hidebreadcrumbs",
|
|
209
|
-
onClick: w,
|
|
210
|
-
onKeydown: F(w, ["enter"])
|
|
211
|
-
}, [
|
|
212
|
-
i("a", lt, [
|
|
213
|
-
i("div", {
|
|
214
|
-
class: O(x.value)
|
|
215
|
-
}, "×", 2)
|
|
216
|
-
])
|
|
217
|
-
], 32),
|
|
218
|
-
i("li", {
|
|
219
|
-
class: "hometab",
|
|
220
|
-
style: J({ display: A.value ? "block" : "none" }),
|
|
221
|
-
onClick: v,
|
|
222
|
-
onKeydown: F(v, ["enter"])
|
|
223
|
-
}, [
|
|
224
|
-
B(o, {
|
|
225
|
-
to: "/",
|
|
226
|
-
tabindex: "0"
|
|
227
|
-
}, {
|
|
228
|
-
default: j(() => [...s[5] || (s[5] = [
|
|
229
|
-
i("svg", {
|
|
230
|
-
class: "icon",
|
|
231
|
-
"aria-label": "Home",
|
|
232
|
-
viewBox: "0 0 24 24",
|
|
233
|
-
fill: "none",
|
|
234
|
-
stroke: "currentColor",
|
|
235
|
-
"stroke-width": "2"
|
|
236
|
-
}, [
|
|
237
|
-
i("path", { d: "M3 12l9-9 9 9" }),
|
|
238
|
-
i("path", { d: "M9 21V12h6v9" })
|
|
239
|
-
], -1)
|
|
240
|
-
])]),
|
|
241
|
-
_: 1
|
|
242
|
-
})
|
|
243
|
-
], 36),
|
|
244
|
-
i("li", {
|
|
245
|
-
class: O(["searchtab", { "search-active": y.value }]),
|
|
246
|
-
style: J({ display: A.value ? "block" : "none" })
|
|
247
|
-
}, [
|
|
248
|
-
i("a", st, [
|
|
249
|
-
z((h(), g("svg", {
|
|
250
|
-
class: "icon search-icon",
|
|
251
|
-
role: "button",
|
|
252
|
-
"aria-label": "Search",
|
|
253
|
-
viewBox: "0 0 24 24",
|
|
254
|
-
fill: "none",
|
|
255
|
-
stroke: "currentColor",
|
|
256
|
-
"stroke-width": "2",
|
|
257
|
-
onClick: b,
|
|
258
|
-
onKeydown: F(b, ["enter"])
|
|
259
|
-
}, [...s[6] || (s[6] = [
|
|
260
|
-
i("circle", {
|
|
261
|
-
cx: "11",
|
|
262
|
-
cy: "11",
|
|
263
|
-
r: "7"
|
|
264
|
-
}, null, -1),
|
|
265
|
-
i("path", { d: "M21 21l-4.35-4.35" }, null, -1)
|
|
266
|
-
])], 544)), [
|
|
267
|
-
[Y, !y.value]
|
|
268
|
-
]),
|
|
269
|
-
z(i("input", {
|
|
270
|
-
ref: "searchinput",
|
|
271
|
-
"onUpdate:modelValue": s[0] || (s[0] = (n) => a.value = n),
|
|
272
|
-
type: "text",
|
|
273
|
-
placeholder: "Search...",
|
|
274
|
-
onClick: s[1] || (s[1] = ue(() => {
|
|
275
|
-
}, ["stop"])),
|
|
276
|
-
onInput: s[2] || (s[2] = (n) => S(n)),
|
|
277
|
-
onBlur: s[3] || (s[3] = (n) => D(n)),
|
|
278
|
-
onKeydown: [
|
|
279
|
-
s[4] || (s[4] = F((n) => D(n), ["enter"])),
|
|
280
|
-
F(b, ["escape"])
|
|
281
|
-
]
|
|
282
|
-
}, null, 544), [
|
|
283
|
-
[Y, y.value],
|
|
284
|
-
[de, a.value]
|
|
285
|
-
])
|
|
286
|
-
])
|
|
287
|
-
], 6),
|
|
288
|
-
(h(!0), g(H, null, U(c.breadcrumbs, (n) => (h(), g("li", {
|
|
289
|
-
key: n.title,
|
|
290
|
-
style: J({ display: A.value ? "block" : "none" })
|
|
291
|
-
}, [
|
|
292
|
-
B(o, {
|
|
293
|
-
tabindex: "0",
|
|
294
|
-
to: n.to
|
|
295
|
-
}, {
|
|
296
|
-
default: j(() => [
|
|
297
|
-
W(N(n.title), 1)
|
|
298
|
-
]),
|
|
299
|
-
_: 2
|
|
300
|
-
}, 1032, ["to"])
|
|
301
|
-
], 4))), 128))
|
|
302
|
-
])
|
|
303
|
-
]);
|
|
304
|
-
};
|
|
305
|
-
}
|
|
306
|
-
}), me = /* @__PURE__ */ ve(ct, [["__scopeId", "data-v-cd118b06"]]), it = {
|
|
307
|
-
key: 1,
|
|
308
|
-
class: "loading"
|
|
309
|
-
}, ut = {
|
|
310
|
-
key: 2,
|
|
311
|
-
class: "loading"
|
|
312
|
-
}, dt = /* @__PURE__ */ q({
|
|
313
|
-
__name: "Desktop",
|
|
314
|
-
props: {
|
|
315
|
-
availableDoctypes: { default: () => [] },
|
|
316
|
-
routeAdapter: {}
|
|
317
|
-
},
|
|
318
|
-
emits: ["action", "navigate", "record:open", "load-records", "load-record"],
|
|
319
|
-
setup(c, { emit: A }) {
|
|
320
|
-
const y = A, { stonecrop: a } = Te();
|
|
321
|
-
let u = null;
|
|
322
|
-
try {
|
|
323
|
-
u = Ve();
|
|
324
|
-
} catch {
|
|
325
|
-
u = null;
|
|
326
|
-
}
|
|
327
|
-
const x = R(
|
|
328
|
-
() => I.value === "record" ? u?.errorsByField ?? {} : {}
|
|
329
|
-
), w = _(!1), b = _(!1), S = _({}), D = R({
|
|
330
|
-
get() {
|
|
331
|
-
if (I.value === "doctypes")
|
|
332
|
-
return {
|
|
333
|
-
doctypes_table: c.availableDoctypes?.map((e) => ({
|
|
334
|
-
id: e,
|
|
335
|
-
doctype: e,
|
|
336
|
-
display_name: E(e),
|
|
337
|
-
actions: "View Records"
|
|
338
|
-
})) ?? []
|
|
339
|
-
};
|
|
340
|
-
if (I.value === "records")
|
|
341
|
-
return {
|
|
342
|
-
records_table: ae().map(
|
|
343
|
-
(e) => Object.assign({}, e, {
|
|
344
|
-
id: re(e) ?? "",
|
|
345
|
-
// A list row is navigation. Actions live on the record view, where the Actions
|
|
346
|
-
// dropdown is built from what the doctype declares and what the record's
|
|
347
|
-
// current state allows. This cell used to also offer Delete, which dispatched
|
|
348
|
-
// an action named `DELETE` that Desktop invented — no doctype in a
|
|
349
|
-
// WorkflowMeta app declares it, so it failed on every click. Removal is a
|
|
350
|
-
// workflow outcome (`archive`, `cancel`) and belongs in the doctype.
|
|
351
|
-
actions: "Edit"
|
|
352
|
-
})
|
|
353
|
-
)
|
|
354
|
-
};
|
|
355
|
-
if (!a.value || !o.value || !m.value)
|
|
356
|
-
return {};
|
|
357
|
-
try {
|
|
358
|
-
const t = { ...V.value ? S.value : a.value.getRecordById(o.value, m.value)?.get("") }, l = a.value.registry.registry[o.value];
|
|
359
|
-
if (l) {
|
|
360
|
-
for (const d of l.getSchemaArray())
|
|
361
|
-
if (d.kind === "fieldset") {
|
|
362
|
-
const p = {};
|
|
363
|
-
for (const k of d.schema)
|
|
364
|
-
k.fieldname && (p[k.fieldname] = t[k.fieldname]);
|
|
365
|
-
t[d.fieldname] = p;
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
return t;
|
|
369
|
-
} catch {
|
|
370
|
-
return {};
|
|
371
|
-
}
|
|
372
|
-
},
|
|
373
|
-
set(e) {
|
|
374
|
-
if (I.value === "record" && !(!a.value || !o.value || !m.value))
|
|
375
|
-
try {
|
|
376
|
-
const t = a.value.registry.registry[o.value], l = /* @__PURE__ */ new Set();
|
|
377
|
-
if (t)
|
|
378
|
-
for (const f of t.getSchemaArray())
|
|
379
|
-
f.kind === "fieldset" && l.add(f.fieldname);
|
|
380
|
-
const d = {}, p = [];
|
|
381
|
-
for (const [f, C] of Object.entries(e))
|
|
382
|
-
l.has(f) && C && typeof C == "object" && !Array.isArray(C) ? p.push(C) : d[f] = C;
|
|
383
|
-
for (const f of p)
|
|
384
|
-
Object.assign(d, f);
|
|
385
|
-
const k = [];
|
|
386
|
-
if (V.value) {
|
|
387
|
-
const f = { ...S.value };
|
|
388
|
-
for (const [C, $] of Object.entries(d))
|
|
389
|
-
$ !== void 0 && f[C] !== $ && (f[C] = $, k.push(C));
|
|
390
|
-
S.value = f;
|
|
391
|
-
} else {
|
|
392
|
-
const f = a.value.getStore();
|
|
393
|
-
for (const [C, $] of Object.entries(d)) {
|
|
394
|
-
if ($ === void 0) continue;
|
|
395
|
-
const T = `${o.value}.${m.value}.${C}`;
|
|
396
|
-
(f.has(T) ? f.get(T) : void 0) !== $ && (f.set(T, $), k.push(C));
|
|
397
|
-
}
|
|
398
|
-
}
|
|
399
|
-
k.length > 0 && v(k);
|
|
400
|
-
} catch (t) {
|
|
401
|
-
console.warn("HST update failed:", t);
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
});
|
|
405
|
-
function v(e) {
|
|
406
|
-
if (!u || !a.value || !o.value || !m.value) return;
|
|
407
|
-
const l = a.value.registry.getDoctype(o.value)?.getTriggers();
|
|
408
|
-
if (!l || Object.keys(l).length === 0) return;
|
|
409
|
-
const d = V.value ? { ...S.value } : {
|
|
410
|
-
...a.value.getRecordById(o.value, m.value)?.get("")
|
|
411
|
-
};
|
|
412
|
-
for (const p of e)
|
|
413
|
-
u.validateField(l, p, d);
|
|
414
|
-
}
|
|
415
|
-
const r = R(() => c.routeAdapter ? null : Q(a.value?.registry.router?.currentRoute)), s = R(() => c.routeAdapter ? null : a.value?.registry.router), o = R(() => {
|
|
416
|
-
if (c.routeAdapter) return c.routeAdapter.getCurrentDoctype();
|
|
417
|
-
if (!r.value) return "";
|
|
418
|
-
if (r.value.meta?.actualDoctype)
|
|
419
|
-
return r.value.meta.actualDoctype;
|
|
420
|
-
if (r.value.params.doctype)
|
|
421
|
-
return r.value.params.doctype.toString();
|
|
422
|
-
const e = r.value.params.pathMatch;
|
|
423
|
-
return e && e.length > 0 ? e[0] : "";
|
|
424
|
-
}), n = R(() => {
|
|
425
|
-
if (c.routeAdapter) return c.routeAdapter.getCurrentDoctype();
|
|
426
|
-
if (!r.value) return "";
|
|
427
|
-
if (r.value.meta?.doctype)
|
|
428
|
-
return r.value.meta.doctype;
|
|
429
|
-
if (r.value.params.doctype)
|
|
430
|
-
return r.value.params.doctype.toString();
|
|
431
|
-
const e = r.value.params.pathMatch;
|
|
432
|
-
return e && e.length > 0 ? e[0] : "";
|
|
433
|
-
}), m = R(() => {
|
|
434
|
-
if (c.routeAdapter) return c.routeAdapter.getCurrentRecordId();
|
|
435
|
-
if (!r.value) return "";
|
|
436
|
-
if (r.value.params.recordId)
|
|
437
|
-
return r.value.params.recordId.toString();
|
|
438
|
-
const e = r.value.params.pathMatch;
|
|
439
|
-
return e && e.length > 1 ? e[1] : "";
|
|
440
|
-
}), V = R(() => Ee(m.value)), I = R(() => {
|
|
441
|
-
if (c.routeAdapter) return c.routeAdapter.getCurrentView();
|
|
442
|
-
if (!r.value || r.value.name === "home" || r.value.path === "/")
|
|
443
|
-
return "doctypes";
|
|
444
|
-
if (r.value.name && r.value.name !== "catch-all") {
|
|
445
|
-
const t = r.value.name;
|
|
446
|
-
if (t.includes("form") || r.value.params.recordId)
|
|
447
|
-
return "record";
|
|
448
|
-
if (t.includes("list") || r.value.params.doctype)
|
|
449
|
-
return "records";
|
|
450
|
-
}
|
|
451
|
-
const e = r.value.params.pathMatch;
|
|
452
|
-
return e && e.length > 0 ? e.length === 1 ? "records" : "record" : "doctypes";
|
|
453
|
-
}), he = () => {
|
|
454
|
-
if (!a.value || !o.value || !m.value)
|
|
455
|
-
return [];
|
|
456
|
-
try {
|
|
457
|
-
const e = a.value.registry.getDoctype(o.value);
|
|
458
|
-
if (!e?.workflow) return [];
|
|
459
|
-
const t = a.value.getRecordState(o.value, m.value), l = e.getAvailableTransitions(t), d = D.value || {};
|
|
460
|
-
return l.map(({ name: p }) => ({
|
|
461
|
-
// Prefer the workflow action's human-readable label (WorkflowMeta format);
|
|
462
|
-
// fall back to the raw transition name for XState workflows with no action meta.
|
|
463
|
-
label: e.getActionMeta(p)?.label ?? p,
|
|
464
|
-
action: () => {
|
|
465
|
-
y("action", {
|
|
466
|
-
name: p,
|
|
467
|
-
doctype: o.value,
|
|
468
|
-
recordId: m.value,
|
|
469
|
-
data: d
|
|
470
|
-
});
|
|
471
|
-
}
|
|
472
|
-
}));
|
|
473
|
-
} catch (e) {
|
|
474
|
-
return console.warn("Error getting available transitions:", e), [];
|
|
475
|
-
}
|
|
476
|
-
}, ye = () => {
|
|
477
|
-
if (!a.value || !o.value || !m.value)
|
|
478
|
-
return [];
|
|
479
|
-
try {
|
|
480
|
-
const e = a.value.registry.getDoctype(o.value);
|
|
481
|
-
if (!e?.workflow) return [];
|
|
482
|
-
const t = a.value.getRecordState(o.value, m.value), l = e.getAvailableCommands(t), d = D.value || {};
|
|
483
|
-
return l.map(({ name: p }) => ({
|
|
484
|
-
label: e.getActionMeta(p)?.label ?? p,
|
|
485
|
-
action: () => {
|
|
486
|
-
y("action", {
|
|
487
|
-
name: p,
|
|
488
|
-
doctype: o.value,
|
|
489
|
-
recordId: m.value,
|
|
490
|
-
data: d
|
|
491
|
-
});
|
|
492
|
-
}
|
|
493
|
-
}));
|
|
494
|
-
} catch (e) {
|
|
495
|
-
return console.warn("Error getting available commands:", e), [];
|
|
496
|
-
}
|
|
497
|
-
}, ge = R(() => {
|
|
498
|
-
const e = [];
|
|
499
|
-
switch (I.value) {
|
|
500
|
-
case "records":
|
|
501
|
-
e.push({
|
|
502
|
-
type: "button",
|
|
503
|
-
label: "New Record",
|
|
504
|
-
action: () => {
|
|
505
|
-
L();
|
|
506
|
-
}
|
|
507
|
-
});
|
|
508
|
-
break;
|
|
509
|
-
case "record": {
|
|
510
|
-
const t = [...he(), ...ye()];
|
|
511
|
-
t.length > 0 && e.push({
|
|
512
|
-
type: "dropdown",
|
|
513
|
-
label: "Actions",
|
|
514
|
-
actions: t
|
|
515
|
-
});
|
|
516
|
-
break;
|
|
517
|
-
}
|
|
518
|
-
}
|
|
519
|
-
return e;
|
|
520
|
-
}), we = R(() => {
|
|
521
|
-
const e = [];
|
|
522
|
-
if (I.value === "records" && n.value)
|
|
523
|
-
e.push(
|
|
524
|
-
{ title: "Home", to: "/" },
|
|
525
|
-
{ title: E(n.value), to: `/${n.value}` }
|
|
526
|
-
);
|
|
527
|
-
else if (I.value === "record" && n.value) {
|
|
528
|
-
const t = m.value ? `/${n.value}/${m.value}` : r.value?.fullPath ?? "";
|
|
529
|
-
e.push(
|
|
530
|
-
{ title: "Home", to: "/" },
|
|
531
|
-
{ title: E(n.value), to: `/${n.value}` },
|
|
532
|
-
{ title: V.value ? "New Record" : "Edit Record", to: t }
|
|
533
|
-
);
|
|
534
|
-
}
|
|
535
|
-
return e;
|
|
536
|
-
}), be = (e) => {
|
|
537
|
-
const t = [
|
|
538
|
-
{
|
|
539
|
-
title: "Go Home",
|
|
540
|
-
description: "Navigate to the home page",
|
|
541
|
-
action: () => {
|
|
542
|
-
M({ view: "doctypes" });
|
|
543
|
-
}
|
|
544
|
-
},
|
|
545
|
-
{
|
|
546
|
-
title: "Toggle Command Palette",
|
|
547
|
-
description: "Open/close the command palette",
|
|
548
|
-
action: () => b.value = !b.value
|
|
549
|
-
}
|
|
550
|
-
];
|
|
551
|
-
return n.value && (t.push({
|
|
552
|
-
title: `View ${E(n.value)} Records`,
|
|
553
|
-
description: `Navigate to ${n.value} list`,
|
|
554
|
-
action: () => {
|
|
555
|
-
M({ view: "records", doctype: n.value });
|
|
556
|
-
}
|
|
557
|
-
}), t.push({
|
|
558
|
-
title: `Create New ${E(n.value)}`,
|
|
559
|
-
description: `Create a new ${n.value} record`,
|
|
560
|
-
action: () => {
|
|
561
|
-
L();
|
|
562
|
-
}
|
|
563
|
-
})), c.availableDoctypes.forEach((l) => {
|
|
564
|
-
t.push({
|
|
565
|
-
title: `View ${E(l)}`,
|
|
566
|
-
description: `Navigate to ${l} list`,
|
|
567
|
-
action: () => {
|
|
568
|
-
M({ view: "records", doctype: l });
|
|
569
|
-
}
|
|
570
|
-
});
|
|
571
|
-
}), e ? t.filter(
|
|
572
|
-
(l) => l.title.toLowerCase().includes(e.toLowerCase()) || l.description.toLowerCase().includes(e.toLowerCase())
|
|
573
|
-
) : t;
|
|
574
|
-
}, ke = (e) => {
|
|
575
|
-
e.action(), b.value = !1;
|
|
576
|
-
}, Ce = (e) => {
|
|
577
|
-
if (!a.value || !o.value)
|
|
578
|
-
return Promise.resolve({ data: [], hasMore: !1 });
|
|
579
|
-
const t = a.value.registry.getDoctype(o.value);
|
|
580
|
-
return t ? a.value.getRecords(t, e) : Promise.resolve({ data: [], hasMore: !1 });
|
|
581
|
-
}, E = (e) => e.split("-").map((t) => t.charAt(0).toUpperCase() + t.slice(1)).join(" "), M = async (e) => {
|
|
582
|
-
y("navigate", e), c.routeAdapter ? await c.routeAdapter.navigate(e) : e.view === "doctypes" ? await s.value?.push("/") : e.view === "records" && e.doctype ? await s.value?.push(`/${e.doctype}`) : e.view === "record" && e.doctype && e.recordId && await s.value?.push(`/${e.doctype}/${e.recordId}`);
|
|
583
|
-
}, Z = async (e) => {
|
|
584
|
-
await M({ view: "records", doctype: e });
|
|
585
|
-
}, ee = async (e) => {
|
|
586
|
-
const t = n.value;
|
|
587
|
-
y("record:open", { doctype: t, recordId: e }), await M({ view: "record", doctype: t, recordId: e });
|
|
588
|
-
}, L = async () => {
|
|
589
|
-
await M({ view: "record", doctype: n.value, recordId: Oe });
|
|
590
|
-
}, Ae = () => c.availableDoctypes?.length ? [
|
|
591
|
-
{
|
|
592
|
-
kind: "table",
|
|
593
|
-
fieldname: "doctypes_table",
|
|
594
|
-
component: "ATable",
|
|
595
|
-
label: "Doctypes",
|
|
596
|
-
schema: [
|
|
597
|
-
{
|
|
598
|
-
fieldname: "doctype",
|
|
599
|
-
label: "Doctype",
|
|
600
|
-
component: "ATextInput",
|
|
601
|
-
align: "left",
|
|
602
|
-
edit: !1,
|
|
603
|
-
width: "20ch"
|
|
604
|
-
},
|
|
605
|
-
{
|
|
606
|
-
fieldname: "display_name",
|
|
607
|
-
label: "Name",
|
|
608
|
-
component: "ATextInput",
|
|
609
|
-
align: "left",
|
|
610
|
-
edit: !1,
|
|
611
|
-
width: "30ch"
|
|
612
|
-
},
|
|
613
|
-
// No record count column. It read `getRecordIds(doctype).length`, which is how many
|
|
614
|
-
// records HST happens to hold — zero for a doctype never opened, and the page size
|
|
615
|
-
// for one that was. The real total belongs to the backend and Desktop never asks
|
|
616
|
-
// for it, so this shell cannot answer it. Same reason the `recordIdField` prop went.
|
|
617
|
-
{
|
|
618
|
-
fieldname: "actions",
|
|
619
|
-
label: "Actions",
|
|
620
|
-
component: "ATextInput",
|
|
621
|
-
align: "center",
|
|
622
|
-
edit: !1,
|
|
623
|
-
width: "20ch"
|
|
624
|
-
}
|
|
625
|
-
],
|
|
626
|
-
config: { view: "list", fullWidth: !0 }
|
|
627
|
-
}
|
|
628
|
-
] : [], De = () => {
|
|
629
|
-
if (!o.value) return [];
|
|
630
|
-
if (!a.value) return [];
|
|
631
|
-
const e = a.value.registry, t = e.registry[o.value];
|
|
632
|
-
if (!t) return [];
|
|
633
|
-
const l = e.resolveSchema(t);
|
|
634
|
-
if (l.length === 0) return [];
|
|
635
|
-
const d = o.value, p = !!a.value.getClient();
|
|
636
|
-
return [
|
|
637
|
-
{
|
|
638
|
-
kind: "table",
|
|
639
|
-
fieldname: "records_table",
|
|
640
|
-
component: "ATable",
|
|
641
|
-
// Which resolved fields a cell can render is answered once, in @stonecrop/aform, and
|
|
642
|
-
// called by the child-table builder too. Flattening alone is not the rule: it kept the
|
|
643
|
-
// expanding links, whose value is a nested record or an array of them.
|
|
644
|
-
schema: [...Fe(l), { fieldname: "actions", label: "Actions", component: "ATextInput" }],
|
|
645
|
-
config: { view: "list", fullWidth: !0 },
|
|
646
|
-
...p ? { getRecords: Ce, sourceKey: d } : {}
|
|
647
|
-
}
|
|
648
|
-
];
|
|
649
|
-
}, te = () => {
|
|
650
|
-
if (!o.value) return [];
|
|
651
|
-
if (!a.value) return [];
|
|
652
|
-
try {
|
|
653
|
-
const e = a.value?.registry, t = e?.registry[o.value];
|
|
654
|
-
return t?.schema ? e.resolveSchema(t) : [];
|
|
655
|
-
} catch {
|
|
656
|
-
return [];
|
|
657
|
-
}
|
|
658
|
-
}, ae = () => {
|
|
659
|
-
if (!a.value || !o.value)
|
|
660
|
-
return [];
|
|
661
|
-
const t = a.value.records(o.value)?.get("");
|
|
662
|
-
return t && typeof t == "object" && !Array.isArray(t) ? Object.values(t) : [];
|
|
663
|
-
}, oe = R(() => {
|
|
664
|
-
switch (I.value) {
|
|
665
|
-
case "doctypes":
|
|
666
|
-
return Ae();
|
|
667
|
-
case "records":
|
|
668
|
-
return De();
|
|
669
|
-
case "record":
|
|
670
|
-
return te();
|
|
671
|
-
default:
|
|
672
|
-
return [];
|
|
673
|
-
}
|
|
674
|
-
}), Re = (e, t) => {
|
|
675
|
-
t && t();
|
|
676
|
-
}, re = (e) => {
|
|
677
|
-
if (!(!a.value || !o.value))
|
|
678
|
-
return a.value.registry.registry[o.value]?.getRecordId(e);
|
|
679
|
-
}, Se = (e) => {
|
|
680
|
-
const t = e.querySelector("td[data-rowindex]");
|
|
681
|
-
if (!t) return null;
|
|
682
|
-
const l = t.getAttribute("data-rowindex");
|
|
683
|
-
if (l === null) return null;
|
|
684
|
-
const d = parseInt(l, 10);
|
|
685
|
-
if (isNaN(d)) return null;
|
|
686
|
-
const k = ae()[d];
|
|
687
|
-
return k ? re(k) ?? null : null;
|
|
688
|
-
}, $e = async (e) => {
|
|
689
|
-
const t = e.target;
|
|
690
|
-
t.getAttribute("data-action") === "create" && await L();
|
|
691
|
-
const d = t.closest("td, th");
|
|
692
|
-
if (d) {
|
|
693
|
-
const p = d.textContent?.trim(), k = d.closest("tr");
|
|
694
|
-
if (p === "View Records" && k) {
|
|
695
|
-
const f = k.querySelectorAll("td");
|
|
696
|
-
if (f.length > 0) {
|
|
697
|
-
const $ = f[1].textContent?.trim();
|
|
698
|
-
$ && await Z($);
|
|
699
|
-
}
|
|
700
|
-
} else if (p === "Edit" && k) {
|
|
701
|
-
const f = Se(k);
|
|
702
|
-
f && await ee(f);
|
|
703
|
-
}
|
|
704
|
-
}
|
|
705
|
-
}, Ie = async () => {
|
|
706
|
-
if (!(!a.value || !o.value || !a.value.getClient())) {
|
|
707
|
-
w.value = !0;
|
|
708
|
-
try {
|
|
709
|
-
await a.value.getRecord(o.value, m.value);
|
|
710
|
-
} catch (e) {
|
|
711
|
-
console.warn("Error fetching record:", e);
|
|
712
|
-
} finally {
|
|
713
|
-
w.value = !1;
|
|
714
|
-
}
|
|
715
|
-
}
|
|
716
|
-
};
|
|
717
|
-
K(
|
|
718
|
-
[I, o, m],
|
|
719
|
-
() => {
|
|
720
|
-
if (I.value === "records" && o.value)
|
|
721
|
-
y("load-records", { doctype: o.value });
|
|
722
|
-
else if (I.value === "record" && o.value && m.value) {
|
|
723
|
-
if (V.value) return;
|
|
724
|
-
y("load-record", { doctype: o.value, recordId: m.value }), Ie();
|
|
725
|
-
}
|
|
726
|
-
},
|
|
727
|
-
{ immediate: !0 }
|
|
728
|
-
), K([o, m], () => {
|
|
729
|
-
u?.clearAll();
|
|
730
|
-
}), K(
|
|
731
|
-
[o, m],
|
|
732
|
-
() => {
|
|
733
|
-
if (!V.value) {
|
|
734
|
-
S.value = {};
|
|
735
|
-
return;
|
|
736
|
-
}
|
|
737
|
-
const e = a.value?.registry;
|
|
738
|
-
S.value = e ? e.initializeRecord(te()) : {};
|
|
739
|
-
},
|
|
740
|
-
{ immediate: !0 }
|
|
741
|
-
), X("desktopMethods", {
|
|
742
|
-
navigateToDoctype: Z,
|
|
743
|
-
openRecord: ee,
|
|
744
|
-
createNewRecord: L,
|
|
745
|
-
/**
|
|
746
|
-
* Convenience wrapper so child components (e.g. slot content) can emit
|
|
747
|
-
* an action event without needing a direct reference to the emit function.
|
|
748
|
-
*/
|
|
749
|
-
emitAction: (e, t) => {
|
|
750
|
-
y("action", {
|
|
751
|
-
name: e,
|
|
752
|
-
doctype: o.value,
|
|
753
|
-
recordId: m.value,
|
|
754
|
-
data: t ?? D.value ?? {}
|
|
755
|
-
});
|
|
756
|
-
}
|
|
757
|
-
}), X("aformLinkNavigator", {
|
|
758
|
-
navigate: (e, t) => {
|
|
759
|
-
M({ view: "record", doctype: e, recordId: String(t) });
|
|
760
|
-
}
|
|
761
|
-
}), X("aformLinkResolver", async (e, t) => {
|
|
762
|
-
if (a.value)
|
|
763
|
-
try {
|
|
764
|
-
const d = (await a.value.getMeta({ path: `/${e}`, segments: [e] }))?.displayField;
|
|
765
|
-
if (!d) return;
|
|
766
|
-
const p = ($) => {
|
|
767
|
-
if (!$) return;
|
|
768
|
-
const T = $[d];
|
|
769
|
-
return typeof T == "string" || typeof T == "number" ? String(T) : void 0;
|
|
770
|
-
}, k = a.value.getRecordById(e, t)?.get(""), f = p(k);
|
|
771
|
-
if (f != null) return f;
|
|
772
|
-
await a.value.getRecord(e, t);
|
|
773
|
-
const C = a.value.getRecordById(e, t)?.get("");
|
|
774
|
-
return p(C);
|
|
775
|
-
} catch {
|
|
776
|
-
return;
|
|
777
|
-
}
|
|
778
|
-
});
|
|
779
|
-
const ne = (e) => {
|
|
780
|
-
(e.ctrlKey || e.metaKey) && e.key === "k" && (e.preventDefault(), b.value = !0), e.key === "Escape" && b.value && (b.value = !1);
|
|
781
|
-
};
|
|
782
|
-
return le(() => {
|
|
783
|
-
document.addEventListener("keydown", ne);
|
|
784
|
-
}), Me(() => {
|
|
785
|
-
document.removeEventListener("keydown", ne);
|
|
786
|
-
}), (e, t) => (h(), g("div", {
|
|
787
|
-
class: "desktop",
|
|
788
|
-
onClick: $e
|
|
789
|
-
}, [
|
|
790
|
-
B(pe, {
|
|
791
|
-
elements: ge.value,
|
|
792
|
-
onActionClick: Re
|
|
793
|
-
}, null, 8, ["elements"]),
|
|
794
|
-
oe.value.length > 0 ? (h(), ie(Q(Be), {
|
|
795
|
-
key: 0,
|
|
796
|
-
data: D.value,
|
|
797
|
-
"onUpdate:data": t[0] || (t[0] = (l) => D.value = l),
|
|
798
|
-
schema: oe.value,
|
|
799
|
-
errors: x.value
|
|
800
|
-
}, null, 8, ["data", "schema", "errors"])) : Q(a) ? (h(), g("div", ut, [
|
|
801
|
-
i("p", null, "Loading " + N(I.value) + " data...", 1)
|
|
802
|
-
])) : (h(), g("div", it, [...t[2] || (t[2] = [
|
|
803
|
-
i("p", null, "Initializing Stonecrop...", -1)
|
|
804
|
-
])])),
|
|
805
|
-
B(me, { breadcrumbs: we.value }, null, 8, ["breadcrumbs"]),
|
|
806
|
-
B(fe, {
|
|
807
|
-
"is-open": b.value,
|
|
808
|
-
search: be,
|
|
809
|
-
placeholder: "Type a command or search...",
|
|
810
|
-
onSelect: ke,
|
|
811
|
-
onClose: t[1] || (t[1] = (l) => b.value = !1)
|
|
812
|
-
}, {
|
|
813
|
-
title: j(({ result: l }) => [
|
|
814
|
-
W(N(l.title), 1)
|
|
815
|
-
]),
|
|
816
|
-
content: j(({ result: l }) => [
|
|
817
|
-
W(N(l.description), 1)
|
|
818
|
-
]),
|
|
819
|
-
_: 1
|
|
820
|
-
}, 8, ["is-open"])
|
|
821
|
-
]));
|
|
822
|
-
}
|
|
823
|
-
}), yt = {
|
|
824
|
-
install: (c) => {
|
|
825
|
-
c.component("ActionSet", pe), c.component("CommandPalette", fe), c.component("Desktop", dt), c.component("SheetNav", me);
|
|
826
|
-
}
|
|
1
|
+
import { Fragment, Teleport, Transition, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, nextTick, normalizeClass, normalizeStyle, onMounted, onUnmounted, openBlock, provide, ref, renderList, renderSlot, resolveComponent, toDisplayString, unref, useTemplateRef, vModelText, vShow, watch, withCtx, withDirectives, withKeys, withModifiers } from "vue";
|
|
2
|
+
import { DRAFT_RECORD_ID, isDraftRecordId, useStonecrop, useValidationStore } from "@stonecrop/stonecrop";
|
|
3
|
+
import { AForm, resolvedFieldsToColumns } from "@stonecrop/aform";
|
|
4
|
+
import './assets/index.css';//#region src/components/ActionSet.vue?vue&type=script&setup=true&lang.ts
|
|
5
|
+
var _hoisted_1$3 = { class: "action-menu-icon" };
|
|
6
|
+
var _hoisted_2$3 = { class: "action-element-header" };
|
|
7
|
+
var _hoisted_3$2 = ["disabled", "onClick"];
|
|
8
|
+
var _hoisted_4$1 = { key: 0 };
|
|
9
|
+
var _hoisted_5$1 = { class: "dropdown-header" };
|
|
10
|
+
var _hoisted_6$1 = ["onClick"];
|
|
11
|
+
var _hoisted_7$1 = ["onClick"];
|
|
12
|
+
var _hoisted_8 = { class: "dropdown-container" };
|
|
13
|
+
var _hoisted_9 = { class: "dropdown" };
|
|
14
|
+
var _hoisted_10 = ["onClick"];
|
|
15
|
+
var _hoisted_11 = ["href"];
|
|
16
|
+
var _hoisted_12 = { class: "dropdown-item" };
|
|
17
|
+
var ActionSet_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
|
|
18
|
+
__name: "ActionSet",
|
|
19
|
+
props: { elements: { default: () => [] } },
|
|
20
|
+
emits: ["actionClick"],
|
|
21
|
+
setup(__props, { emit: __emit }) {
|
|
22
|
+
const emit = __emit;
|
|
23
|
+
const dropdownStates = ref({});
|
|
24
|
+
const isOpen = ref(true);
|
|
25
|
+
const dropdownOpen = ref([]);
|
|
26
|
+
onMounted(() => {
|
|
27
|
+
closeDropdowns();
|
|
28
|
+
});
|
|
29
|
+
const closeDropdowns = () => {
|
|
30
|
+
dropdownStates.value = {};
|
|
31
|
+
dropdownOpen.value = [];
|
|
32
|
+
};
|
|
33
|
+
const onClick = () => {
|
|
34
|
+
isOpen.value = !isOpen.value;
|
|
35
|
+
};
|
|
36
|
+
const toggleDropdown = (index) => {
|
|
37
|
+
const showDropdown = !dropdownStates.value[index];
|
|
38
|
+
closeDropdowns();
|
|
39
|
+
if (showDropdown) {
|
|
40
|
+
dropdownStates.value[index] = true;
|
|
41
|
+
dropdownOpen.value[index] = true;
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
const handleClick = (action, label) => {
|
|
45
|
+
emit("actionClick", label, action);
|
|
46
|
+
};
|
|
47
|
+
return (_ctx, _cache) => {
|
|
48
|
+
return openBlock(), createElementBlock("div", { class: normalizeClass([{ collapsed: !isOpen.value }, "action-set"]) }, [
|
|
49
|
+
createElementVNode("div", _hoisted_1$3, [createElementVNode("div", {
|
|
50
|
+
id: "cross",
|
|
51
|
+
class: normalizeClass({ rotated: isOpen.value }),
|
|
52
|
+
onClick
|
|
53
|
+
}, "×", 2)]),
|
|
54
|
+
_cache[0] || (_cache[0] = createElementVNode("div", { style: { "margin-right": "30px" } }, null, -1)),
|
|
55
|
+
(openBlock(true), createElementBlock(Fragment, null, renderList(__props.elements, (el, index) => {
|
|
56
|
+
return openBlock(), createElementBlock("div", {
|
|
57
|
+
key: el.label,
|
|
58
|
+
class: "action-element"
|
|
59
|
+
}, [createElementVNode("div", _hoisted_2$3, [el.type == "button" ? (openBlock(), createElementBlock("button", {
|
|
60
|
+
key: 0,
|
|
61
|
+
disabled: el.disabled,
|
|
62
|
+
class: "button-default",
|
|
63
|
+
onClick: ($event) => handleClick(el.action, el.label)
|
|
64
|
+
}, toDisplayString(el.label), 9, _hoisted_3$2)) : createCommentVNode("", true)]), el.type == "dropdown" ? (openBlock(), createElementBlock("div", _hoisted_4$1, [createElementVNode("div", _hoisted_5$1, [createElementVNode("div", {
|
|
65
|
+
class: normalizeClass(["cross", { rotated: dropdownOpen.value[index] }]),
|
|
66
|
+
onClick: ($event) => toggleDropdown(index)
|
|
67
|
+
}, "×", 10, _hoisted_6$1), createElementVNode("button", {
|
|
68
|
+
class: "button-default dropdown-title",
|
|
69
|
+
onClick: ($event) => toggleDropdown(index)
|
|
70
|
+
}, toDisplayString(el.label), 9, _hoisted_7$1)]), withDirectives(createElementVNode("div", _hoisted_8, [createElementVNode("div", _hoisted_9, [(openBlock(true), createElementBlock(Fragment, null, renderList(el.actions, (item) => {
|
|
71
|
+
return openBlock(), createElementBlock("div", { key: item.label }, [item.action != null ? (openBlock(), createElementBlock("button", {
|
|
72
|
+
key: 0,
|
|
73
|
+
class: "dropdown-item",
|
|
74
|
+
onClick: ($event) => handleClick(item.action, item.label)
|
|
75
|
+
}, toDisplayString(item.label), 9, _hoisted_10)) : item.link != null ? (openBlock(), createElementBlock("a", {
|
|
76
|
+
key: 1,
|
|
77
|
+
href: item.link
|
|
78
|
+
}, [createElementVNode("button", _hoisted_12, toDisplayString(item.label), 1)], 8, _hoisted_11)) : createCommentVNode("", true)]);
|
|
79
|
+
}), 128))])], 512), [[vShow, dropdownStates.value[index]]])])) : createCommentVNode("", true)]);
|
|
80
|
+
}), 128))
|
|
81
|
+
], 2);
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
//#endregion
|
|
86
|
+
//#region \0plugin-vue:export-helper
|
|
87
|
+
var _plugin_vue_export_helper_default = (sfc, props) => {
|
|
88
|
+
const target = sfc.__vccOpts || sfc;
|
|
89
|
+
for (const [key, val] of props) target[key] = val;
|
|
90
|
+
return target;
|
|
827
91
|
};
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
92
|
+
//#endregion
|
|
93
|
+
//#region src/components/ActionSet.vue
|
|
94
|
+
var ActionSet_default = /*#__PURE__*/ _plugin_vue_export_helper_default(ActionSet_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-8e18f635"]]);
|
|
95
|
+
//#endregion
|
|
96
|
+
//#region src/components/CommandPalette.vue?vue&type=script&setup=true&lang.ts
|
|
97
|
+
var _hoisted_1$2 = { class: "command-palette-header" };
|
|
98
|
+
var _hoisted_2$2 = ["placeholder"];
|
|
99
|
+
var _hoisted_3$1 = {
|
|
100
|
+
key: 0,
|
|
101
|
+
class: "command-palette-results"
|
|
834
102
|
};
|
|
835
|
-
|
|
103
|
+
var _hoisted_4 = ["onClick", "onMouseover"];
|
|
104
|
+
var _hoisted_5 = { class: "result-title" };
|
|
105
|
+
var _hoisted_6 = { class: "result-content" };
|
|
106
|
+
var _hoisted_7 = {
|
|
107
|
+
key: 1,
|
|
108
|
+
class: "command-palette-no-results"
|
|
109
|
+
};
|
|
110
|
+
//#endregion
|
|
111
|
+
//#region src/components/CommandPalette.vue
|
|
112
|
+
var CommandPalette_default = /* @__PURE__ */ defineComponent({
|
|
113
|
+
__name: "CommandPalette",
|
|
114
|
+
props: {
|
|
115
|
+
search: { type: Function },
|
|
116
|
+
isOpen: {
|
|
117
|
+
type: Boolean,
|
|
118
|
+
default: false
|
|
119
|
+
},
|
|
120
|
+
placeholder: { default: "Type a command or search..." },
|
|
121
|
+
maxResults: { default: 10 }
|
|
122
|
+
},
|
|
123
|
+
emits: ["select", "close"],
|
|
124
|
+
setup(__props, { emit: __emit }) {
|
|
125
|
+
const emit = __emit;
|
|
126
|
+
const query = ref("");
|
|
127
|
+
const selectedIndex = ref(0);
|
|
128
|
+
const inputRef = useTemplateRef("input");
|
|
129
|
+
const results = computed(() => {
|
|
130
|
+
if (!query.value) return [];
|
|
131
|
+
return __props.search(query.value).slice(0, __props.maxResults);
|
|
132
|
+
});
|
|
133
|
+
watch(() => __props.isOpen, async (open) => {
|
|
134
|
+
if (open) {
|
|
135
|
+
query.value = "";
|
|
136
|
+
selectedIndex.value = 0;
|
|
137
|
+
await nextTick();
|
|
138
|
+
inputRef.value?.focus();
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
watch(results, () => {
|
|
142
|
+
selectedIndex.value = 0;
|
|
143
|
+
});
|
|
144
|
+
const closeModal = () => {
|
|
145
|
+
emit("close");
|
|
146
|
+
};
|
|
147
|
+
const handleKeydown = (e) => {
|
|
148
|
+
switch (e.key) {
|
|
149
|
+
case "Escape":
|
|
150
|
+
closeModal();
|
|
151
|
+
break;
|
|
152
|
+
case "ArrowDown":
|
|
153
|
+
e.preventDefault();
|
|
154
|
+
if (results.value.length) selectedIndex.value = (selectedIndex.value + 1) % results.value.length;
|
|
155
|
+
break;
|
|
156
|
+
case "ArrowUp":
|
|
157
|
+
e.preventDefault();
|
|
158
|
+
if (results.value.length) selectedIndex.value = (selectedIndex.value - 1 + results.value.length) % results.value.length;
|
|
159
|
+
break;
|
|
160
|
+
case "Enter": if (results.value.length && selectedIndex.value >= 0) selectResult(results.value[selectedIndex.value]);
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
const selectResult = (result) => {
|
|
164
|
+
emit("select", result);
|
|
165
|
+
closeModal();
|
|
166
|
+
};
|
|
167
|
+
return (_ctx, _cache) => {
|
|
168
|
+
return openBlock(), createBlock(Teleport, { to: "body" }, [createVNode(Transition, { name: "fade" }, {
|
|
169
|
+
default: withCtx(() => [__props.isOpen ? (openBlock(), createElementBlock("div", {
|
|
170
|
+
key: 0,
|
|
171
|
+
class: "command-palette-overlay",
|
|
172
|
+
onClick: closeModal
|
|
173
|
+
}, [createElementVNode("div", {
|
|
174
|
+
class: "command-palette",
|
|
175
|
+
onClick: _cache[1] || (_cache[1] = withModifiers(() => {}, ["stop"]))
|
|
176
|
+
}, [createElementVNode("div", _hoisted_1$2, [withDirectives(createElementVNode("input", {
|
|
177
|
+
ref: "input",
|
|
178
|
+
"onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => query.value = $event),
|
|
179
|
+
type: "text",
|
|
180
|
+
class: "command-palette-input",
|
|
181
|
+
placeholder: __props.placeholder,
|
|
182
|
+
autofocus: "",
|
|
183
|
+
onKeydown: handleKeydown
|
|
184
|
+
}, null, 40, _hoisted_2$2), [[vModelText, query.value]])]), results.value.length ? (openBlock(), createElementBlock("div", _hoisted_3$1, [(openBlock(true), createElementBlock(Fragment, null, renderList(results.value, (result, index) => {
|
|
185
|
+
return openBlock(), createElementBlock("div", {
|
|
186
|
+
key: index,
|
|
187
|
+
class: normalizeClass(["command-palette-result", { selected: index === selectedIndex.value }]),
|
|
188
|
+
onClick: ($event) => selectResult(result),
|
|
189
|
+
onMouseover: ($event) => selectedIndex.value = index
|
|
190
|
+
}, [createElementVNode("div", _hoisted_5, [renderSlot(_ctx.$slots, "title", { result })]), createElementVNode("div", _hoisted_6, [renderSlot(_ctx.$slots, "content", { result })])], 42, _hoisted_4);
|
|
191
|
+
}), 128))])) : query.value && !results.value.length ? (openBlock(), createElementBlock("div", _hoisted_7, [renderSlot(_ctx.$slots, "empty", {}, () => [createTextVNode(" No results found for \"" + toDisplayString(query.value) + "\" ", 1)])])) : createCommentVNode("", true)])])) : createCommentVNode("", true)]),
|
|
192
|
+
_: 3
|
|
193
|
+
})]);
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
//#endregion
|
|
198
|
+
//#region src/components/SheetNav.vue?vue&type=script&setup=true&lang.ts
|
|
199
|
+
var _hoisted_1$1 = { class: "tabs" };
|
|
200
|
+
var _hoisted_2$1 = { tabindex: "0" };
|
|
201
|
+
var _hoisted_3 = { tabindex: "0" };
|
|
202
|
+
//#endregion
|
|
203
|
+
//#region src/components/SheetNav.vue
|
|
204
|
+
var SheetNav_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE__ */ defineComponent({
|
|
205
|
+
__name: "SheetNav",
|
|
206
|
+
props: { breadcrumbs: { default: () => [] } },
|
|
207
|
+
setup(__props) {
|
|
208
|
+
const breadcrumbsVisibile = ref(true);
|
|
209
|
+
const searchVisible = ref(false);
|
|
210
|
+
const searchText = ref("");
|
|
211
|
+
const inputRef = useTemplateRef("searchinput");
|
|
212
|
+
const rotateHideTabIcon = computed(() => {
|
|
213
|
+
return breadcrumbsVisibile.value ? "unrotated" : "rotated";
|
|
214
|
+
});
|
|
215
|
+
const toggleBreadcrumbs = () => {
|
|
216
|
+
breadcrumbsVisibile.value = !breadcrumbsVisibile.value;
|
|
217
|
+
};
|
|
218
|
+
const toggleSearch = async () => {
|
|
219
|
+
searchVisible.value = !searchVisible.value;
|
|
220
|
+
await nextTick(() => {
|
|
221
|
+
inputRef.value?.focus();
|
|
222
|
+
});
|
|
223
|
+
};
|
|
224
|
+
const handleSearchInput = (event) => {
|
|
225
|
+
event.preventDefault();
|
|
226
|
+
event.stopPropagation();
|
|
227
|
+
};
|
|
228
|
+
const handleSearch = async (event) => {
|
|
229
|
+
event.preventDefault();
|
|
230
|
+
event.stopPropagation();
|
|
231
|
+
await toggleSearch();
|
|
232
|
+
};
|
|
233
|
+
const navigateHome = () => {};
|
|
234
|
+
return (_ctx, _cache) => {
|
|
235
|
+
const _component_router_link = resolveComponent("router-link");
|
|
236
|
+
return openBlock(), createElementBlock("footer", null, [createElementVNode("ul", _hoisted_1$1, [
|
|
237
|
+
createElementVNode("li", {
|
|
238
|
+
class: "hidebreadcrumbs",
|
|
239
|
+
onClick: toggleBreadcrumbs,
|
|
240
|
+
onKeydown: withKeys(toggleBreadcrumbs, ["enter"])
|
|
241
|
+
}, [createElementVNode("a", _hoisted_2$1, [createElementVNode("div", { class: normalizeClass(rotateHideTabIcon.value) }, "×", 2)])], 32),
|
|
242
|
+
createElementVNode("li", {
|
|
243
|
+
class: "hometab",
|
|
244
|
+
style: normalizeStyle({ display: breadcrumbsVisibile.value ? "block" : "none" }),
|
|
245
|
+
onClick: navigateHome,
|
|
246
|
+
onKeydown: withKeys(navigateHome, ["enter"])
|
|
247
|
+
}, [createVNode(_component_router_link, {
|
|
248
|
+
to: "/",
|
|
249
|
+
tabindex: "0"
|
|
250
|
+
}, {
|
|
251
|
+
default: withCtx(() => [..._cache[5] || (_cache[5] = [createElementVNode("svg", {
|
|
252
|
+
class: "icon",
|
|
253
|
+
"aria-label": "Home",
|
|
254
|
+
viewBox: "0 0 24 24",
|
|
255
|
+
fill: "none",
|
|
256
|
+
stroke: "currentColor",
|
|
257
|
+
"stroke-width": "2"
|
|
258
|
+
}, [createElementVNode("path", { d: "M3 12l9-9 9 9" }), createElementVNode("path", { d: "M9 21V12h6v9" })], -1)])]),
|
|
259
|
+
_: 1
|
|
260
|
+
})], 36),
|
|
261
|
+
createElementVNode("li", {
|
|
262
|
+
class: normalizeClass(["searchtab", { "search-active": searchVisible.value }]),
|
|
263
|
+
style: normalizeStyle({ display: breadcrumbsVisibile.value ? "block" : "none" })
|
|
264
|
+
}, [createElementVNode("a", _hoisted_3, [withDirectives((openBlock(), createElementBlock("svg", {
|
|
265
|
+
class: "icon search-icon",
|
|
266
|
+
role: "button",
|
|
267
|
+
"aria-label": "Search",
|
|
268
|
+
viewBox: "0 0 24 24",
|
|
269
|
+
fill: "none",
|
|
270
|
+
stroke: "currentColor",
|
|
271
|
+
"stroke-width": "2",
|
|
272
|
+
onClick: toggleSearch,
|
|
273
|
+
onKeydown: withKeys(toggleSearch, ["enter"])
|
|
274
|
+
}, [..._cache[6] || (_cache[6] = [createElementVNode("circle", {
|
|
275
|
+
cx: "11",
|
|
276
|
+
cy: "11",
|
|
277
|
+
r: "7"
|
|
278
|
+
}, null, -1), createElementVNode("path", { d: "M21 21l-4.35-4.35" }, null, -1)])], 544)), [[vShow, !searchVisible.value]]), withDirectives(createElementVNode("input", {
|
|
279
|
+
ref: "searchinput",
|
|
280
|
+
"onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => searchText.value = $event),
|
|
281
|
+
type: "text",
|
|
282
|
+
placeholder: "Search...",
|
|
283
|
+
onClick: _cache[1] || (_cache[1] = withModifiers(() => {}, ["stop"])),
|
|
284
|
+
onInput: _cache[2] || (_cache[2] = ($event) => handleSearchInput($event)),
|
|
285
|
+
onBlur: _cache[3] || (_cache[3] = ($event) => handleSearch($event)),
|
|
286
|
+
onKeydown: [_cache[4] || (_cache[4] = withKeys(($event) => handleSearch($event), ["enter"])), withKeys(toggleSearch, ["escape"])]
|
|
287
|
+
}, null, 544), [[vShow, searchVisible.value], [vModelText, searchText.value]])])], 6),
|
|
288
|
+
(openBlock(true), createElementBlock(Fragment, null, renderList(__props.breadcrumbs, (breadcrumb) => {
|
|
289
|
+
return openBlock(), createElementBlock("li", {
|
|
290
|
+
key: breadcrumb.title,
|
|
291
|
+
style: normalizeStyle({ display: breadcrumbsVisibile.value ? "block" : "none" })
|
|
292
|
+
}, [createVNode(_component_router_link, {
|
|
293
|
+
tabindex: "0",
|
|
294
|
+
to: breadcrumb.to
|
|
295
|
+
}, {
|
|
296
|
+
default: withCtx(() => [createTextVNode(toDisplayString(breadcrumb.title), 1)]),
|
|
297
|
+
_: 2
|
|
298
|
+
}, 1032, ["to"])], 4);
|
|
299
|
+
}), 128))
|
|
300
|
+
])]);
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
}), [["__scopeId", "data-v-cd118b06"]]);
|
|
304
|
+
//#endregion
|
|
305
|
+
//#region src/components/Desktop.vue?vue&type=script&setup=true&lang.ts
|
|
306
|
+
var _hoisted_1 = {
|
|
307
|
+
key: 1,
|
|
308
|
+
class: "loading"
|
|
309
|
+
};
|
|
310
|
+
var _hoisted_2 = {
|
|
311
|
+
key: 2,
|
|
312
|
+
class: "loading"
|
|
313
|
+
};
|
|
314
|
+
//#endregion
|
|
315
|
+
//#region src/components/Desktop.vue
|
|
316
|
+
var Desktop_default = /* @__PURE__ */ defineComponent({
|
|
317
|
+
__name: "Desktop",
|
|
318
|
+
props: {
|
|
319
|
+
availableDoctypes: { default: () => [] },
|
|
320
|
+
routeAdapter: {}
|
|
321
|
+
},
|
|
322
|
+
emits: [
|
|
323
|
+
"action",
|
|
324
|
+
"navigate",
|
|
325
|
+
"record:open",
|
|
326
|
+
"load-records",
|
|
327
|
+
"load-record"
|
|
328
|
+
],
|
|
329
|
+
setup(__props, { emit: __emit }) {
|
|
330
|
+
const emit = __emit;
|
|
331
|
+
const { stonecrop } = useStonecrop();
|
|
332
|
+
let validationStore = null;
|
|
333
|
+
try {
|
|
334
|
+
validationStore = useValidationStore();
|
|
335
|
+
} catch {
|
|
336
|
+
validationStore = null;
|
|
337
|
+
}
|
|
338
|
+
const fieldErrors = computed(() => currentView.value === "record" ? validationStore?.errorsByField ?? {} : {});
|
|
339
|
+
const loading = ref(false);
|
|
340
|
+
const commandPaletteOpen = ref(false);
|
|
341
|
+
const draftRecord = ref({});
|
|
342
|
+
const currentViewData = computed({
|
|
343
|
+
get() {
|
|
344
|
+
if (currentView.value === "doctypes") return { doctypes_table: __props.availableDoctypes?.map((doctype) => ({
|
|
345
|
+
id: doctype,
|
|
346
|
+
doctype,
|
|
347
|
+
display_name: formatDoctypeName(doctype),
|
|
348
|
+
actions: "View Records"
|
|
349
|
+
})) ?? [] };
|
|
350
|
+
if (currentView.value === "records") return { records_table: getRecords().map((record) => Object.assign({}, record, {
|
|
351
|
+
id: resolveRecordId(record) ?? "",
|
|
352
|
+
actions: "Edit"
|
|
353
|
+
})) };
|
|
354
|
+
if (!stonecrop.value || !currentDoctype.value || !currentRecordId.value) return {};
|
|
355
|
+
try {
|
|
356
|
+
const flat = { ...isNewRecord.value ? draftRecord.value : stonecrop.value.getRecordById(currentDoctype.value, currentRecordId.value)?.get("") };
|
|
357
|
+
const doctype = stonecrop.value.registry.registry[currentDoctype.value];
|
|
358
|
+
if (doctype) {
|
|
359
|
+
for (const field of doctype.getSchemaArray()) if (field.kind === "fieldset") {
|
|
360
|
+
const nested = {};
|
|
361
|
+
for (const child of field.schema) if (child.fieldname) nested[child.fieldname] = flat[child.fieldname];
|
|
362
|
+
flat[field.fieldname] = nested;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
return flat;
|
|
366
|
+
} catch {
|
|
367
|
+
return {};
|
|
368
|
+
}
|
|
369
|
+
},
|
|
370
|
+
set(newData) {
|
|
371
|
+
if (currentView.value !== "record") return;
|
|
372
|
+
if (!stonecrop.value || !currentDoctype.value || !currentRecordId.value) return;
|
|
373
|
+
try {
|
|
374
|
+
const doctype = stonecrop.value.registry.registry[currentDoctype.value];
|
|
375
|
+
const fieldsetNames = /* @__PURE__ */ new Set();
|
|
376
|
+
if (doctype) {
|
|
377
|
+
for (const field of doctype.getSchemaArray()) if (field.kind === "fieldset") fieldsetNames.add(field.fieldname);
|
|
378
|
+
}
|
|
379
|
+
const flatData = {};
|
|
380
|
+
const fieldsetValues = [];
|
|
381
|
+
for (const [key, value] of Object.entries(newData)) if (fieldsetNames.has(key) && value && typeof value === "object" && !Array.isArray(value)) fieldsetValues.push(value);
|
|
382
|
+
else flatData[key] = value;
|
|
383
|
+
for (const nestedValue of fieldsetValues) Object.assign(flatData, nestedValue);
|
|
384
|
+
const changedFields = [];
|
|
385
|
+
if (isNewRecord.value) {
|
|
386
|
+
const next = { ...draftRecord.value };
|
|
387
|
+
for (const [fieldname, value] of Object.entries(flatData)) {
|
|
388
|
+
if (value === void 0) continue;
|
|
389
|
+
if (next[fieldname] !== value) {
|
|
390
|
+
next[fieldname] = value;
|
|
391
|
+
changedFields.push(fieldname);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
draftRecord.value = next;
|
|
395
|
+
} else {
|
|
396
|
+
const hstStore = stonecrop.value.getStore();
|
|
397
|
+
for (const [fieldname, value] of Object.entries(flatData)) {
|
|
398
|
+
if (value === void 0) continue;
|
|
399
|
+
const fieldPath = `${currentDoctype.value}.${currentRecordId.value}.${fieldname}`;
|
|
400
|
+
if ((hstStore.has(fieldPath) ? hstStore.get(fieldPath) : void 0) !== value) {
|
|
401
|
+
hstStore.set(fieldPath, value);
|
|
402
|
+
changedFields.push(fieldname);
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
if (changedFields.length > 0) driveFieldValidation(changedFields);
|
|
407
|
+
} catch (error) {
|
|
408
|
+
console.warn("HST update failed:", error);
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
});
|
|
412
|
+
function driveFieldValidation(changedFields) {
|
|
413
|
+
if (!validationStore || !stonecrop.value || !currentDoctype.value || !currentRecordId.value) return;
|
|
414
|
+
const triggers = stonecrop.value.registry.getDoctype(currentDoctype.value)?.getTriggers();
|
|
415
|
+
if (!triggers || Object.keys(triggers).length === 0) return;
|
|
416
|
+
const record = isNewRecord.value ? { ...draftRecord.value } : { ...stonecrop.value.getRecordById(currentDoctype.value, currentRecordId.value)?.get("") };
|
|
417
|
+
for (const field of changedFields) validationStore.validateField(triggers, field, record);
|
|
418
|
+
}
|
|
419
|
+
const route = computed(() => __props.routeAdapter ? null : unref(stonecrop.value?.registry.router?.currentRoute));
|
|
420
|
+
const router = computed(() => __props.routeAdapter ? null : stonecrop.value?.registry.router);
|
|
421
|
+
const currentDoctype = computed(() => {
|
|
422
|
+
if (__props.routeAdapter) return __props.routeAdapter.getCurrentDoctype();
|
|
423
|
+
if (!route.value) return "";
|
|
424
|
+
if (route.value.meta?.actualDoctype) return route.value.meta.actualDoctype;
|
|
425
|
+
if (route.value.params.doctype) return route.value.params.doctype.toString();
|
|
426
|
+
const pathMatch = route.value.params.pathMatch;
|
|
427
|
+
if (pathMatch && pathMatch.length > 0) return pathMatch[0];
|
|
428
|
+
return "";
|
|
429
|
+
});
|
|
430
|
+
const routeDoctype = computed(() => {
|
|
431
|
+
if (__props.routeAdapter) return __props.routeAdapter.getCurrentDoctype();
|
|
432
|
+
if (!route.value) return "";
|
|
433
|
+
if (route.value.meta?.doctype) return route.value.meta.doctype;
|
|
434
|
+
if (route.value.params.doctype) return route.value.params.doctype.toString();
|
|
435
|
+
const pathMatch = route.value.params.pathMatch;
|
|
436
|
+
if (pathMatch && pathMatch.length > 0) return pathMatch[0];
|
|
437
|
+
return "";
|
|
438
|
+
});
|
|
439
|
+
const currentRecordId = computed(() => {
|
|
440
|
+
if (__props.routeAdapter) return __props.routeAdapter.getCurrentRecordId();
|
|
441
|
+
if (!route.value) return "";
|
|
442
|
+
if (route.value.params.recordId) return route.value.params.recordId.toString();
|
|
443
|
+
const pathMatch = route.value.params.pathMatch;
|
|
444
|
+
if (pathMatch && pathMatch.length > 1) return pathMatch[1];
|
|
445
|
+
return "";
|
|
446
|
+
});
|
|
447
|
+
const isNewRecord = computed(() => isDraftRecordId(currentRecordId.value));
|
|
448
|
+
const currentView = computed(() => {
|
|
449
|
+
if (__props.routeAdapter) return __props.routeAdapter.getCurrentView();
|
|
450
|
+
if (!route.value) return "doctypes";
|
|
451
|
+
if (route.value.name === "home" || route.value.path === "/") return "doctypes";
|
|
452
|
+
if (route.value.name && route.value.name !== "catch-all") {
|
|
453
|
+
const routeName = route.value.name;
|
|
454
|
+
if (routeName.includes("form") || route.value.params.recordId) return "record";
|
|
455
|
+
else if (routeName.includes("list") || route.value.params.doctype) return "records";
|
|
456
|
+
}
|
|
457
|
+
const pathMatch = route.value.params.pathMatch;
|
|
458
|
+
if (pathMatch && pathMatch.length > 0) return pathMatch.length === 1 ? "records" : "record";
|
|
459
|
+
return "doctypes";
|
|
460
|
+
});
|
|
461
|
+
const getAvailableTransitions = () => {
|
|
462
|
+
if (!stonecrop.value || !currentDoctype.value || !currentRecordId.value) return [];
|
|
463
|
+
try {
|
|
464
|
+
const doctype = stonecrop.value.registry.getDoctype(currentDoctype.value);
|
|
465
|
+
if (!doctype?.workflow) return [];
|
|
466
|
+
const currentState = stonecrop.value.getRecordState(currentDoctype.value, currentRecordId.value);
|
|
467
|
+
const transitions = doctype.getAvailableTransitions(currentState);
|
|
468
|
+
const recordData = currentViewData.value || {};
|
|
469
|
+
return transitions.map(({ name }) => ({
|
|
470
|
+
label: doctype.getActionMeta(name)?.label ?? name,
|
|
471
|
+
action: () => {
|
|
472
|
+
emit("action", {
|
|
473
|
+
name,
|
|
474
|
+
doctype: currentDoctype.value,
|
|
475
|
+
recordId: currentRecordId.value,
|
|
476
|
+
data: recordData
|
|
477
|
+
});
|
|
478
|
+
}
|
|
479
|
+
}));
|
|
480
|
+
} catch (error) {
|
|
481
|
+
console.warn("Error getting available transitions:", error);
|
|
482
|
+
return [];
|
|
483
|
+
}
|
|
484
|
+
};
|
|
485
|
+
const getAvailableCommands = () => {
|
|
486
|
+
if (!stonecrop.value || !currentDoctype.value || !currentRecordId.value) return [];
|
|
487
|
+
try {
|
|
488
|
+
const doctype = stonecrop.value.registry.getDoctype(currentDoctype.value);
|
|
489
|
+
if (!doctype?.workflow) return [];
|
|
490
|
+
const currentState = stonecrop.value.getRecordState(currentDoctype.value, currentRecordId.value);
|
|
491
|
+
const commands = doctype.getAvailableCommands(currentState);
|
|
492
|
+
const recordData = currentViewData.value || {};
|
|
493
|
+
return commands.map(({ name }) => ({
|
|
494
|
+
label: doctype.getActionMeta(name)?.label ?? name,
|
|
495
|
+
action: () => {
|
|
496
|
+
emit("action", {
|
|
497
|
+
name,
|
|
498
|
+
doctype: currentDoctype.value,
|
|
499
|
+
recordId: currentRecordId.value,
|
|
500
|
+
data: recordData
|
|
501
|
+
});
|
|
502
|
+
}
|
|
503
|
+
}));
|
|
504
|
+
} catch (error) {
|
|
505
|
+
console.warn("Error getting available commands:", error);
|
|
506
|
+
return [];
|
|
507
|
+
}
|
|
508
|
+
};
|
|
509
|
+
const actionElements = computed(() => {
|
|
510
|
+
const elements = [];
|
|
511
|
+
switch (currentView.value) {
|
|
512
|
+
case "records":
|
|
513
|
+
elements.push({
|
|
514
|
+
type: "button",
|
|
515
|
+
label: "New Record",
|
|
516
|
+
action: () => void createNewRecord()
|
|
517
|
+
});
|
|
518
|
+
break;
|
|
519
|
+
case "record": {
|
|
520
|
+
const recordActions = [...getAvailableTransitions(), ...getAvailableCommands()];
|
|
521
|
+
if (recordActions.length > 0) elements.push({
|
|
522
|
+
type: "dropdown",
|
|
523
|
+
label: "Actions",
|
|
524
|
+
actions: recordActions
|
|
525
|
+
});
|
|
526
|
+
break;
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
return elements;
|
|
530
|
+
});
|
|
531
|
+
const navigationBreadcrumbs = computed(() => {
|
|
532
|
+
const breadcrumbs = [];
|
|
533
|
+
if (currentView.value === "records" && routeDoctype.value) breadcrumbs.push({
|
|
534
|
+
title: "Home",
|
|
535
|
+
to: "/"
|
|
536
|
+
}, {
|
|
537
|
+
title: formatDoctypeName(routeDoctype.value),
|
|
538
|
+
to: `/${routeDoctype.value}`
|
|
539
|
+
});
|
|
540
|
+
else if (currentView.value === "record" && routeDoctype.value) {
|
|
541
|
+
const recordPath = currentRecordId.value ? `/${routeDoctype.value}/${currentRecordId.value}` : route.value?.fullPath ?? "";
|
|
542
|
+
breadcrumbs.push({
|
|
543
|
+
title: "Home",
|
|
544
|
+
to: "/"
|
|
545
|
+
}, {
|
|
546
|
+
title: formatDoctypeName(routeDoctype.value),
|
|
547
|
+
to: `/${routeDoctype.value}`
|
|
548
|
+
}, {
|
|
549
|
+
title: isNewRecord.value ? "New Record" : "Edit Record",
|
|
550
|
+
to: recordPath
|
|
551
|
+
});
|
|
552
|
+
}
|
|
553
|
+
return breadcrumbs;
|
|
554
|
+
});
|
|
555
|
+
const searchCommands = (query) => {
|
|
556
|
+
const commands = [{
|
|
557
|
+
title: "Go Home",
|
|
558
|
+
description: "Navigate to the home page",
|
|
559
|
+
action: () => void doNavigate({ view: "doctypes" })
|
|
560
|
+
}, {
|
|
561
|
+
title: "Toggle Command Palette",
|
|
562
|
+
description: "Open/close the command palette",
|
|
563
|
+
action: () => commandPaletteOpen.value = !commandPaletteOpen.value
|
|
564
|
+
}];
|
|
565
|
+
if (routeDoctype.value) {
|
|
566
|
+
commands.push({
|
|
567
|
+
title: `View ${formatDoctypeName(routeDoctype.value)} Records`,
|
|
568
|
+
description: `Navigate to ${routeDoctype.value} list`,
|
|
569
|
+
action: () => void doNavigate({
|
|
570
|
+
view: "records",
|
|
571
|
+
doctype: routeDoctype.value
|
|
572
|
+
})
|
|
573
|
+
});
|
|
574
|
+
commands.push({
|
|
575
|
+
title: `Create New ${formatDoctypeName(routeDoctype.value)}`,
|
|
576
|
+
description: `Create a new ${routeDoctype.value} record`,
|
|
577
|
+
action: () => void createNewRecord()
|
|
578
|
+
});
|
|
579
|
+
}
|
|
580
|
+
__props.availableDoctypes.forEach((doctype) => {
|
|
581
|
+
commands.push({
|
|
582
|
+
title: `View ${formatDoctypeName(doctype)}`,
|
|
583
|
+
description: `Navigate to ${doctype} list`,
|
|
584
|
+
action: () => void doNavigate({
|
|
585
|
+
view: "records",
|
|
586
|
+
doctype
|
|
587
|
+
})
|
|
588
|
+
});
|
|
589
|
+
});
|
|
590
|
+
if (!query) return commands;
|
|
591
|
+
return commands.filter((cmd) => cmd.title.toLowerCase().includes(query.toLowerCase()) || cmd.description.toLowerCase().includes(query.toLowerCase()));
|
|
592
|
+
};
|
|
593
|
+
const executeCommand = (command) => {
|
|
594
|
+
command.action();
|
|
595
|
+
commandPaletteOpen.value = false;
|
|
596
|
+
};
|
|
597
|
+
const listRecordsFetcher = (options) => {
|
|
598
|
+
if (!stonecrop.value || !currentDoctype.value) return Promise.resolve({
|
|
599
|
+
data: [],
|
|
600
|
+
hasMore: false
|
|
601
|
+
});
|
|
602
|
+
const doctype = stonecrop.value.registry.getDoctype(currentDoctype.value);
|
|
603
|
+
if (!doctype) return Promise.resolve({
|
|
604
|
+
data: [],
|
|
605
|
+
hasMore: false
|
|
606
|
+
});
|
|
607
|
+
return stonecrop.value.getRecords(doctype, options);
|
|
608
|
+
};
|
|
609
|
+
const formatDoctypeName = (doctype) => {
|
|
610
|
+
return doctype.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
611
|
+
};
|
|
612
|
+
const doNavigate = async (target) => {
|
|
613
|
+
emit("navigate", target);
|
|
614
|
+
if (__props.routeAdapter) await __props.routeAdapter.navigate(target);
|
|
615
|
+
else if (target.view === "doctypes") await router.value?.push("/");
|
|
616
|
+
else if (target.view === "records" && target.doctype) await router.value?.push(`/${target.doctype}`);
|
|
617
|
+
else if (target.view === "record" && target.doctype && target.recordId) await router.value?.push(`/${target.doctype}/${target.recordId}`);
|
|
618
|
+
};
|
|
619
|
+
const navigateToDoctype = async (doctype) => {
|
|
620
|
+
await doNavigate({
|
|
621
|
+
view: "records",
|
|
622
|
+
doctype
|
|
623
|
+
});
|
|
624
|
+
};
|
|
625
|
+
const openRecord = async (recordId) => {
|
|
626
|
+
const doctype = routeDoctype.value;
|
|
627
|
+
emit("record:open", {
|
|
628
|
+
doctype,
|
|
629
|
+
recordId
|
|
630
|
+
});
|
|
631
|
+
await doNavigate({
|
|
632
|
+
view: "record",
|
|
633
|
+
doctype,
|
|
634
|
+
recordId
|
|
635
|
+
});
|
|
636
|
+
};
|
|
637
|
+
const createNewRecord = async () => {
|
|
638
|
+
await doNavigate({
|
|
639
|
+
view: "record",
|
|
640
|
+
doctype: routeDoctype.value,
|
|
641
|
+
recordId: DRAFT_RECORD_ID
|
|
642
|
+
});
|
|
643
|
+
};
|
|
644
|
+
const getDoctypesSchema = () => {
|
|
645
|
+
if (!__props.availableDoctypes?.length) return [];
|
|
646
|
+
return [{
|
|
647
|
+
kind: "table",
|
|
648
|
+
fieldname: "doctypes_table",
|
|
649
|
+
component: "ATable",
|
|
650
|
+
label: "Doctypes",
|
|
651
|
+
schema: [
|
|
652
|
+
{
|
|
653
|
+
fieldname: "doctype",
|
|
654
|
+
label: "Doctype",
|
|
655
|
+
component: "ATextInput",
|
|
656
|
+
align: "left",
|
|
657
|
+
edit: false,
|
|
658
|
+
width: "20ch"
|
|
659
|
+
},
|
|
660
|
+
{
|
|
661
|
+
fieldname: "display_name",
|
|
662
|
+
label: "Name",
|
|
663
|
+
component: "ATextInput",
|
|
664
|
+
align: "left",
|
|
665
|
+
edit: false,
|
|
666
|
+
width: "30ch"
|
|
667
|
+
},
|
|
668
|
+
{
|
|
669
|
+
fieldname: "actions",
|
|
670
|
+
label: "Actions",
|
|
671
|
+
component: "ATextInput",
|
|
672
|
+
align: "center",
|
|
673
|
+
edit: false,
|
|
674
|
+
width: "20ch"
|
|
675
|
+
}
|
|
676
|
+
],
|
|
677
|
+
config: {
|
|
678
|
+
view: "list",
|
|
679
|
+
fullWidth: true
|
|
680
|
+
}
|
|
681
|
+
}];
|
|
682
|
+
};
|
|
683
|
+
const getRecordsSchema = () => {
|
|
684
|
+
if (!currentDoctype.value) return [];
|
|
685
|
+
if (!stonecrop.value) return [];
|
|
686
|
+
const registry = stonecrop.value.registry;
|
|
687
|
+
const doctype = registry.registry[currentDoctype.value];
|
|
688
|
+
if (!doctype) return [];
|
|
689
|
+
const schema = registry.resolveSchema(doctype);
|
|
690
|
+
if (schema.length === 0) return [];
|
|
691
|
+
const doctypeSlug = currentDoctype.value;
|
|
692
|
+
const clientConfigured = Boolean(stonecrop.value.getClient());
|
|
693
|
+
return [{
|
|
694
|
+
kind: "table",
|
|
695
|
+
fieldname: "records_table",
|
|
696
|
+
component: "ATable",
|
|
697
|
+
schema: [...resolvedFieldsToColumns(schema), {
|
|
698
|
+
fieldname: "actions",
|
|
699
|
+
label: "Actions",
|
|
700
|
+
component: "ATextInput"
|
|
701
|
+
}],
|
|
702
|
+
config: {
|
|
703
|
+
view: "list",
|
|
704
|
+
fullWidth: true
|
|
705
|
+
},
|
|
706
|
+
...clientConfigured ? {
|
|
707
|
+
getRecords: listRecordsFetcher,
|
|
708
|
+
sourceKey: doctypeSlug
|
|
709
|
+
} : {}
|
|
710
|
+
}];
|
|
711
|
+
};
|
|
712
|
+
const getRecordFormSchema = () => {
|
|
713
|
+
if (!currentDoctype.value) return [];
|
|
714
|
+
if (!stonecrop.value) return [];
|
|
715
|
+
try {
|
|
716
|
+
const registry = stonecrop.value?.registry;
|
|
717
|
+
const doctype = registry?.registry[currentDoctype.value];
|
|
718
|
+
if (!doctype?.schema) return [];
|
|
719
|
+
return registry.resolveSchema(doctype);
|
|
720
|
+
} catch {
|
|
721
|
+
return [];
|
|
722
|
+
}
|
|
723
|
+
};
|
|
724
|
+
const getRecords = () => {
|
|
725
|
+
if (!stonecrop.value || !currentDoctype.value) return [];
|
|
726
|
+
const recordsData = stonecrop.value.records(currentDoctype.value)?.get("");
|
|
727
|
+
if (recordsData && typeof recordsData === "object" && !Array.isArray(recordsData)) return Object.values(recordsData);
|
|
728
|
+
return [];
|
|
729
|
+
};
|
|
730
|
+
const currentViewSchema = computed(() => {
|
|
731
|
+
switch (currentView.value) {
|
|
732
|
+
case "doctypes": return getDoctypesSchema();
|
|
733
|
+
case "records": return getRecordsSchema();
|
|
734
|
+
case "record": return getRecordFormSchema();
|
|
735
|
+
default: return [];
|
|
736
|
+
}
|
|
737
|
+
});
|
|
738
|
+
const handleActionClick = (_label, action) => {
|
|
739
|
+
if (action) action();
|
|
740
|
+
};
|
|
741
|
+
/**
|
|
742
|
+
* Resolve a record's identity for links and navigation.
|
|
743
|
+
*
|
|
744
|
+
* Identity is declared once, on the doctype: `primaryKey`, or `id` when nothing is declared.
|
|
745
|
+
* Delegating to `Doctype.getRecordId` is what guarantees this matches the key
|
|
746
|
+
* `Stonecrop.getRecords` stored the record under — resolving it independently here would let a
|
|
747
|
+
* row render a link to an HST path that does not exist.
|
|
748
|
+
*
|
|
749
|
+
* There is deliberately no per-shell override. Identity is a per-doctype fact and one shell
|
|
750
|
+
* renders many doctypes, so a single prop cannot answer it; a shell that named a field would
|
|
751
|
+
* also be overriding the very declaration the store keyed on, which is the bug above.
|
|
752
|
+
*/
|
|
753
|
+
const resolveRecordId = (record) => {
|
|
754
|
+
if (!stonecrop.value || !currentDoctype.value) return void 0;
|
|
755
|
+
return stonecrop.value.registry.registry[currentDoctype.value]?.getRecordId(record);
|
|
756
|
+
};
|
|
757
|
+
const getRecordIdFromRow = (rowElement) => {
|
|
758
|
+
const cell = rowElement.querySelector("td[data-rowindex]");
|
|
759
|
+
if (!cell) return null;
|
|
760
|
+
const rowIndexAttr = cell.getAttribute("data-rowindex");
|
|
761
|
+
if (rowIndexAttr === null) return null;
|
|
762
|
+
const rowIndex = parseInt(rowIndexAttr, 10);
|
|
763
|
+
if (isNaN(rowIndex)) return null;
|
|
764
|
+
const record = getRecords()[rowIndex];
|
|
765
|
+
if (!record) return null;
|
|
766
|
+
return resolveRecordId(record) ?? null;
|
|
767
|
+
};
|
|
768
|
+
const handleClick = async (event) => {
|
|
769
|
+
const target = event.target;
|
|
770
|
+
if (target.getAttribute("data-action") === "create") await createNewRecord();
|
|
771
|
+
const cell = target.closest("td, th");
|
|
772
|
+
if (cell) {
|
|
773
|
+
const cellText = cell.textContent?.trim();
|
|
774
|
+
const row = cell.closest("tr");
|
|
775
|
+
if (cellText === "View Records" && row) {
|
|
776
|
+
const cells = row.querySelectorAll("td");
|
|
777
|
+
if (cells.length > 0) {
|
|
778
|
+
const doctype = cells[1].textContent?.trim();
|
|
779
|
+
if (doctype) await navigateToDoctype(doctype);
|
|
780
|
+
}
|
|
781
|
+
} else if (cellText === "Edit" && row) {
|
|
782
|
+
const recordId = getRecordIdFromRow(row);
|
|
783
|
+
if (recordId) await openRecord(recordId);
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
};
|
|
787
|
+
const loadRecordData = async () => {
|
|
788
|
+
if (!stonecrop.value || !currentDoctype.value || !stonecrop.value.getClient()) return;
|
|
789
|
+
loading.value = true;
|
|
790
|
+
try {
|
|
791
|
+
await stonecrop.value.getRecord(currentDoctype.value, currentRecordId.value);
|
|
792
|
+
} catch (error) {
|
|
793
|
+
console.warn("Error fetching record:", error);
|
|
794
|
+
} finally {
|
|
795
|
+
loading.value = false;
|
|
796
|
+
}
|
|
797
|
+
};
|
|
798
|
+
watch([
|
|
799
|
+
currentView,
|
|
800
|
+
currentDoctype,
|
|
801
|
+
currentRecordId
|
|
802
|
+
], () => {
|
|
803
|
+
if (currentView.value === "records" && currentDoctype.value) emit("load-records", { doctype: currentDoctype.value });
|
|
804
|
+
else if (currentView.value === "record" && currentDoctype.value && currentRecordId.value) {
|
|
805
|
+
if (isNewRecord.value) return;
|
|
806
|
+
emit("load-record", {
|
|
807
|
+
doctype: currentDoctype.value,
|
|
808
|
+
recordId: currentRecordId.value
|
|
809
|
+
});
|
|
810
|
+
loadRecordData();
|
|
811
|
+
}
|
|
812
|
+
}, { immediate: true });
|
|
813
|
+
watch([currentDoctype, currentRecordId], () => {
|
|
814
|
+
validationStore?.clearAll();
|
|
815
|
+
});
|
|
816
|
+
watch([currentDoctype, currentRecordId], () => {
|
|
817
|
+
if (!isNewRecord.value) {
|
|
818
|
+
draftRecord.value = {};
|
|
819
|
+
return;
|
|
820
|
+
}
|
|
821
|
+
const registry = stonecrop.value?.registry;
|
|
822
|
+
draftRecord.value = registry ? registry.initializeRecord(getRecordFormSchema()) : {};
|
|
823
|
+
}, { immediate: true });
|
|
824
|
+
provide("desktopMethods", {
|
|
825
|
+
navigateToDoctype,
|
|
826
|
+
openRecord,
|
|
827
|
+
createNewRecord,
|
|
828
|
+
/**
|
|
829
|
+
* Convenience wrapper so child components (e.g. slot content) can emit
|
|
830
|
+
* an action event without needing a direct reference to the emit function.
|
|
831
|
+
*/
|
|
832
|
+
emitAction: (name, data) => {
|
|
833
|
+
emit("action", {
|
|
834
|
+
name,
|
|
835
|
+
doctype: currentDoctype.value,
|
|
836
|
+
recordId: currentRecordId.value,
|
|
837
|
+
data: data ?? currentViewData.value ?? {}
|
|
838
|
+
});
|
|
839
|
+
}
|
|
840
|
+
});
|
|
841
|
+
provide("aformLinkNavigator", { navigate: (doctype, id) => {
|
|
842
|
+
doNavigate({
|
|
843
|
+
view: "record",
|
|
844
|
+
doctype,
|
|
845
|
+
recordId: String(id)
|
|
846
|
+
});
|
|
847
|
+
} });
|
|
848
|
+
provide("aformLinkResolver", async (doctypeSlug, id) => {
|
|
849
|
+
if (!stonecrop.value) return void 0;
|
|
850
|
+
try {
|
|
851
|
+
const displayField = (await stonecrop.value.getMeta({
|
|
852
|
+
path: `/${doctypeSlug}`,
|
|
853
|
+
segments: [doctypeSlug]
|
|
854
|
+
}))?.displayField;
|
|
855
|
+
if (!displayField) return void 0;
|
|
856
|
+
const readDisplay = (rec) => {
|
|
857
|
+
if (!rec) return void 0;
|
|
858
|
+
const val = rec[displayField];
|
|
859
|
+
return typeof val === "string" || typeof val === "number" ? String(val) : void 0;
|
|
860
|
+
};
|
|
861
|
+
const cached = stonecrop.value.getRecordById(doctypeSlug, id)?.get("");
|
|
862
|
+
const cachedDisplay = readDisplay(cached);
|
|
863
|
+
if (cachedDisplay != null) return cachedDisplay;
|
|
864
|
+
await stonecrop.value.getRecord(doctypeSlug, id);
|
|
865
|
+
const fetched = stonecrop.value.getRecordById(doctypeSlug, id)?.get("");
|
|
866
|
+
return readDisplay(fetched);
|
|
867
|
+
} catch {
|
|
868
|
+
return;
|
|
869
|
+
}
|
|
870
|
+
});
|
|
871
|
+
const handleKeydown = (event) => {
|
|
872
|
+
if ((event.ctrlKey || event.metaKey) && event.key === "k") {
|
|
873
|
+
event.preventDefault();
|
|
874
|
+
commandPaletteOpen.value = true;
|
|
875
|
+
}
|
|
876
|
+
if (event.key === "Escape" && commandPaletteOpen.value) commandPaletteOpen.value = false;
|
|
877
|
+
};
|
|
878
|
+
onMounted(() => {
|
|
879
|
+
document.addEventListener("keydown", handleKeydown);
|
|
880
|
+
});
|
|
881
|
+
onUnmounted(() => {
|
|
882
|
+
document.removeEventListener("keydown", handleKeydown);
|
|
883
|
+
});
|
|
884
|
+
return (_ctx, _cache) => {
|
|
885
|
+
return openBlock(), createElementBlock("div", {
|
|
886
|
+
class: "desktop",
|
|
887
|
+
onClick: handleClick
|
|
888
|
+
}, [
|
|
889
|
+
createVNode(ActionSet_default, {
|
|
890
|
+
elements: actionElements.value,
|
|
891
|
+
onActionClick: handleActionClick
|
|
892
|
+
}, null, 8, ["elements"]),
|
|
893
|
+
currentViewSchema.value.length > 0 ? (openBlock(), createBlock(unref(AForm), {
|
|
894
|
+
key: 0,
|
|
895
|
+
data: currentViewData.value,
|
|
896
|
+
"onUpdate:data": _cache[0] || (_cache[0] = ($event) => currentViewData.value = $event),
|
|
897
|
+
schema: currentViewSchema.value,
|
|
898
|
+
errors: fieldErrors.value
|
|
899
|
+
}, null, 8, [
|
|
900
|
+
"data",
|
|
901
|
+
"schema",
|
|
902
|
+
"errors"
|
|
903
|
+
])) : !unref(stonecrop) ? (openBlock(), createElementBlock("div", _hoisted_1, [..._cache[2] || (_cache[2] = [createElementVNode("p", null, "Initializing Stonecrop...", -1)])])) : (openBlock(), createElementBlock("div", _hoisted_2, [createElementVNode("p", null, "Loading " + toDisplayString(currentView.value) + " data...", 1)])),
|
|
904
|
+
createVNode(SheetNav_default, { breadcrumbs: navigationBreadcrumbs.value }, null, 8, ["breadcrumbs"]),
|
|
905
|
+
createVNode(CommandPalette_default, {
|
|
906
|
+
"is-open": commandPaletteOpen.value,
|
|
907
|
+
search: searchCommands,
|
|
908
|
+
placeholder: "Type a command or search...",
|
|
909
|
+
onSelect: executeCommand,
|
|
910
|
+
onClose: _cache[1] || (_cache[1] = ($event) => commandPaletteOpen.value = false)
|
|
911
|
+
}, {
|
|
912
|
+
title: withCtx(({ result }) => [createTextVNode(toDisplayString(result.title), 1)]),
|
|
913
|
+
content: withCtx(({ result }) => [createTextVNode(toDisplayString(result.description), 1)]),
|
|
914
|
+
_: 1
|
|
915
|
+
}, 8, ["is-open"])
|
|
916
|
+
]);
|
|
917
|
+
};
|
|
918
|
+
}
|
|
919
|
+
});
|
|
920
|
+
//#endregion
|
|
921
|
+
//#region src/plugins/index.ts
|
|
922
|
+
/**
|
|
923
|
+
* This is the main plugin that will be used to register all the desktop components.
|
|
924
|
+
* @public
|
|
925
|
+
*/
|
|
926
|
+
var plugin = { install: (app) => {
|
|
927
|
+
app.component("ActionSet", ActionSet_default);
|
|
928
|
+
app.component("CommandPalette", CommandPalette_default);
|
|
929
|
+
app.component("Desktop", Desktop_default);
|
|
930
|
+
app.component("SheetNav", SheetNav_default);
|
|
931
|
+
} };
|
|
932
|
+
//#endregion
|
|
933
|
+
export { ActionSet_default as ActionSet, CommandPalette_default as CommandPalette, Desktop_default as Desktop, SheetNav_default as SheetNav, plugin as StonecropDesktop };
|
|
934
|
+
|
|
935
|
+
//# sourceMappingURL=desktop.js.map
|