@stsdti/approvable-vue 0.1.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.
@@ -0,0 +1,902 @@
1
+ import { inject as J, ref as T, computed as C, watch as se, openBlock as e, createElementBlock as a, normalizeClass as N, createElementVNode as t, toDisplayString as c, unref as w, createCommentVNode as y, createTextVNode as z, Fragment as D, renderList as q, useTemplateRef as oe, onMounted as re, onBeforeUnmount as ke, withDirectives as ge, vModelText as Se, nextTick as we, markRaw as Ae, renderSlot as H, createBlock as K, resolveDynamicComponent as W, mergeProps as X, withCtx as ie, createVNode as pe, normalizeStyle as Q, createSlots as $e, Teleport as Ce, withModifiers as Ee, withKeys as Re, useModel as De, mergeModels as le } from "vue";
2
+ import { mergeMessages as Le, ApprovableAuditRepository as xe, formatMessage as G, get as V, notifyError as ne, ApprovableStepRepository as ue, isSuccessResponse as de, notifySuccess as ce, registerActionRenderer as Oe, createStepViewModel as Me, approvableStatusTone as Ie, approvableStepGlyph as Te, isClassIcon as Y, actionRenderer as Ne, performStepAction as Ve, ApprovableStatus as B, createApprovableViewModel as je, isRegisteredIcon as Pe, isUrlIcon as qe, ApprovableStatusRepository as Be } from "@stsdti/approvable-core";
3
+ import { actionRenderer as fa, actionSlotName as ha, isClassIcon as ya, isRegisteredIcon as _a, isUrlIcon as ka, unregisterActionRenderer as ga } from "@stsdti/approvable-core";
4
+ const ve = Symbol("approvable.messages");
5
+ function U() {
6
+ return Le(J(ve, null));
7
+ }
8
+ const Ke = {
9
+ key: 0,
10
+ class: "approvable-timeline-header"
11
+ }, Ue = { class: "approvable-timeline-eyebrow" }, Fe = { class: "approvable-timeline-title" }, Ge = ["disabled"], He = {
12
+ key: 1,
13
+ class: "approvable-timeline-state",
14
+ role: "status"
15
+ }, ze = {
16
+ key: 2,
17
+ class: "approvable-timeline-error"
18
+ }, Qe = {
19
+ key: 3,
20
+ class: "approvable-timeline-state"
21
+ }, We = { class: "approvable-timeline-list" }, Ye = ["stroke-width"], Je = ["d"], Xe = { class: "approvable-timeline-content" }, Ze = { class: "approvable-timeline-line" }, et = { class: "approvable-timeline-actor" }, tt = { class: "approvable-timeline-operation" }, at = { class: "approvable-timeline-time" }, st = {
22
+ key: 0,
23
+ class: "approvable-timeline-comment"
24
+ }, ot = {
25
+ key: 1,
26
+ class: "approvable-timeline-change"
27
+ }, lt = { class: "approvable-timeline-change-label" }, nt = { class: "approvable-timeline-value approvable-timeline-value--old" }, rt = { class: "approvable-timeline-value approvable-timeline-value--new" }, it = { class: "approvable-timeline-footer" }, me = {
28
+ __name: "ApprovableAuditTimeline",
29
+ props: {
30
+ approvableId: { type: [Number, String], required: !0 },
31
+ limit: { type: Number, default: 100 },
32
+ showHeader: { type: Boolean, default: !0 }
33
+ },
34
+ emits: ["loaded"],
35
+ setup(r, { expose: _, emit: b }) {
36
+ const f = r, h = b, S = U(), k = new xe(), o = T([]), m = T(!1), L = T(""), A = {
37
+ approvable_status_name: "Status",
38
+ comment: "Comment",
39
+ responsible: "Assigned to",
40
+ is_active: "Active step"
41
+ }, O = {
42
+ approve: { paths: ["M4 8.4l2.8 2.8 5.4-6"], width: 2.8 },
43
+ reject: { paths: ["M5.2 5.2l5.6 5.6M10.8 5.2l-5.6 5.6"], width: 2.4 },
44
+ comment: { paths: ["M8 4.6v3.6l2.6 1.6"], width: 2.2 },
45
+ status: { paths: ["M4 8h8M9.2 5.4L11.8 8l-2.6 2.6"], width: 2.2 },
46
+ undo: { paths: ["M4.4 6.6h3.4M4.4 6.6v-3M4.6 9.4a3.6 3.6 0 1 0 1-3.2"], width: 2 },
47
+ signal: { paths: ["M8 3.4v3.2M5.2 5.2l2.2 2.2M8 11.6a1.4 1.4 0 1 0 0-2.8 1.4 1.4 0 0 0 0 2.8"], width: 1.8 },
48
+ created: { paths: ["M4.4 8h7.2"], width: 2.2 },
49
+ update: { paths: ["M4.4 8h7.2"], width: 2.2 }
50
+ }, v = /* @__PURE__ */ new Set(["created", "update"]), d = C(() => {
51
+ const s = o.value.filter((l) => l.approvable_step_id), n = /* @__PURE__ */ new Map();
52
+ for (const l of s) {
53
+ const i = l.request_id || `audit-${l.id}`;
54
+ n.has(i) || n.set(i, []), n.get(i).push(l);
55
+ }
56
+ return [...n.values()].map((l) => {
57
+ const i = l[0], $ = x(i), F = l.flatMap(u);
58
+ return {
59
+ id: i.request_id || `audit-${i.id}`,
60
+ entries: l,
61
+ audit: i,
62
+ kind: $,
63
+ // A modifier class rather than utilities: the accent for each kind of
64
+ // event is a theme decision, so it belongs in the stylesheets alongside
65
+ // every other colour, not baked into the component.
66
+ kindClass: `approvable-timeline-marker--${$}`,
67
+ icon: O[$],
68
+ isQuiet: v.has($),
69
+ isSingleLine: F.length === 0
70
+ };
71
+ }).sort((l, i) => new Date(i.audit.created_at) - new Date(l.audit.created_at));
72
+ });
73
+ function x(s) {
74
+ var l, i, $;
75
+ const n = (l = s.metadata) == null ? void 0 : l.button;
76
+ return n != null && n.is_undo ? "undo" : (n == null ? void 0 : n.result) === "rejected" ? "reject" : (n == null ? void 0 : n.result) === "approved" ? "approve" : ((i = s.metadata) == null ? void 0 : i.operation) === "comment" ? "comment" : (($ = s.metadata) == null ? void 0 : $.operation) === "signal" ? "signal" : s.event === "created" ? "created" : j(s) ? "status" : "update";
77
+ }
78
+ function j(s) {
79
+ var i, $;
80
+ const n = (i = s.old_values) == null ? void 0 : i.approvable_status_name, l = ($ = s.new_values) == null ? void 0 : $.approvable_status_name;
81
+ return l !== void 0 && n !== l;
82
+ }
83
+ function R(s) {
84
+ var i, $, F, Z, ee, te;
85
+ const n = (i = s.metadata) == null ? void 0 : i.button;
86
+ if (n) {
87
+ const ae = n.text || n.label || n.id || "action";
88
+ return n.is_undo ? "Reverted the decision" : n.is_revision ? `Changed decision to ${ae}` : ae;
89
+ }
90
+ if ((($ = s.metadata) == null ? void 0 : $.operation) === "comment") return "Comment added";
91
+ if (((F = s.metadata) == null ? void 0 : F.operation) === "signal") return `Signal received: ${((ee = (Z = s.metadata) == null ? void 0 : Z.signal) == null ? void 0 : ee.name) || ""}`.trim();
92
+ if (s.event === "created") return "Step started";
93
+ const l = (te = s.new_values) == null ? void 0 : te.approvable_status_name;
94
+ return j(s) && l ? `Status set to ${l}` : "Step updated";
95
+ }
96
+ function p(s = {}) {
97
+ return s.type === "system" ? "System" : s.name ? s.name : s.email ? s.email : s.id ? s.type === "fake" ? `Test user ${s.id}` : `User ${s.id}` : s.type === "fake" ? "Test identity" : "Automated";
98
+ }
99
+ function u(s) {
100
+ const n = s.old_values || {}, l = s.new_values || {};
101
+ return Object.keys(A).filter((i) => i in n || i in l).map((i) => ({ key: i, label: A[i], oldValue: n[i], newValue: l[i] })).filter((i) => i.oldValue !== i.newValue);
102
+ }
103
+ function E(s) {
104
+ return s.oldValue !== void 0 && s.oldValue !== null && s.oldValue !== "";
105
+ }
106
+ function P(s) {
107
+ if (s == null || s === "") return "—";
108
+ if (typeof s == "boolean") return s ? "Yes" : "No";
109
+ if (Array.isArray(s)) return s.length ? s.join(", ") : "—";
110
+ const n = typeof s == "object" ? JSON.stringify(s) : String(s);
111
+ return n.length > 180 ? `${n.slice(0, 177)}…` : n;
112
+ }
113
+ function I(s) {
114
+ if (!s) return "";
115
+ const n = new Date(s);
116
+ return Number.isNaN(n.getTime()) ? s : new Intl.DateTimeFormat(void 0, {
117
+ dateStyle: "medium",
118
+ timeStyle: "short"
119
+ }).format(n);
120
+ }
121
+ async function M() {
122
+ var s, n;
123
+ if (!f.approvableId) {
124
+ o.value = [], m.value = !1, L.value = "The approval history is unavailable because the approvable has no id.";
125
+ return;
126
+ }
127
+ m.value = !0, L.value = "";
128
+ try {
129
+ const l = await k.fetchTimeline(f.approvableId, f.limit);
130
+ if (!l || l.status < 200 || l.status >= 300)
131
+ throw new Error(((s = l == null ? void 0 : l.data) == null ? void 0 : s.message) || "The audit timeline could not be loaded.");
132
+ const i = Array.isArray(l.data) ? l.data : (n = l.data) == null ? void 0 : n.data;
133
+ o.value = Array.isArray(i) ? i : [];
134
+ } catch (l) {
135
+ L.value = (l == null ? void 0 : l.message) || "The audit timeline could not be loaded.";
136
+ } finally {
137
+ m.value = !1;
138
+ }
139
+ }
140
+ const g = C(() => G(S.eventCount, { count: d.value.length }));
141
+ return se(d, (s) => h("loaded", s.length)), se(() => f.approvableId, M, { immediate: !0 }), _({ refresh: M }), (s, n) => (e(), a("section", {
142
+ class: N(["approvable-timeline", r.showHeader && "approvable-timeline--panel"])
143
+ }, [
144
+ r.showHeader ? (e(), a("div", Ke, [
145
+ t("p", Ue, c(w(S).history), 1),
146
+ t("h3", Fe, c(g.value), 1),
147
+ t("button", {
148
+ type: "button",
149
+ class: "approvable-timeline-refresh",
150
+ disabled: m.value,
151
+ onClick: M
152
+ }, c(m.value ? "Loading…" : "Refresh"), 9, Ge)
153
+ ])) : y("", !0),
154
+ m.value ? (e(), a("div", He, [...n[0] || (n[0] = [
155
+ t("span", {
156
+ class: "approvable-spinner",
157
+ "aria-hidden": "true"
158
+ }, null, -1),
159
+ z(" Loading approval history… ", -1)
160
+ ])])) : L.value ? (e(), a("p", ze, c(L.value), 1)) : d.value.length ? (e(), a(D, { key: 4 }, [
161
+ t("ol", We, [
162
+ (e(!0), a(D, null, q(d.value, (l) => (e(), a("li", {
163
+ key: l.id,
164
+ class: N(["approvable-timeline-item", {
165
+ "approvable-timeline-item--single-line": l.isSingleLine,
166
+ "approvable-timeline-item--quiet": l.isQuiet
167
+ }])
168
+ }, [
169
+ t("span", {
170
+ class: N(["approvable-timeline-marker", l.kindClass])
171
+ }, [
172
+ (e(), a("svg", {
173
+ fill: "none",
174
+ stroke: "currentColor",
175
+ "stroke-width": l.icon.width,
176
+ "stroke-linecap": "round",
177
+ "stroke-linejoin": "round",
178
+ viewBox: "0 0 16 16",
179
+ "aria-hidden": "true"
180
+ }, [
181
+ (e(!0), a(D, null, q(l.icon.paths, (i, $) => (e(), a("path", {
182
+ key: $,
183
+ d: i
184
+ }, null, 8, Je))), 128))
185
+ ], 8, Ye))
186
+ ], 2),
187
+ t("div", Xe, [
188
+ t("div", Ze, [
189
+ t("p", et, c(p(l.audit.actor)), 1),
190
+ t("p", tt, c(R(l.audit)), 1),
191
+ t("time", at, c(I(l.audit.created_at)), 1)
192
+ ]),
193
+ (e(!0), a(D, null, q(l.entries, (i) => (e(), a(D, {
194
+ key: i.id
195
+ }, [
196
+ (e(!0), a(D, null, q(u(i), ($) => (e(), a(D, {
197
+ key: `${i.id}-${$.key}`
198
+ }, [
199
+ $.key === "comment" ? (e(), a("p", st, c(P($.newValue)), 1)) : (e(), a("p", ot, [
200
+ t("span", lt, c($.label), 1),
201
+ E($) ? (e(), a(D, { key: 0 }, [
202
+ t("span", nt, c(P($.oldValue)), 1),
203
+ n[1] || (n[1] = t("span", { class: "approvable-timeline-arrow" }, "→", -1))
204
+ ], 64)) : y("", !0),
205
+ t("span", rt, c(P($.newValue)), 1)
206
+ ]))
207
+ ], 64))), 128))
208
+ ], 64))), 128))
209
+ ])
210
+ ], 2))), 128))
211
+ ]),
212
+ t("p", it, c(w(S).allEventsShown), 1)
213
+ ], 64)) : (e(), a("p", Qe, "No approval activity yet."))
214
+ ], 2));
215
+ }
216
+ }, pt = ["title"], ut = {
217
+ key: 0,
218
+ class: "approvable-popover-panel"
219
+ }, dt = {
220
+ key: 0,
221
+ class: "approvable-loading"
222
+ }, ct = { class: "approvable-popover-title" }, vt = {
223
+ key: 1,
224
+ class: "approvable-popover-meta"
225
+ }, mt = { class: "approvable-popover-author" }, bt = { class: "approvable-popover-actions" }, be = {
226
+ __name: "ApprovableStepComment",
227
+ props: {
228
+ approvableStep: {
229
+ required: !0
230
+ },
231
+ disabled: {
232
+ required: !0,
233
+ type: Boolean
234
+ }
235
+ },
236
+ emits: ["isLoading", "refresh"],
237
+ setup(r, { emit: _ }) {
238
+ const b = r, f = _, h = oe("rootRef"), S = oe("textareaRef"), k = T(!1), o = T(!1), m = T(null), L = C(() => V(b.approvableStep, "commented_by"));
239
+ function A() {
240
+ k.value ? v() : O();
241
+ }
242
+ function O() {
243
+ m.value = V(b.approvableStep, "comment"), k.value = !0, we(d);
244
+ }
245
+ function v() {
246
+ k.value = !1;
247
+ }
248
+ function d() {
249
+ const u = S.value;
250
+ u && (u.style.height = "auto", u.style.height = `${u.scrollHeight}px`);
251
+ }
252
+ function x(u) {
253
+ k.value && h.value && !h.value.contains(u.target) && v();
254
+ }
255
+ function j(u) {
256
+ u.key === "Escape" && v();
257
+ }
258
+ re(() => {
259
+ document.addEventListener("click", x), document.addEventListener("keydown", j);
260
+ }), ke(() => {
261
+ document.removeEventListener("click", x), document.removeEventListener("keydown", j);
262
+ });
263
+ const R = U();
264
+ async function p() {
265
+ if (!V(b.approvableStep, "comment") && !m.value) {
266
+ ne(R.commentRequired);
267
+ return;
268
+ }
269
+ o.value = !0, f("isLoading", !0);
270
+ const u = {
271
+ comment: m.value
272
+ }, E = await new ue().comment(b.approvableStep.id, u);
273
+ de(E) ? (ce(R.commentSaved), v(), f("refresh")) : ne(R.commentFailed), o.value = !1, f("isLoading", !1);
274
+ }
275
+ return (u, E) => (e(), a("div", {
276
+ ref_key: "rootRef",
277
+ ref: h,
278
+ class: "approvable-popover"
279
+ }, [
280
+ t("button", {
281
+ class: "approvable-btn",
282
+ title: w(R).comments,
283
+ type: "button",
284
+ onClick: A
285
+ }, [...E[1] || (E[1] = [
286
+ t("svg", {
287
+ xmlns: "http://www.w3.org/2000/svg",
288
+ width: "16",
289
+ height: "16",
290
+ viewBox: "0 0 24 24",
291
+ fill: "none",
292
+ stroke: "currentColor",
293
+ "stroke-width": "1.8",
294
+ "stroke-linecap": "round",
295
+ "stroke-linejoin": "round",
296
+ "aria-hidden": "true"
297
+ }, [
298
+ t("path", { d: "M8 9h8" }),
299
+ t("path", { d: "M8 13h6" }),
300
+ t("path", { d: "M18 4a3 3 0 0 1 3 3v8a3 3 0 0 1 -3 3h-5l-5 3v-3h-2a3 3 0 0 1 -3 -3v-8a3 3 0 0 1 3 -3h12z" })
301
+ ], -1)
302
+ ])], 8, pt),
303
+ k.value ? (e(), a("div", ut, [
304
+ o.value ? (e(), a("div", dt, [...E[2] || (E[2] = [
305
+ t("span", { class: "approvable-spinner" }, null, -1)
306
+ ])])) : y("", !0),
307
+ t("div", ct, c(w(R).comments), 1),
308
+ L.value ? (e(), a("div", vt, [
309
+ t("div", null, c(w(R).commentAuthor) + ":", 1),
310
+ t("div", mt, c(L.value), 1)
311
+ ])) : y("", !0),
312
+ r.disabled ? y("", !0) : (e(), a(D, { key: 2 }, [
313
+ ge(t("textarea", {
314
+ ref_key: "textareaRef",
315
+ ref: S,
316
+ "onUpdate:modelValue": E[0] || (E[0] = (P) => m.value = P),
317
+ class: "approvable-textarea",
318
+ rows: "1",
319
+ onInput: d
320
+ }, null, 544), [
321
+ [Se, m.value]
322
+ ]),
323
+ t("div", bt, [
324
+ t("button", {
325
+ class: "approvable-btn approvable-btn--primary",
326
+ type: "button",
327
+ onClick: p
328
+ }, c(w(R).save), 1)
329
+ ])
330
+ ], 64))
331
+ ])) : y("", !0)
332
+ ], 512));
333
+ }
334
+ };
335
+ function ca(r, _) {
336
+ return Oe(r, Ae(_));
337
+ }
338
+ const fe = Symbol("approvable.linkComponent");
339
+ function ft() {
340
+ return J(fe, "a");
341
+ }
342
+ function ht(r, _) {
343
+ return r === "a" ? { href: _ } : { to: _ };
344
+ }
345
+ const he = Symbol("approvable.iconRegistry");
346
+ function yt() {
347
+ return J(he, {});
348
+ }
349
+ const _t = {
350
+ key: 0,
351
+ "aria-hidden": "true",
352
+ fill: "none",
353
+ stroke: "currentColor",
354
+ "stroke-linecap": "round",
355
+ "stroke-linejoin": "round",
356
+ viewBox: "0 0 16 16"
357
+ }, kt = ["d", "stroke-width"], gt = { class: "approvable-step-body" }, St = { class: "approvable-step-line" }, wt = { class: "approvable-step-name" }, At = ["title"], $t = {
358
+ key: 1,
359
+ class: "approvable-step-spacer"
360
+ }, Ct = {
361
+ key: 0,
362
+ class: "approvable-step-status"
363
+ }, Et = { key: 0 }, Rt = {
364
+ key: 1,
365
+ class: "approvable-step-date"
366
+ }, Dt = {
367
+ key: 1,
368
+ class: "approvable-step-actions"
369
+ }, Lt = { class: "approvable-btn-group" }, xt = ["title", "onClick"], Ot = ["title", "onClick"], Mt = {
370
+ key: 0,
371
+ class: "approvable-btn-group"
372
+ }, It = {
373
+ key: 0,
374
+ class: "approvable-step-comment"
375
+ }, Tt = ["title"], Nt = ["aria-expanded"], ye = {
376
+ __name: "ApprovableStep",
377
+ props: {
378
+ value: {
379
+ type: Object,
380
+ required: !0
381
+ },
382
+ approvable: {
383
+ type: Object,
384
+ required: !0
385
+ },
386
+ resource: {
387
+ type: Object,
388
+ required: !0
389
+ }
390
+ },
391
+ emits: ["isLoading", "refresh"],
392
+ setup(r, { emit: _ }) {
393
+ const b = _, f = r, h = ft(), S = U(), k = T(!1), o = C(() => Me(f.value)), m = C(() => Ie(o.value.status)), L = C(() => o.value.buttons.length > 0 || !!f.value.can_comment), A = C(() => (!o.value.isActive || !L.value) && !!(o.value.statusName || o.value.performedAt)), O = C(() => ({
394
+ "approvable-step": !0,
395
+ "approvable-step--active": o.value.isActive,
396
+ // A step nobody has reached yet is dimmed; one with an outcome is not.
397
+ "approvable-step--pending": !o.value.isActive && !m.value,
398
+ [`approvable-step--${m.value}`]: !!m.value,
399
+ // Nothing wraps below the name, so the row can hold to a single line.
400
+ "approvable-step--single-line": !L.value && !o.value.comment.text
401
+ })), v = {
402
+ check: { d: "M4 8.4l2.8 2.8 5.4-6", width: 2.8 },
403
+ cross: { d: "M5.2 5.2l5.6 5.6M10.8 5.2l-5.6 5.6", width: 2.4 },
404
+ dash: { d: "M4.4 8h7.2", width: 2.2 }
405
+ }, d = {
406
+ check: "success",
407
+ cross: "danger",
408
+ dash: "muted",
409
+ ring: "ring",
410
+ pending: "pending"
411
+ }, x = C(() => Te(m.value, o.value.isActive)), j = C(() => v[x.value] ?? null), R = C(() => ({
412
+ "approvable-step-disc": !0,
413
+ [`approvable-step-disc--${d[x.value]}`]: !0
414
+ })), p = C(() => k.value ? o.value.comment.text : o.value.comment.preview), u = (I) => ({
415
+ "approvable-btn": !0,
416
+ // A button carrying only an icon collapses to a circle, so the row keeps its
417
+ // rhythm instead of stretching around an empty label.
418
+ "approvable-btn--icon": !I.text,
419
+ "approvable-btn--primary": I.result === "approved"
420
+ }), E = (I) => o.value.isActive ? Ne(I == null ? void 0 : I.action_ui) : null, P = async (I) => {
421
+ b("isLoading", !0);
422
+ const M = await Ve({
423
+ stepId: o.value.id,
424
+ button: I,
425
+ buttons: o.value.buttons
426
+ });
427
+ b("isLoading", !1), M.skipped || b("refresh");
428
+ };
429
+ return (I, M) => o.value.isVisible ? (e(), a("li", {
430
+ key: 0,
431
+ class: N(O.value)
432
+ }, [
433
+ t("span", {
434
+ class: N(R.value)
435
+ }, [
436
+ j.value ? (e(), a("svg", _t, [
437
+ t("path", {
438
+ d: j.value.d,
439
+ "stroke-width": j.value.width
440
+ }, null, 8, kt)
441
+ ])) : y("", !0)
442
+ ], 2),
443
+ t("div", gt, [
444
+ t("div", St, [
445
+ H(I.$slots, "approvableStepInfo", { step: r.value }, () => [
446
+ t("span", wt, c(o.value.approverName), 1)
447
+ ]),
448
+ H(I.$slots, "approvableStepRole", {
449
+ step: r.value,
450
+ role: o.value.approverRole
451
+ }, () => [
452
+ o.value.approverRole ? (e(), a("span", {
453
+ key: 0,
454
+ title: o.value.approverRole,
455
+ class: "approvable-step-role"
456
+ }, c(o.value.approverRole), 9, At)) : (e(), a("span", $t))
457
+ ]),
458
+ A.value ? (e(), a("span", Ct, [
459
+ o.value.statusName ? (e(), a("span", Et, c(o.value.statusName), 1)) : y("", !0),
460
+ o.value.performedAt ? (e(), a("time", Rt, c(o.value.performedAt), 1)) : y("", !0)
461
+ ])) : y("", !0),
462
+ L.value ? (e(), a("div", Dt, [
463
+ t("div", Lt, [
464
+ (e(!0), a(D, null, q(o.value.buttons, (g, s) => (e(), a(D, {
465
+ key: g.id ?? s
466
+ }, [
467
+ E(g) ? (e(), K(W(E(g)), {
468
+ key: 0,
469
+ "action-ui": g.action_ui,
470
+ approvable: r.approvable,
471
+ button: g,
472
+ buttons: [g],
473
+ complete: P,
474
+ resource: r.resource,
475
+ step: r.value,
476
+ onIsLoading: M[0] || (M[0] = (n) => b("isLoading", n)),
477
+ onRefresh: M[1] || (M[1] = (n) => b("refresh"))
478
+ }, null, 40, ["action-ui", "approvable", "button", "buttons", "resource", "step"])) : g.link ? (e(), K(W(w(h)), X({
479
+ key: 1,
480
+ ref_for: !0
481
+ }, w(ht)(w(h), g.link)), {
482
+ default: ie(() => [
483
+ t("button", {
484
+ title: g.tooltip,
485
+ class: N(u(g)),
486
+ type: "button",
487
+ onClick: (n) => P(g)
488
+ }, [
489
+ w(Y)(g.icon) ? (e(), a("i", {
490
+ key: 0,
491
+ class: N(g.icon)
492
+ }, null, 2)) : y("", !0)
493
+ ], 10, xt)
494
+ ]),
495
+ _: 2
496
+ }, 1040)) : (e(), a("button", {
497
+ key: 2,
498
+ title: g.tooltip,
499
+ class: N(u(g)),
500
+ type: "button",
501
+ onClick: (n) => P(g)
502
+ }, [
503
+ w(Y)(g.icon) ? (e(), a("i", {
504
+ key: 0,
505
+ class: N(g.icon)
506
+ }, null, 2)) : y("", !0),
507
+ z(" " + c(g.text), 1)
508
+ ], 10, Ot))
509
+ ], 64))), 128))
510
+ ]),
511
+ r.value.can_comment ? (e(), a("div", Mt, [
512
+ pe(be, {
513
+ "approvable-step": r.value,
514
+ disabled: !r.value.can_comment,
515
+ onRefresh: M[2] || (M[2] = (g) => b("refresh")),
516
+ onIsLoading: M[3] || (M[3] = (g) => b("isLoading", g))
517
+ }, null, 8, ["approvable-step", "disabled"])
518
+ ])) : y("", !0)
519
+ ])) : y("", !0)
520
+ ]),
521
+ o.value.comment.text ? (e(), a("p", It, [
522
+ t("span", {
523
+ title: o.value.comment.title
524
+ }, c(p.value), 9, Tt),
525
+ o.value.comment.isTrimmed ? (e(), a("button", {
526
+ key: 0,
527
+ type: "button",
528
+ class: "approvable-step-comment-more",
529
+ "aria-expanded": k.value,
530
+ onClick: M[4] || (M[4] = (g) => k.value = !k.value)
531
+ }, c(k.value ? w(S).showLess : w(S).showMore), 9, Nt)) : y("", !0)
532
+ ])) : y("", !0)
533
+ ])
534
+ ], 2)) : y("", !0);
535
+ }
536
+ }, _e = {
537
+ __name: "ApproveStatusInfo",
538
+ props: {
539
+ value: {
540
+ required: !0
541
+ },
542
+ label: {
543
+ default: null
544
+ }
545
+ },
546
+ setup(r) {
547
+ const _ = r, b = C(() => {
548
+ const h = V(_.value, "code", " - ");
549
+ return {
550
+ "approvable-badge": !0,
551
+ "approvable-badge--draft": [B.CODES.CODE_DRAFT].includes(h),
552
+ "approvable-badge--waiting": [B.CODES.CODE_WAITING].includes(h),
553
+ "approvable-badge--success": [B.CODES.CODE_APPROVED, B.CODES.CODE_VIEWED, B.CODES.CODE_NOTICED].includes(h),
554
+ "approvable-badge--danger": [B.CODES.CODE_REJECTED].includes(h),
555
+ "approvable-badge--muted": [B.CODES.CODE_EXPIRED, B.CODES.CODE_SOLVED].includes(h),
556
+ "approvable-badge--empty": h === " - "
557
+ };
558
+ }), f = C(() => _.label ? _.label : V(_.value, "name", " - "));
559
+ return (h, S) => (e(), a("span", {
560
+ class: N(b.value)
561
+ }, c(f.value), 3));
562
+ }
563
+ }, Vt = {
564
+ key: 0,
565
+ class: "approvable"
566
+ }, jt = {
567
+ key: 0,
568
+ class: "approvable-loading"
569
+ }, Pt = { class: "approvable-header" }, qt = { class: "approvable-sr-only" }, Bt = { class: "approvable-updated-at" }, Kt = ["title", "aria-label"], Ut = {
570
+ class: "approvable-sr-only",
571
+ "aria-live": "polite"
572
+ }, Ft = {
573
+ key: 1,
574
+ class: "approvable-footer"
575
+ }, Gt = { class: "approvable-dialog-header" }, Ht = { class: "approvable-dialog-eyebrow" }, zt = {
576
+ id: "approvable-history-title",
577
+ class: "approvable-dialog-title"
578
+ }, Qt = ["aria-label"], Wt = { class: "approvable-dialog-body" }, Yt = {
579
+ __name: "Approvable",
580
+ props: {
581
+ value: {},
582
+ showApprovableStatus: { type: Boolean, default: !0 },
583
+ title: { default: "Approval" },
584
+ isDirectionRow: { default: !1 }
585
+ },
586
+ emits: ["refresh", "isLoading"],
587
+ setup(r, { emit: _ }) {
588
+ const b = r, f = _, h = T(!1), S = T(null), k = T(!1), o = T(null), m = U(), L = [
589
+ { name: "118px", meta: "56px", delay: "0s", metaDelay: "0.15s" },
590
+ { name: "96px", meta: "72px", delay: "0.1s", metaDelay: "0.25s" },
591
+ { name: "78px", meta: "48px", delay: "0.2s", metaDelay: "0.35s" }
592
+ ], A = C(() => je(b.value)), O = C(() => o.value === null ? m.historyTitle : G(m.eventCount, { count: o.value })), v = C(() => h.value && !A.value.steps.length), d = C(() => ({
593
+ "approvable-steps": !0,
594
+ "approvable-steps--row": b.isDirectionRow
595
+ })), x = C(() => {
596
+ const { activeStepNumber: R, visibleStepCount: p, activeApproverName: u } = A.value;
597
+ if (!R || !p)
598
+ return null;
599
+ const E = G(m.stepProgress, {
600
+ current: R,
601
+ total: p
602
+ });
603
+ return u ? `${E} — ${G(m.awaitingApprover, { name: u })}` : E;
604
+ }), j = () => {
605
+ var R;
606
+ (R = S.value) == null || R.refresh(), f("refresh");
607
+ };
608
+ return (R, p) => A.value.hasApprovable ? (e(), a("div", Vt, [
609
+ h.value && A.value.steps.length ? (e(), a("div", jt, [...p[6] || (p[6] = [
610
+ t("span", { class: "approvable-spinner" }, null, -1)
611
+ ])])) : y("", !0),
612
+ t("div", Pt, [
613
+ t("h2", qt, c(r.title), 1),
614
+ v.value ? (e(), a(D, { key: 0 }, [
615
+ p[7] || (p[7] = t("span", {
616
+ "aria-hidden": "true",
617
+ class: "approvable-skeleton-bar approvable-skeleton-bar--pill"
618
+ }, null, -1)),
619
+ p[8] || (p[8] = t("span", { class: "approvable-skeleton-spacer" }, null, -1)),
620
+ p[9] || (p[9] = t("span", {
621
+ "aria-hidden": "true",
622
+ class: "approvable-skeleton-bar approvable-skeleton-bar--soft",
623
+ style: { width: "104px", "animation-delay": "0.2s" }
624
+ }, null, -1))
625
+ ], 64)) : (e(), a(D, { key: 1 }, [
626
+ r.showApprovableStatus ? (e(), K(_e, {
627
+ key: 0,
628
+ label: A.value.statusName,
629
+ value: A.value.status
630
+ }, null, 8, ["label", "value"])) : y("", !0),
631
+ t("span", Bt, c(A.value.updatedAt), 1),
632
+ A.value.id ? (e(), a("button", {
633
+ key: 1,
634
+ type: "button",
635
+ class: "approvable-history-btn",
636
+ title: w(m).historyTitle,
637
+ "aria-label": w(m).historyTitle,
638
+ onClick: p[0] || (p[0] = (u) => k.value = !0)
639
+ }, c(w(m).history), 9, Kt)) : y("", !0)
640
+ ], 64))
641
+ ]),
642
+ v.value ? (e(), a(D, { key: 1 }, [
643
+ t("span", Ut, c(w(m).loadingStatus), 1),
644
+ (e(), a(D, null, q(L, (u) => t("div", {
645
+ key: u.delay,
646
+ "aria-hidden": "true",
647
+ class: "approvable-skeleton-row"
648
+ }, [
649
+ t("span", {
650
+ class: "approvable-skeleton-disc",
651
+ style: Q({ animationDelay: u.delay })
652
+ }, null, 4),
653
+ t("span", {
654
+ class: "approvable-skeleton-bar",
655
+ style: Q({ width: u.name, animationDelay: u.delay })
656
+ }, null, 4),
657
+ p[10] || (p[10] = t("span", { class: "approvable-skeleton-spacer" }, null, -1)),
658
+ t("span", {
659
+ class: "approvable-skeleton-bar approvable-skeleton-bar--soft",
660
+ style: Q({ width: u.meta, animationDelay: u.metaDelay })
661
+ }, null, 4)
662
+ ])), 64)),
663
+ p[11] || (p[11] = t("div", {
664
+ class: "approvable-footer",
665
+ "aria-hidden": "true"
666
+ }, [
667
+ t("span", {
668
+ class: "approvable-skeleton-bar approvable-skeleton-bar--soft",
669
+ style: { display: "block", width: "132px" }
670
+ })
671
+ ], -1))
672
+ ], 64)) : (e(), a(D, { key: 2 }, [
673
+ A.value.steps.length ? (e(), a("ol", {
674
+ key: 0,
675
+ class: N(d.value)
676
+ }, [
677
+ (e(!0), a(D, null, q(A.value.steps, (u) => (e(), K(ye, {
678
+ key: u.id,
679
+ approvable: A.value.approvable,
680
+ resource: r.value,
681
+ value: u,
682
+ onIsLoading: p[1] || (p[1] = (E) => h.value = E),
683
+ onRefresh: j
684
+ }, $e({ _: 2 }, [
685
+ q(Object.keys(R.$slots), (E) => ({
686
+ name: E,
687
+ fn: ie((P) => [
688
+ H(R.$slots, E, X({ ref_for: !0 }, P ?? {}))
689
+ ])
690
+ }))
691
+ ]), 1032, ["approvable", "resource", "value"]))), 128))
692
+ ], 2)) : y("", !0),
693
+ x.value ? (e(), a("p", Ft, c(x.value), 1)) : y("", !0)
694
+ ], 64)),
695
+ (e(), K(Ce, { to: "body" }, [
696
+ k.value ? (e(), a("div", {
697
+ key: 0,
698
+ class: "approvable-dialog-backdrop",
699
+ onClick: p[5] || (p[5] = Ee((u) => k.value = !1, ["self"]))
700
+ }, [
701
+ t("section", {
702
+ role: "dialog",
703
+ "aria-modal": "true",
704
+ "aria-labelledby": "approvable-history-title",
705
+ class: "approvable-dialog",
706
+ onKeydown: p[4] || (p[4] = Re((u) => k.value = !1, ["esc"]))
707
+ }, [
708
+ t("header", Gt, [
709
+ t("p", Ht, [
710
+ p[12] || (p[12] = t("svg", {
711
+ "aria-hidden": "true",
712
+ fill: "none",
713
+ stroke: "currentColor",
714
+ "stroke-linecap": "round",
715
+ "stroke-linejoin": "round",
716
+ "stroke-width": "2",
717
+ viewBox: "0 0 16 16"
718
+ }, [
719
+ t("path", { d: "M9.6 4.5 6 8l3.6 3.5" })
720
+ ], -1)),
721
+ z(" " + c(w(m).history), 1)
722
+ ]),
723
+ t("h2", zt, c(O.value), 1),
724
+ t("button", {
725
+ type: "button",
726
+ class: "approvable-dialog-close",
727
+ "aria-label": w(m).historyClose,
728
+ onClick: p[2] || (p[2] = (u) => k.value = !1)
729
+ }, [...p[13] || (p[13] = [
730
+ t("svg", {
731
+ "aria-hidden": "true",
732
+ class: "approvable-icon",
733
+ fill: "none",
734
+ stroke: "currentColor",
735
+ "stroke-linecap": "round",
736
+ "stroke-width": "2",
737
+ viewBox: "0 0 16 16"
738
+ }, [
739
+ t("path", { d: "m5.2 5.2 5.6 5.6M10.8 5.2l-5.6 5.6" })
740
+ ], -1)
741
+ ])], 8, Qt)
742
+ ]),
743
+ t("div", Wt, [
744
+ pe(me, {
745
+ ref_key: "auditTimeline",
746
+ ref: S,
747
+ "approvable-id": A.value.id,
748
+ "show-header": !1,
749
+ onLoaded: p[3] || (p[3] = (u) => o.value = u)
750
+ }, null, 8, ["approvable-id"])
751
+ ])
752
+ ], 32)
753
+ ])) : y("", !0)
754
+ ]))
755
+ ])) : y("", !0);
756
+ }
757
+ }, Jt = {
758
+ key: 0,
759
+ class: "approvable-actions"
760
+ }, Xt = { class: "approvable-actions-list" }, Zt = ["title", "onClick"], ea = ["src"], ta = {
761
+ __name: "ApprovableButtons",
762
+ props: {
763
+ value: {
764
+ required: !0
765
+ }
766
+ },
767
+ emits: ["isLoading", "refresh"],
768
+ setup(r, { emit: _ }) {
769
+ const b = r, f = _, h = T(!1), S = C(() => V(b.value, "buttons", [])), k = C(() => S.value ? S.value.length > 0 : !1), o = yt(), m = U(), L = (O) => {
770
+ let v = V(b.value, "id");
771
+ v && A(v, O);
772
+ }, A = async (O, v) => {
773
+ f("isLoading", !0), h.value = !0;
774
+ const d = await new ue().updateApproveStatus(O, v);
775
+ de(d) && ce(m.actionSucceeded), f("isLoading", !1), f("refresh");
776
+ };
777
+ return (O, v) => k.value ? (e(), a("div", Jt, [
778
+ v[0] || (v[0] = t("hr", { class: "approvable-divider" }, null, -1)),
779
+ t("div", Xt, [
780
+ (e(!0), a(D, null, q(S.value, (d) => (e(), a("button", {
781
+ key: d.code,
782
+ title: d.tooltip,
783
+ class: "approvable-btn",
784
+ type: "button",
785
+ onClick: (x) => L(d)
786
+ }, [
787
+ H(O.$slots, "icon", { button: d }, () => [
788
+ w(Pe)(w(o), d.icon) ? (e(), K(W(w(o)[d.icon]), {
789
+ key: 0,
790
+ class: "approvable-btn-icon"
791
+ })) : w(qe)(d.icon) ? (e(), a("img", {
792
+ key: 1,
793
+ src: d.icon,
794
+ alt: "",
795
+ class: "approvable-btn-icon"
796
+ }, null, 8, ea)) : w(Y)(d.icon) ? (e(), a("i", {
797
+ key: 2,
798
+ class: N(d.icon)
799
+ }, null, 2)) : y("", !0)
800
+ ]),
801
+ z(" " + c(d.text), 1)
802
+ ], 8, Zt))), 128))
803
+ ])
804
+ ])) : y("", !0);
805
+ }
806
+ }, aa = { class: "approvable-select" }, sa = {
807
+ key: 0,
808
+ class: "approvable-select-label"
809
+ }, oa = ["value"], la = ["value"], na = /* @__PURE__ */ Object.assign({
810
+ inheritAttrs: !1
811
+ }, {
812
+ __name: "ApprovableStatusSelect",
813
+ props: /* @__PURE__ */ le({
814
+ getList: {},
815
+ label: {
816
+ default: "Status"
817
+ }
818
+ }, {
819
+ modelValue: {},
820
+ modelModifiers: {}
821
+ }),
822
+ emits: /* @__PURE__ */ le(["mounted"], ["update:modelValue"]),
823
+ setup(r, { emit: _ }) {
824
+ const b = _, f = De(r, "modelValue"), h = r, S = T([]), k = async (v) => {
825
+ let d = [{ field: "search", value: v }];
826
+ return await new Be().fetchAll({ filters: d });
827
+ }, o = (v) => String(V(v, "id") ?? V(v, "code", "")), m = (v) => V(v, "name") ?? V(v, "text", ""), L = C(() => f.value ? o(f.value) : ""), A = (v) => {
828
+ const d = v.target.value;
829
+ f.value = S.value.find((x) => o(x) === d) ?? null;
830
+ }, O = async (v = null) => {
831
+ const d = await (h.getList ?? k)(v);
832
+ S.value = Array.isArray(d) ? d : [];
833
+ };
834
+ return re(async () => {
835
+ await O(), b("mounted", { refresh: O, options: S });
836
+ }), (v, d) => (e(), a("label", aa, [
837
+ r.label ? (e(), a("span", sa, c(r.label), 1)) : y("", !0),
838
+ t("select", X({
839
+ value: L.value,
840
+ class: "approvable-select-input"
841
+ }, v.$attrs, { onChange: A }), [
842
+ d[0] || (d[0] = t("option", { value: "" }, "-", -1)),
843
+ (e(!0), a(D, null, q(S.value, (x) => (e(), a("option", {
844
+ key: o(x),
845
+ value: o(x)
846
+ }, c(m(x)), 9, la))), 128))
847
+ ], 16, oa)
848
+ ]));
849
+ }
850
+ }), ra = { class: "approvable-select-option" }, ia = {
851
+ __name: "ApprovableStatusSelectOption",
852
+ props: {
853
+ value: {}
854
+ },
855
+ setup(r) {
856
+ const _ = r, b = C(() => V(_.value, "name"));
857
+ return (f, h) => (e(), a("div", ra, [
858
+ t("span", null, c(b.value), 1)
859
+ ]));
860
+ }
861
+ }, pa = {
862
+ Approvable: Yt,
863
+ ApprovableStep: ye,
864
+ ApprovableButtons: ta,
865
+ ApprovableStepComment: be,
866
+ ApprovableAuditTimeline: me,
867
+ ApproveStatusInfo: _e,
868
+ ApprovableStatusSelect: na,
869
+ ApprovableStatusSelectOption: ia
870
+ }, va = {
871
+ install(r, { linkComponent: _ = null, icons: b = null, messages: f = null, register: h = !0 } = {}) {
872
+ if (_ && r.provide(fe, _), b && r.provide(he, b), f && r.provide(ve, f), h)
873
+ for (const [S, k] of Object.entries(pa))
874
+ r.component(S, k);
875
+ }
876
+ };
877
+ export {
878
+ he as APPROVABLE_ICON_REGISTRY,
879
+ fe as APPROVABLE_LINK_COMPONENT,
880
+ ve as APPROVABLE_MESSAGES,
881
+ Yt as Approvable,
882
+ me as ApprovableAuditTimeline,
883
+ ta as ApprovableButtons,
884
+ na as ApprovableStatusSelect,
885
+ ia as ApprovableStatusSelectOption,
886
+ ye as ApprovableStep,
887
+ be as ApprovableStepComment,
888
+ _e as ApproveStatusInfo,
889
+ fa as approvableActionRenderer,
890
+ ha as approvableActionSlotName,
891
+ va as default,
892
+ ya as isClassIcon,
893
+ _a as isRegisteredIcon,
894
+ ka as isUrlIcon,
895
+ ht as linkProps,
896
+ ca as registerApprovableActionRenderer,
897
+ ga as unregisterApprovableActionRenderer,
898
+ yt as useIconRegistry,
899
+ ft as useLinkComponent,
900
+ U as useMessages
901
+ };
902
+ //# sourceMappingURL=approvable-vue.mjs.map