@vss-software/ui 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.
- package/README.md +1255 -0
- package/dist/index.d.ts +73 -0
- package/dist/lumen-ui.css +1 -0
- package/dist/lumen-ui.js +3965 -0
- package/package.json +62 -0
package/dist/lumen-ui.js
ADDED
|
@@ -0,0 +1,3965 @@
|
|
|
1
|
+
import { computed as b, openBlock as n, createElementBlock as a, normalizeClass as w, toDisplayString as y, createCommentVNode as c, createElementVNode as l, renderSlot as B, useAttrs as Ae, useModel as G, ref as E, useId as q, mergeProps as be, createTextVNode as M, withDirectives as ee, vModelDynamic as _e, mergeModels as te, vModelText as ge, Fragment as z, renderList as j, withKeys as Q, withModifiers as U, normalizeStyle as H, watch as ie, createBlock as P, resolveDynamicComponent as Be, reactive as Ee, Teleport as ye, createVNode as A, TransitionGroup as Ie, withCtx as T, unref as R, onMounted as ve, onBeforeUnmount as me, nextTick as pe, createStaticVNode as ze, provide as Te, inject as he, onUnmounted as Me, resolveComponent as xe, Transition as Z, vShow as je, createSlots as Oe } from "vue";
|
|
2
|
+
import { format as se, startOfMonth as J, endOfMonth as De, startOfWeek as Ve, endOfWeek as Pe, eachDayOfInterval as Re, parseISO as Ne, subMonths as Fe, addMonths as qe, isSameDay as Ke, isSameMonth as Ue, isToday as He, isWithinInterval as Ze } from "date-fns";
|
|
3
|
+
import { de as We } from "date-fns/locale";
|
|
4
|
+
import { AlertCircle as Ge, X as Xe, TrendingUp as Je, TrendingDown as Ye } from "lucide-vue-next";
|
|
5
|
+
import { useRoute as Qe } from "vue-router";
|
|
6
|
+
import { Line as et, Bar as tt, Doughnut as nt } from "vue-chartjs";
|
|
7
|
+
import { Chart as ue, CategoryScale as we, LinearScale as ke, PointElement as at, LineElement as rt, Tooltip as de, Legend as ce, Filler as st, BarElement as lt, ArcElement as ot, Title as it } from "chart.js";
|
|
8
|
+
const ut = ["type", "disabled", "aria-busy", "aria-disabled"], dt = {
|
|
9
|
+
key: 0,
|
|
10
|
+
class: "sr-only",
|
|
11
|
+
"aria-live": "polite"
|
|
12
|
+
}, K = /* @__PURE__ */ Object.assign({ name: "LuButton" }, {
|
|
13
|
+
__name: "LuButton",
|
|
14
|
+
props: {
|
|
15
|
+
/**
|
|
16
|
+
* Visual style variant.
|
|
17
|
+
* @type {'primary' | 'secondary' | 'danger' | 'ghost' | 'icon'}
|
|
18
|
+
*/
|
|
19
|
+
variant: {
|
|
20
|
+
type: String,
|
|
21
|
+
default: "primary",
|
|
22
|
+
validator: (e) => ["primary", "secondary", "danger", "ghost", "icon"].includes(e)
|
|
23
|
+
},
|
|
24
|
+
/**
|
|
25
|
+
* Button size. sm=32px, md=40px, lg=48px height.
|
|
26
|
+
* @type {'sm' | 'md' | 'lg'}
|
|
27
|
+
*/
|
|
28
|
+
size: {
|
|
29
|
+
type: String,
|
|
30
|
+
default: "md",
|
|
31
|
+
validator: (e) => ["sm", "md", "lg"].includes(e)
|
|
32
|
+
},
|
|
33
|
+
/**
|
|
34
|
+
* Whether the button is disabled.
|
|
35
|
+
*/
|
|
36
|
+
disabled: {
|
|
37
|
+
type: Boolean,
|
|
38
|
+
default: !1
|
|
39
|
+
},
|
|
40
|
+
/**
|
|
41
|
+
* Whether to show a loading spinner and disable interaction.
|
|
42
|
+
*/
|
|
43
|
+
loading: {
|
|
44
|
+
type: Boolean,
|
|
45
|
+
default: !1
|
|
46
|
+
},
|
|
47
|
+
/**
|
|
48
|
+
* HTML button type attribute.
|
|
49
|
+
* @type {'button' | 'submit' | 'reset'}
|
|
50
|
+
*/
|
|
51
|
+
type: {
|
|
52
|
+
type: String,
|
|
53
|
+
default: "button",
|
|
54
|
+
validator: (e) => ["button", "submit", "reset"].includes(e)
|
|
55
|
+
},
|
|
56
|
+
/**
|
|
57
|
+
* Accessible loading announcement text for screen readers.
|
|
58
|
+
* Override for i18n support.
|
|
59
|
+
* @type {string}
|
|
60
|
+
*/
|
|
61
|
+
loadingText: {
|
|
62
|
+
type: String,
|
|
63
|
+
default: "Wird geladen…"
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
setup(e) {
|
|
67
|
+
const r = e, t = {
|
|
68
|
+
primary: "bg-teal-500 text-white hover:bg-teal-700 active:bg-teal-700 focus-visible:ring-teal-500",
|
|
69
|
+
secondary: "bg-white text-gray-900 border border-lu-border hover:bg-gray-50 active:bg-gray-100 focus-visible:ring-teal-500",
|
|
70
|
+
danger: "bg-red-500 text-white hover:bg-red-600 active:bg-red-700 focus-visible:ring-red-500",
|
|
71
|
+
ghost: "bg-transparent text-teal-500 hover:bg-teal-500/10 active:bg-teal-500/20 focus-visible:ring-teal-500",
|
|
72
|
+
icon: "bg-gray-100 text-gray-600 hover:bg-gray-200 active:bg-gray-300 focus-visible:ring-teal-500 px-0!"
|
|
73
|
+
}, o = {
|
|
74
|
+
sm: "h-8 px-3 text-xs gap-1",
|
|
75
|
+
md: "h-10 px-4 text-sm gap-2",
|
|
76
|
+
lg: "h-12 px-6 text-base gap-2"
|
|
77
|
+
}, s = {
|
|
78
|
+
sm: "w-8 h-8",
|
|
79
|
+
md: "w-10 h-10",
|
|
80
|
+
lg: "w-12 h-12"
|
|
81
|
+
}, i = {
|
|
82
|
+
sm: "h-3 w-3",
|
|
83
|
+
md: "h-4 w-4",
|
|
84
|
+
lg: "h-5 w-5"
|
|
85
|
+
}, u = b(() => [
|
|
86
|
+
"inline-flex items-center justify-center font-medium transition-colors duration-150",
|
|
87
|
+
"rounded-input",
|
|
88
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2",
|
|
89
|
+
"disabled:opacity-50",
|
|
90
|
+
r.loading ? "cursor-wait" : "disabled:cursor-not-allowed",
|
|
91
|
+
t[r.variant],
|
|
92
|
+
r.variant === "icon" ? s[r.size] : o[r.size]
|
|
93
|
+
]), g = b(() => ["animate-spin shrink-0", i[r.size]]);
|
|
94
|
+
return (d, v) => (n(), a("button", {
|
|
95
|
+
type: e.type,
|
|
96
|
+
disabled: e.disabled || e.loading,
|
|
97
|
+
class: w(u.value),
|
|
98
|
+
"aria-busy": e.loading || void 0,
|
|
99
|
+
"aria-disabled": e.disabled || e.loading || void 0
|
|
100
|
+
}, [
|
|
101
|
+
e.loading ? (n(), a("span", dt, y(e.loadingText), 1)) : c("", !0),
|
|
102
|
+
e.loading ? (n(), a("svg", {
|
|
103
|
+
key: 1,
|
|
104
|
+
class: w(g.value),
|
|
105
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
106
|
+
viewBox: "0 0 24 24",
|
|
107
|
+
fill: "none",
|
|
108
|
+
stroke: "currentColor",
|
|
109
|
+
"stroke-width": "2",
|
|
110
|
+
"stroke-linecap": "round",
|
|
111
|
+
"stroke-linejoin": "round",
|
|
112
|
+
"aria-hidden": "true"
|
|
113
|
+
}, [...v[0] || (v[0] = [
|
|
114
|
+
l("path", { d: "M21 12a9 9 0 1 1-6.219-8.56" }, null, -1)
|
|
115
|
+
])], 2)) : c("", !0),
|
|
116
|
+
e.loading ? c("", !0) : B(d.$slots, "icon-left", { key: 2 }),
|
|
117
|
+
B(d.$slots, "default"),
|
|
118
|
+
e.loading ? c("", !0) : B(d.$slots, "icon-right", { key: 3 })
|
|
119
|
+
], 10, ut));
|
|
120
|
+
}
|
|
121
|
+
}), ct = {
|
|
122
|
+
key: 0,
|
|
123
|
+
class: "text-red-500 ml-0.5"
|
|
124
|
+
}, ft = {
|
|
125
|
+
key: 0,
|
|
126
|
+
class: "pl-3 text-sm text-gray-500 select-none shrink-0"
|
|
127
|
+
}, bt = ["type", "placeholder", "disabled", "readonly", "required", "aria-invalid", "aria-describedby"], gt = {
|
|
128
|
+
key: 1,
|
|
129
|
+
class: "pr-3 text-sm text-gray-500 select-none shrink-0"
|
|
130
|
+
}, yt = ["aria-label", "disabled"], vt = {
|
|
131
|
+
key: 0,
|
|
132
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
133
|
+
class: "h-5 w-5",
|
|
134
|
+
viewBox: "0 0 24 24",
|
|
135
|
+
fill: "none",
|
|
136
|
+
stroke: "currentColor",
|
|
137
|
+
"stroke-width": "2",
|
|
138
|
+
"stroke-linecap": "round",
|
|
139
|
+
"stroke-linejoin": "round",
|
|
140
|
+
"aria-hidden": "true"
|
|
141
|
+
}, mt = {
|
|
142
|
+
key: 1,
|
|
143
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
144
|
+
class: "h-5 w-5",
|
|
145
|
+
viewBox: "0 0 24 24",
|
|
146
|
+
fill: "none",
|
|
147
|
+
stroke: "currentColor",
|
|
148
|
+
"stroke-width": "2",
|
|
149
|
+
"stroke-linecap": "round",
|
|
150
|
+
"stroke-linejoin": "round",
|
|
151
|
+
"aria-hidden": "true"
|
|
152
|
+
}, pt = ["id"], ht = ["id"], xt = /* @__PURE__ */ Object.assign({ inheritAttrs: !1 }, {
|
|
153
|
+
__name: "LuInput",
|
|
154
|
+
props: /* @__PURE__ */ te({
|
|
155
|
+
/**
|
|
156
|
+
* Input type attribute.
|
|
157
|
+
* @type {'text' | 'password' | 'number' | 'email' | 'search'}
|
|
158
|
+
*/
|
|
159
|
+
type: {
|
|
160
|
+
type: String,
|
|
161
|
+
default: "text",
|
|
162
|
+
validator: (e) => ["text", "password", "number", "email", "search"].includes(e)
|
|
163
|
+
},
|
|
164
|
+
/**
|
|
165
|
+
* Label text displayed above the input.
|
|
166
|
+
*/
|
|
167
|
+
label: {
|
|
168
|
+
type: String,
|
|
169
|
+
default: ""
|
|
170
|
+
},
|
|
171
|
+
/**
|
|
172
|
+
* Placeholder text displayed when the input is empty.
|
|
173
|
+
*/
|
|
174
|
+
placeholder: {
|
|
175
|
+
type: String,
|
|
176
|
+
default: ""
|
|
177
|
+
},
|
|
178
|
+
/**
|
|
179
|
+
* Error message displayed below the input. Triggers red border styling.
|
|
180
|
+
*/
|
|
181
|
+
error: {
|
|
182
|
+
type: String,
|
|
183
|
+
default: ""
|
|
184
|
+
},
|
|
185
|
+
/**
|
|
186
|
+
* Hint text displayed below the input in gray.
|
|
187
|
+
*/
|
|
188
|
+
hint: {
|
|
189
|
+
type: String,
|
|
190
|
+
default: ""
|
|
191
|
+
},
|
|
192
|
+
/**
|
|
193
|
+
* Prefix text displayed inside the input on the left (e.g. 'EUR').
|
|
194
|
+
*/
|
|
195
|
+
prefix: {
|
|
196
|
+
type: String,
|
|
197
|
+
default: ""
|
|
198
|
+
},
|
|
199
|
+
/**
|
|
200
|
+
* Suffix text displayed inside the input on the right.
|
|
201
|
+
*/
|
|
202
|
+
suffix: {
|
|
203
|
+
type: String,
|
|
204
|
+
default: ""
|
|
205
|
+
},
|
|
206
|
+
/**
|
|
207
|
+
* Whether the input is disabled.
|
|
208
|
+
*/
|
|
209
|
+
disabled: {
|
|
210
|
+
type: Boolean,
|
|
211
|
+
default: !1
|
|
212
|
+
},
|
|
213
|
+
/**
|
|
214
|
+
* Whether the input is read-only.
|
|
215
|
+
*/
|
|
216
|
+
readonly: {
|
|
217
|
+
type: Boolean,
|
|
218
|
+
default: !1
|
|
219
|
+
},
|
|
220
|
+
/**
|
|
221
|
+
* Whether the input is required.
|
|
222
|
+
*/
|
|
223
|
+
required: {
|
|
224
|
+
type: Boolean,
|
|
225
|
+
default: !1
|
|
226
|
+
}
|
|
227
|
+
}, {
|
|
228
|
+
modelValue: { type: [String, Number], default: "" },
|
|
229
|
+
modelModifiers: {}
|
|
230
|
+
}),
|
|
231
|
+
emits: ["update:modelValue"],
|
|
232
|
+
setup(e, { expose: r }) {
|
|
233
|
+
const t = Ae(), o = b(
|
|
234
|
+
() => Object.fromEntries(Object.entries(t).filter(([h]) => h !== "class" && h !== "style"))
|
|
235
|
+
), s = b(
|
|
236
|
+
() => Object.fromEntries(Object.entries(t).filter(([h]) => h === "class" || h === "style"))
|
|
237
|
+
), i = G(e, "modelValue"), u = e, g = E(null), d = E(!1), v = b(() => u.type === "password" && d.value ? "text" : u.type), m = b(() => u.type === "password"), f = `lu-input-${q()}`, p = b(() => [
|
|
238
|
+
"flex items-center w-full rounded-input border bg-white transition-colors",
|
|
239
|
+
"duration-150",
|
|
240
|
+
"focus-within:ring-2 focus-within:ring-offset-[2px]",
|
|
241
|
+
u.error ? "border-red-500 focus-within:ring-red-500" : "border-lu-border focus-within:ring-teal-500 focus-within:border-teal-500",
|
|
242
|
+
u.disabled ? "opacity-50 cursor-not-allowed bg-gray-50" : ""
|
|
243
|
+
]), x = b(() => [
|
|
244
|
+
"w-full bg-transparent text-sm text-gray-900 placeholder-gray-400",
|
|
245
|
+
"outline-none py-2",
|
|
246
|
+
"disabled:cursor-not-allowed",
|
|
247
|
+
u.prefix ? "pl-1" : "pl-3",
|
|
248
|
+
u.suffix || m.value ? "pr-1" : "pr-3"
|
|
249
|
+
]);
|
|
250
|
+
function S() {
|
|
251
|
+
d.value = !d.value;
|
|
252
|
+
}
|
|
253
|
+
function k() {
|
|
254
|
+
var h;
|
|
255
|
+
(h = g.value) == null || h.focus();
|
|
256
|
+
}
|
|
257
|
+
return r({ focus: k }), (h, I) => (n(), a("div", be({ class: "flex flex-col gap-1" }, s.value), [
|
|
258
|
+
e.label ? (n(), a("label", {
|
|
259
|
+
key: 0,
|
|
260
|
+
for: f,
|
|
261
|
+
class: "text-sm font-medium text-gray-700"
|
|
262
|
+
}, [
|
|
263
|
+
M(y(e.label) + " ", 1),
|
|
264
|
+
e.required ? (n(), a("span", ct, "*")) : c("", !0)
|
|
265
|
+
])) : c("", !0),
|
|
266
|
+
l("div", {
|
|
267
|
+
class: w(p.value)
|
|
268
|
+
}, [
|
|
269
|
+
e.prefix ? (n(), a("span", ft, y(e.prefix), 1)) : c("", !0),
|
|
270
|
+
ee(l("input", be({
|
|
271
|
+
ref_key: "inputRef",
|
|
272
|
+
ref: g,
|
|
273
|
+
id: f,
|
|
274
|
+
"onUpdate:modelValue": I[0] || (I[0] = (F) => i.value = F),
|
|
275
|
+
type: v.value,
|
|
276
|
+
placeholder: e.placeholder,
|
|
277
|
+
disabled: e.disabled,
|
|
278
|
+
readonly: e.readonly,
|
|
279
|
+
required: e.required,
|
|
280
|
+
class: x.value,
|
|
281
|
+
"aria-invalid": !!e.error || void 0,
|
|
282
|
+
"aria-describedby": e.error ? `${f}-error` : e.hint ? `${f}-hint` : void 0
|
|
283
|
+
}, o.value), null, 16, bt), [
|
|
284
|
+
[_e, i.value]
|
|
285
|
+
]),
|
|
286
|
+
e.suffix && !m.value ? (n(), a("span", gt, y(e.suffix), 1)) : c("", !0),
|
|
287
|
+
m.value ? (n(), a("button", {
|
|
288
|
+
key: 2,
|
|
289
|
+
type: "button",
|
|
290
|
+
class: "pr-3 text-gray-400 hover:text-gray-600 transition-colors duration-150 focus:outline-none focus-visible:ring-2 focus-visible:ring-teal-500 focus-visible:ring-offset-[2px] rounded shrink-0",
|
|
291
|
+
"aria-label": d.value ? "Passwort verbergen" : "Passwort anzeigen",
|
|
292
|
+
disabled: e.disabled,
|
|
293
|
+
onClick: S
|
|
294
|
+
}, [
|
|
295
|
+
d.value ? (n(), a("svg", mt, [...I[2] || (I[2] = [
|
|
296
|
+
l("path", { d: "M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94" }, null, -1),
|
|
297
|
+
l("path", { d: "M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19" }, null, -1),
|
|
298
|
+
l("path", { d: "M14.12 14.12a3 3 0 1 1-4.24-4.24" }, null, -1),
|
|
299
|
+
l("line", {
|
|
300
|
+
x1: "1",
|
|
301
|
+
y1: "1",
|
|
302
|
+
x2: "23",
|
|
303
|
+
y2: "23"
|
|
304
|
+
}, null, -1)
|
|
305
|
+
])])) : (n(), a("svg", vt, [...I[1] || (I[1] = [
|
|
306
|
+
l("path", { d: "M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z" }, null, -1),
|
|
307
|
+
l("circle", {
|
|
308
|
+
cx: "12",
|
|
309
|
+
cy: "12",
|
|
310
|
+
r: "3"
|
|
311
|
+
}, null, -1)
|
|
312
|
+
])]))
|
|
313
|
+
], 8, yt)) : c("", !0)
|
|
314
|
+
], 2),
|
|
315
|
+
e.error ? (n(), a("p", {
|
|
316
|
+
key: 1,
|
|
317
|
+
id: `${f}-error`,
|
|
318
|
+
class: "text-xs text-red-500",
|
|
319
|
+
role: "alert"
|
|
320
|
+
}, y(e.error), 9, pt)) : e.hint ? (n(), a("p", {
|
|
321
|
+
key: 2,
|
|
322
|
+
id: `${f}-hint`,
|
|
323
|
+
class: "text-xs text-gray-400"
|
|
324
|
+
}, y(e.hint), 9, ht)) : c("", !0)
|
|
325
|
+
], 16));
|
|
326
|
+
}
|
|
327
|
+
}), wt = { class: "flex flex-col gap-1" }, kt = {
|
|
328
|
+
key: 0,
|
|
329
|
+
class: "text-red-500 ml-0.5"
|
|
330
|
+
}, $t = ["placeholder", "disabled", "readonly", "required", "rows", "aria-invalid", "aria-describedby"], St = ["id"], Ct = ["id"], Lt = {
|
|
331
|
+
__name: "LuTextarea",
|
|
332
|
+
props: /* @__PURE__ */ te({
|
|
333
|
+
/**
|
|
334
|
+
* Label text displayed above the textarea.
|
|
335
|
+
*/
|
|
336
|
+
label: {
|
|
337
|
+
type: String,
|
|
338
|
+
default: ""
|
|
339
|
+
},
|
|
340
|
+
/**
|
|
341
|
+
* Placeholder text displayed when the textarea is empty.
|
|
342
|
+
*/
|
|
343
|
+
placeholder: {
|
|
344
|
+
type: String,
|
|
345
|
+
default: ""
|
|
346
|
+
},
|
|
347
|
+
/**
|
|
348
|
+
* Error message displayed below the textarea. Triggers red border styling.
|
|
349
|
+
*/
|
|
350
|
+
error: {
|
|
351
|
+
type: String,
|
|
352
|
+
default: ""
|
|
353
|
+
},
|
|
354
|
+
/**
|
|
355
|
+
* Hint text displayed below the textarea in gray.
|
|
356
|
+
*/
|
|
357
|
+
hint: {
|
|
358
|
+
type: String,
|
|
359
|
+
default: ""
|
|
360
|
+
},
|
|
361
|
+
/**
|
|
362
|
+
* Whether the textarea is disabled.
|
|
363
|
+
*/
|
|
364
|
+
disabled: {
|
|
365
|
+
type: Boolean,
|
|
366
|
+
default: !1
|
|
367
|
+
},
|
|
368
|
+
/**
|
|
369
|
+
* Whether the textarea is read-only.
|
|
370
|
+
*/
|
|
371
|
+
readonly: {
|
|
372
|
+
type: Boolean,
|
|
373
|
+
default: !1
|
|
374
|
+
},
|
|
375
|
+
/**
|
|
376
|
+
* Whether the textarea is required.
|
|
377
|
+
*/
|
|
378
|
+
required: {
|
|
379
|
+
type: Boolean,
|
|
380
|
+
default: !1
|
|
381
|
+
},
|
|
382
|
+
/**
|
|
383
|
+
* Number of visible text rows.
|
|
384
|
+
*/
|
|
385
|
+
rows: {
|
|
386
|
+
type: [Number, String],
|
|
387
|
+
default: 3
|
|
388
|
+
},
|
|
389
|
+
/**
|
|
390
|
+
* CSS resize behaviour.
|
|
391
|
+
* @type {'none' | 'vertical' | 'both'}
|
|
392
|
+
*/
|
|
393
|
+
resize: {
|
|
394
|
+
type: String,
|
|
395
|
+
default: "vertical",
|
|
396
|
+
validator: (e) => ["none", "vertical", "both"].includes(e)
|
|
397
|
+
}
|
|
398
|
+
}, {
|
|
399
|
+
modelValue: { type: String, default: "" },
|
|
400
|
+
modelModifiers: {}
|
|
401
|
+
}),
|
|
402
|
+
emits: ["update:modelValue"],
|
|
403
|
+
setup(e) {
|
|
404
|
+
const r = G(e, "modelValue"), t = e, o = `lu-textarea-${q()}`, s = {
|
|
405
|
+
none: "resize-none",
|
|
406
|
+
vertical: "resize-y",
|
|
407
|
+
both: "resize"
|
|
408
|
+
}, i = b(() => [
|
|
409
|
+
"w-full rounded-input border bg-white px-3 py-2 text-sm text-gray-900",
|
|
410
|
+
"placeholder-gray-400 outline-none transition-colors duration-150",
|
|
411
|
+
"focus:ring-2 focus:ring-offset-[2px]",
|
|
412
|
+
t.error ? "border-red-500 focus:ring-red-500" : "border-lu-border focus:ring-teal-500 focus:border-teal-500",
|
|
413
|
+
t.disabled ? "opacity-50 cursor-not-allowed bg-gray-50" : "",
|
|
414
|
+
s[t.resize]
|
|
415
|
+
]);
|
|
416
|
+
return (u, g) => (n(), a("div", wt, [
|
|
417
|
+
e.label ? (n(), a("label", {
|
|
418
|
+
key: 0,
|
|
419
|
+
for: o,
|
|
420
|
+
class: "text-sm font-medium text-gray-700"
|
|
421
|
+
}, [
|
|
422
|
+
M(y(e.label) + " ", 1),
|
|
423
|
+
e.required ? (n(), a("span", kt, "*")) : c("", !0)
|
|
424
|
+
])) : c("", !0),
|
|
425
|
+
ee(l("textarea", {
|
|
426
|
+
id: o,
|
|
427
|
+
"onUpdate:modelValue": g[0] || (g[0] = (d) => r.value = d),
|
|
428
|
+
placeholder: e.placeholder,
|
|
429
|
+
disabled: e.disabled,
|
|
430
|
+
readonly: e.readonly,
|
|
431
|
+
required: e.required,
|
|
432
|
+
rows: e.rows,
|
|
433
|
+
class: w(i.value),
|
|
434
|
+
"aria-invalid": !!e.error || void 0,
|
|
435
|
+
"aria-describedby": e.error ? `${o}-error` : e.hint ? `${o}-hint` : void 0
|
|
436
|
+
}, null, 10, $t), [
|
|
437
|
+
[ge, r.value]
|
|
438
|
+
]),
|
|
439
|
+
e.error ? (n(), a("p", {
|
|
440
|
+
key: 1,
|
|
441
|
+
id: `${o}-error`,
|
|
442
|
+
class: "text-xs text-red-500",
|
|
443
|
+
role: "alert"
|
|
444
|
+
}, y(e.error), 9, St)) : e.hint ? (n(), a("p", {
|
|
445
|
+
key: 2,
|
|
446
|
+
id: `${o}-hint`,
|
|
447
|
+
class: "text-xs text-gray-400"
|
|
448
|
+
}, y(e.hint), 9, Ct)) : c("", !0)
|
|
449
|
+
]));
|
|
450
|
+
}
|
|
451
|
+
}, At = { class: "bg-lu-surface rounded-card shadow-card" }, _t = {
|
|
452
|
+
key: 0,
|
|
453
|
+
class: "p-6"
|
|
454
|
+
}, Bt = { class: "text-sm font-medium text-gray-500 truncate" }, Et = { class: "mt-2 flex items-baseline gap-2" }, It = { class: "text-2xl font-semibold text-gray-900" }, zt = { class: "sr-only" }, Tt = {
|
|
455
|
+
key: 0,
|
|
456
|
+
class: "w-4 h-4",
|
|
457
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
458
|
+
viewBox: "0 0 20 20",
|
|
459
|
+
fill: "currentColor",
|
|
460
|
+
"aria-hidden": "true"
|
|
461
|
+
}, Mt = {
|
|
462
|
+
key: 1,
|
|
463
|
+
class: "w-4 h-4",
|
|
464
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
465
|
+
viewBox: "0 0 20 20",
|
|
466
|
+
fill: "currentColor",
|
|
467
|
+
"aria-hidden": "true"
|
|
468
|
+
}, jt = {
|
|
469
|
+
key: 2,
|
|
470
|
+
class: "w-4 h-4",
|
|
471
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
472
|
+
viewBox: "0 0 20 20",
|
|
473
|
+
fill: "currentColor",
|
|
474
|
+
"aria-hidden": "true"
|
|
475
|
+
}, Ot = {
|
|
476
|
+
key: 0,
|
|
477
|
+
class: "px-6 py-4 border-b border-lu-border"
|
|
478
|
+
}, Dt = { class: "p-6" }, Vt = {
|
|
479
|
+
key: 1,
|
|
480
|
+
class: "px-6 py-4 border-t border-lu-border"
|
|
481
|
+
}, Pt = {
|
|
482
|
+
__name: "LuCard",
|
|
483
|
+
props: {
|
|
484
|
+
/**
|
|
485
|
+
* Card display variant.
|
|
486
|
+
* @type {'standard' | 'kpi'}
|
|
487
|
+
*/
|
|
488
|
+
variant: {
|
|
489
|
+
type: String,
|
|
490
|
+
default: "standard",
|
|
491
|
+
validator: (e) => ["standard", "kpi"].includes(e)
|
|
492
|
+
},
|
|
493
|
+
/**
|
|
494
|
+
* KPI metric value (only used with variant="kpi").
|
|
495
|
+
* @type {string | number}
|
|
496
|
+
*/
|
|
497
|
+
value: {
|
|
498
|
+
type: [String, Number],
|
|
499
|
+
default: void 0
|
|
500
|
+
},
|
|
501
|
+
/**
|
|
502
|
+
* KPI label text (only used with variant="kpi").
|
|
503
|
+
* @type {string}
|
|
504
|
+
*/
|
|
505
|
+
label: {
|
|
506
|
+
type: String,
|
|
507
|
+
default: ""
|
|
508
|
+
},
|
|
509
|
+
/**
|
|
510
|
+
* KPI trend text, e.g. "+5%" or "-3%" (only used with variant="kpi").
|
|
511
|
+
* @type {string}
|
|
512
|
+
*/
|
|
513
|
+
trend: {
|
|
514
|
+
type: String,
|
|
515
|
+
default: ""
|
|
516
|
+
},
|
|
517
|
+
/**
|
|
518
|
+
* Direction of the trend indicator (only used with variant="kpi").
|
|
519
|
+
* Determines arrow direction and color: up = green, down = red, neutral = gray.
|
|
520
|
+
* @type {'up' | 'down' | 'neutral'}
|
|
521
|
+
*/
|
|
522
|
+
trendDirection: {
|
|
523
|
+
type: String,
|
|
524
|
+
default: "neutral",
|
|
525
|
+
validator: (e) => ["up", "down", "neutral"].includes(e)
|
|
526
|
+
}
|
|
527
|
+
},
|
|
528
|
+
setup(e) {
|
|
529
|
+
const r = e, t = {
|
|
530
|
+
up: "text-green-600",
|
|
531
|
+
down: "text-red-500",
|
|
532
|
+
neutral: "text-gray-400"
|
|
533
|
+
}, o = b(
|
|
534
|
+
() => t[r.trendDirection] ?? t.neutral
|
|
535
|
+
);
|
|
536
|
+
return (s, i) => (n(), a("div", At, [
|
|
537
|
+
e.variant === "kpi" ? (n(), a("div", _t, [
|
|
538
|
+
l("p", Bt, y(e.label), 1),
|
|
539
|
+
l("div", Et, [
|
|
540
|
+
l("span", It, y(e.value), 1),
|
|
541
|
+
e.trend ? (n(), a("span", {
|
|
542
|
+
key: 0,
|
|
543
|
+
class: w(["inline-flex items-center gap-1 text-sm font-medium", o.value])
|
|
544
|
+
}, [
|
|
545
|
+
l("span", zt, y(e.trendDirection === "up" ? "Aufwaertstrend" : e.trendDirection === "down" ? "Abwaertstrend" : "Unveraendert"), 1),
|
|
546
|
+
e.trendDirection === "up" ? (n(), a("svg", Tt, [...i[0] || (i[0] = [
|
|
547
|
+
l("path", {
|
|
548
|
+
"fill-rule": "evenodd",
|
|
549
|
+
d: "M10 17a.75.75 0 0 1-.75-.75V5.612L5.29 9.77a.75.75 0 0 1-1.08-1.04l5.25-5.5a.75.75 0 0 1 1.08 0l5.25 5.5a.75.75 0 1 1-1.08 1.04l-3.96-4.158V16.25A.75.75 0 0 1 10 17Z",
|
|
550
|
+
"clip-rule": "evenodd"
|
|
551
|
+
}, null, -1)
|
|
552
|
+
])])) : c("", !0),
|
|
553
|
+
e.trendDirection === "down" ? (n(), a("svg", Mt, [...i[1] || (i[1] = [
|
|
554
|
+
l("path", {
|
|
555
|
+
"fill-rule": "evenodd",
|
|
556
|
+
d: "M10 3a.75.75 0 0 1 .75.75v10.638l3.96-4.158a.75.75 0 1 1 1.08 1.04l-5.25 5.5a.75.75 0 0 1-1.08 0l-5.25-5.5a.75.75 0 1 1 1.08-1.04l3.96 4.158V3.75A.75.75 0 0 1 10 3Z",
|
|
557
|
+
"clip-rule": "evenodd"
|
|
558
|
+
}, null, -1)
|
|
559
|
+
])])) : c("", !0),
|
|
560
|
+
e.trendDirection === "neutral" ? (n(), a("svg", jt, [...i[2] || (i[2] = [
|
|
561
|
+
l("path", {
|
|
562
|
+
"fill-rule": "evenodd",
|
|
563
|
+
d: "M4 10a.75.75 0 0 1 .75-.75h10.5a.75.75 0 0 1 0 1.5H4.75A.75.75 0 0 1 4 10Z",
|
|
564
|
+
"clip-rule": "evenodd"
|
|
565
|
+
}, null, -1)
|
|
566
|
+
])])) : c("", !0),
|
|
567
|
+
M(" " + y(e.trend), 1)
|
|
568
|
+
], 2)) : c("", !0)
|
|
569
|
+
])
|
|
570
|
+
])) : (n(), a(z, { key: 1 }, [
|
|
571
|
+
s.$slots.header ? (n(), a("div", Ot, [
|
|
572
|
+
B(s.$slots, "header")
|
|
573
|
+
])) : c("", !0),
|
|
574
|
+
l("div", Dt, [
|
|
575
|
+
B(s.$slots, "default")
|
|
576
|
+
]),
|
|
577
|
+
s.$slots.footer ? (n(), a("div", Vt, [
|
|
578
|
+
B(s.$slots, "footer")
|
|
579
|
+
])) : c("", !0)
|
|
580
|
+
], 64))
|
|
581
|
+
]));
|
|
582
|
+
}
|
|
583
|
+
}, Rt = { class: "bg-lu-surface rounded-card shadow-card overflow-hidden" }, Nt = { class: "overflow-x-auto" }, Ft = {
|
|
584
|
+
class: "w-full text-left text-sm",
|
|
585
|
+
role: "table"
|
|
586
|
+
}, qt = { class: "border-b border-lu-border" }, Kt = ["tabindex", "aria-sort", "onClick", "onKeydown"], Ut = {
|
|
587
|
+
key: 1,
|
|
588
|
+
class: "inline-flex items-center gap-1"
|
|
589
|
+
}, Ht = {
|
|
590
|
+
key: 0,
|
|
591
|
+
class: "w-3.5 h-3.5 text-teal-500",
|
|
592
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
593
|
+
viewBox: "0 0 20 20",
|
|
594
|
+
fill: "currentColor",
|
|
595
|
+
"aria-hidden": "true"
|
|
596
|
+
}, Zt = {
|
|
597
|
+
key: 1,
|
|
598
|
+
class: "w-3.5 h-3.5 text-teal-500",
|
|
599
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
600
|
+
viewBox: "0 0 20 20",
|
|
601
|
+
fill: "currentColor",
|
|
602
|
+
"aria-hidden": "true"
|
|
603
|
+
}, Wt = { key: 0 }, Gt = { key: 1 }, Xt = ["colspan"], Jt = { key: 2 }, Yt = ["onClick"], Qt = {
|
|
604
|
+
__name: "LuTable",
|
|
605
|
+
props: {
|
|
606
|
+
/**
|
|
607
|
+
* Column definitions.
|
|
608
|
+
* @type {TableColumn[]}
|
|
609
|
+
*/
|
|
610
|
+
columns: {
|
|
611
|
+
type: Array,
|
|
612
|
+
required: !0
|
|
613
|
+
},
|
|
614
|
+
/**
|
|
615
|
+
* Row data array. Each item is an object whose keys correspond to column keys.
|
|
616
|
+
* Each row should have a unique identifier matching the `rowKey` prop for correct
|
|
617
|
+
* Vue reactivity when sorting or reordering rows.
|
|
618
|
+
* @type {Array<Record<string, unknown>>}
|
|
619
|
+
*/
|
|
620
|
+
data: {
|
|
621
|
+
type: Array,
|
|
622
|
+
default: () => []
|
|
623
|
+
},
|
|
624
|
+
/**
|
|
625
|
+
* Whether the table is in a loading state (shows skeleton rows).
|
|
626
|
+
*/
|
|
627
|
+
loading: {
|
|
628
|
+
type: Boolean,
|
|
629
|
+
default: !1
|
|
630
|
+
},
|
|
631
|
+
/**
|
|
632
|
+
* Currently active sort field (column key).
|
|
633
|
+
* @type {string}
|
|
634
|
+
*/
|
|
635
|
+
sortField: {
|
|
636
|
+
type: String,
|
|
637
|
+
default: ""
|
|
638
|
+
},
|
|
639
|
+
/**
|
|
640
|
+
* Sort direction for the active sort field.
|
|
641
|
+
* @type {'asc' | 'desc'}
|
|
642
|
+
*/
|
|
643
|
+
sortDir: {
|
|
644
|
+
type: String,
|
|
645
|
+
default: "asc",
|
|
646
|
+
validator: (e) => ["asc", "desc"].includes(e)
|
|
647
|
+
},
|
|
648
|
+
/**
|
|
649
|
+
* Property name used as unique key for each row. Ensures stable DOM identity
|
|
650
|
+
* when rows are sorted or reordered, preventing Vue reactivity issues with
|
|
651
|
+
* slot state (inputs, toggles, tooltips). Falls back to row index if not found.
|
|
652
|
+
* @type {string}
|
|
653
|
+
*/
|
|
654
|
+
rowKey: {
|
|
655
|
+
type: String,
|
|
656
|
+
default: "id"
|
|
657
|
+
},
|
|
658
|
+
/**
|
|
659
|
+
* Optional function to compute custom CSS classes for each data row.
|
|
660
|
+
* Receives (row, index) and should return a string or array of strings.
|
|
661
|
+
* When provided, overrides the default zebra-striping background.
|
|
662
|
+
* @type {((row: Record<string, unknown>, index: number) => string|string[]) | null}
|
|
663
|
+
*/
|
|
664
|
+
rowClass: {
|
|
665
|
+
type: Function,
|
|
666
|
+
default: null
|
|
667
|
+
}
|
|
668
|
+
},
|
|
669
|
+
emits: ["sort", "row-click"],
|
|
670
|
+
setup(e, { emit: r }) {
|
|
671
|
+
const t = ["75%", "55%", "65%", "85%", "45%", "70%"], o = [0, 1, 2], s = e, i = r;
|
|
672
|
+
function u(v) {
|
|
673
|
+
i("sort", v);
|
|
674
|
+
}
|
|
675
|
+
function g(v, m) {
|
|
676
|
+
return v[s.rowKey] ?? v._id ?? m;
|
|
677
|
+
}
|
|
678
|
+
function d(v, m) {
|
|
679
|
+
return t[(v * 3 + m) % t.length];
|
|
680
|
+
}
|
|
681
|
+
return (v, m) => (n(), a("div", Rt, [
|
|
682
|
+
l("div", Nt, [
|
|
683
|
+
l("table", Ft, [
|
|
684
|
+
l("thead", null, [
|
|
685
|
+
l("tr", qt, [
|
|
686
|
+
(n(!0), a(z, null, j(e.columns, (f) => (n(), a("th", {
|
|
687
|
+
key: f.key,
|
|
688
|
+
scope: "col",
|
|
689
|
+
class: w([
|
|
690
|
+
"px-6 py-3 text-xs font-semibold text-gray-500 uppercase tracking-wider whitespace-nowrap",
|
|
691
|
+
f.sortable ? "cursor-pointer select-none hover:text-gray-700 transition-colors duration-150" : "",
|
|
692
|
+
f.hideOnMobile ? "hidden md:table-cell" : ""
|
|
693
|
+
]),
|
|
694
|
+
style: H(f.width ? { width: f.width } : void 0),
|
|
695
|
+
tabindex: f.sortable ? 0 : void 0,
|
|
696
|
+
"aria-sort": f.sortable ? e.sortField === f.key ? e.sortDir === "asc" ? "ascending" : "descending" : "none" : void 0,
|
|
697
|
+
onClick: (p) => f.sortable && u(f.key),
|
|
698
|
+
onKeydown: [
|
|
699
|
+
Q((p) => f.sortable && u(f.key), ["enter"]),
|
|
700
|
+
Q(U((p) => f.sortable && u(f.key), ["prevent"]), ["space"])
|
|
701
|
+
]
|
|
702
|
+
}, [
|
|
703
|
+
v.$slots[`header-${f.key}`] ? B(v.$slots, `header-${f.key}`, {
|
|
704
|
+
key: 0,
|
|
705
|
+
column: f
|
|
706
|
+
}) : (n(), a("span", Ut, [
|
|
707
|
+
M(y(f.label) + " ", 1),
|
|
708
|
+
f.sortable && e.sortField === f.key ? (n(), a(z, { key: 0 }, [
|
|
709
|
+
e.sortDir === "asc" ? (n(), a("svg", Ht, [...m[0] || (m[0] = [
|
|
710
|
+
l("path", {
|
|
711
|
+
"fill-rule": "evenodd",
|
|
712
|
+
d: "M9.47 6.47a.75.75 0 0 1 1.06 0l4.25 4.25a.75.75 0 1 1-1.06 1.06L10 8.06l-3.72 3.72a.75.75 0 0 1-1.06-1.06l4.25-4.25Z",
|
|
713
|
+
"clip-rule": "evenodd"
|
|
714
|
+
}, null, -1)
|
|
715
|
+
])])) : (n(), a("svg", Zt, [...m[1] || (m[1] = [
|
|
716
|
+
l("path", {
|
|
717
|
+
"fill-rule": "evenodd",
|
|
718
|
+
d: "M5.22 8.22a.75.75 0 0 1 1.06 0L10 11.94l3.72-3.72a.75.75 0 1 1 1.06 1.06l-4.25 4.25a.75.75 0 0 1-1.06 0l-4.25-4.25a.75.75 0 0 1 0-1.06Z",
|
|
719
|
+
"clip-rule": "evenodd"
|
|
720
|
+
}, null, -1)
|
|
721
|
+
])]))
|
|
722
|
+
], 64)) : c("", !0)
|
|
723
|
+
]))
|
|
724
|
+
], 46, Kt))), 128))
|
|
725
|
+
])
|
|
726
|
+
]),
|
|
727
|
+
e.loading ? (n(), a("tbody", Wt, [
|
|
728
|
+
(n(), a(z, null, j(o, (f) => l("tr", {
|
|
729
|
+
key: "skeleton-" + f,
|
|
730
|
+
class: "border-b border-lu-border last:border-b-0"
|
|
731
|
+
}, [
|
|
732
|
+
(n(!0), a(z, null, j(e.columns, (p, x) => (n(), a("td", {
|
|
733
|
+
key: p.key,
|
|
734
|
+
class: w(["px-6 py-4", p.hideOnMobile ? "hidden md:table-cell" : ""])
|
|
735
|
+
}, [
|
|
736
|
+
l("div", {
|
|
737
|
+
class: "h-4 bg-gray-200 rounded animate-pulse",
|
|
738
|
+
style: H({ width: d(f, x) })
|
|
739
|
+
}, null, 4)
|
|
740
|
+
], 2))), 128))
|
|
741
|
+
])), 64))
|
|
742
|
+
])) : !e.data || e.data.length === 0 ? (n(), a("tbody", Gt, [
|
|
743
|
+
l("tr", null, [
|
|
744
|
+
l("td", {
|
|
745
|
+
colspan: e.columns.length,
|
|
746
|
+
class: "px-6 py-12 text-center text-gray-400"
|
|
747
|
+
}, [
|
|
748
|
+
B(v.$slots, "empty", {}, () => [
|
|
749
|
+
m[2] || (m[2] = M(" Keine Daten vorhanden ", -1))
|
|
750
|
+
])
|
|
751
|
+
], 8, Xt)
|
|
752
|
+
])
|
|
753
|
+
])) : (n(), a("tbody", Jt, [
|
|
754
|
+
(n(!0), a(z, null, j(e.data, (f, p) => (n(), a(z, {
|
|
755
|
+
key: g(f, p)
|
|
756
|
+
}, [
|
|
757
|
+
v.$slots.row ? B(v.$slots, "row", {
|
|
758
|
+
key: 1,
|
|
759
|
+
row: f,
|
|
760
|
+
index: p
|
|
761
|
+
}) : (n(), a("tr", {
|
|
762
|
+
key: 0,
|
|
763
|
+
class: w([
|
|
764
|
+
"border-b border-lu-border last:border-b-0 transition-colors duration-150",
|
|
765
|
+
s.rowClass ? s.rowClass(f, p) : p % 2 === 1 ? "bg-lu-bg" : "bg-lu-surface"
|
|
766
|
+
]),
|
|
767
|
+
onClick: (x) => i("row-click", f, p)
|
|
768
|
+
}, [
|
|
769
|
+
(n(!0), a(z, null, j(e.columns, (x) => (n(), a("td", {
|
|
770
|
+
key: x.key,
|
|
771
|
+
class: w(["px-6 py-4 text-gray-700", x.hideOnMobile ? "hidden md:table-cell" : ""])
|
|
772
|
+
}, [
|
|
773
|
+
B(v.$slots, "cell-" + x.key, {
|
|
774
|
+
row: f,
|
|
775
|
+
value: f[x.key]
|
|
776
|
+
}, () => [
|
|
777
|
+
M(y(f[x.key]), 1)
|
|
778
|
+
])
|
|
779
|
+
], 2))), 128))
|
|
780
|
+
], 10, Yt))
|
|
781
|
+
], 64))), 128))
|
|
782
|
+
]))
|
|
783
|
+
])
|
|
784
|
+
])
|
|
785
|
+
]));
|
|
786
|
+
}
|
|
787
|
+
}, en = {
|
|
788
|
+
__name: "LuBadge",
|
|
789
|
+
props: {
|
|
790
|
+
/**
|
|
791
|
+
* Semantic color variant.
|
|
792
|
+
* @type {'success' | 'warning' | 'error' | 'info' | 'neutral'}
|
|
793
|
+
*/
|
|
794
|
+
variant: {
|
|
795
|
+
type: String,
|
|
796
|
+
default: "neutral",
|
|
797
|
+
validator: (e) => ["success", "warning", "error", "info", "neutral"].includes(e)
|
|
798
|
+
},
|
|
799
|
+
/**
|
|
800
|
+
* Badge size.
|
|
801
|
+
* @type {'sm' | 'md'}
|
|
802
|
+
*/
|
|
803
|
+
size: {
|
|
804
|
+
type: String,
|
|
805
|
+
default: "md",
|
|
806
|
+
validator: (e) => ["sm", "md"].includes(e)
|
|
807
|
+
}
|
|
808
|
+
},
|
|
809
|
+
setup(e) {
|
|
810
|
+
const r = e, t = {
|
|
811
|
+
success: "bg-green-50 text-green-700",
|
|
812
|
+
warning: "bg-amber-50 text-amber-700",
|
|
813
|
+
error: "bg-red-50 text-red-700",
|
|
814
|
+
info: "bg-blue-50 text-blue-700",
|
|
815
|
+
neutral: "bg-gray-100 text-gray-700"
|
|
816
|
+
}, o = {
|
|
817
|
+
sm: "px-1.5 py-0.5 text-[11px]",
|
|
818
|
+
md: "px-2 py-0.5 text-xs"
|
|
819
|
+
}, s = b(() => [
|
|
820
|
+
"inline-flex items-center font-medium rounded-full whitespace-nowrap leading-tight",
|
|
821
|
+
t[r.variant],
|
|
822
|
+
o[r.size]
|
|
823
|
+
]);
|
|
824
|
+
return (i, u) => (n(), a("span", {
|
|
825
|
+
class: w(s.value)
|
|
826
|
+
}, [
|
|
827
|
+
B(i.$slots, "default")
|
|
828
|
+
], 2));
|
|
829
|
+
}
|
|
830
|
+
}, O = {
|
|
831
|
+
__name: "LuIcon",
|
|
832
|
+
props: {
|
|
833
|
+
/**
|
|
834
|
+
* Lucide icon name in PascalCase (e.g. 'Clock', 'CircleCheck', 'User').
|
|
835
|
+
* @type {string}
|
|
836
|
+
*/
|
|
837
|
+
name: {
|
|
838
|
+
type: String,
|
|
839
|
+
required: !0
|
|
840
|
+
},
|
|
841
|
+
/**
|
|
842
|
+
* Icon size in pixels.
|
|
843
|
+
* @type {number | string}
|
|
844
|
+
*/
|
|
845
|
+
size: {
|
|
846
|
+
type: [Number, String],
|
|
847
|
+
default: 20
|
|
848
|
+
},
|
|
849
|
+
/**
|
|
850
|
+
* Icon color. Accepts any CSS color value.
|
|
851
|
+
* @type {string}
|
|
852
|
+
*/
|
|
853
|
+
color: {
|
|
854
|
+
type: String,
|
|
855
|
+
default: "currentColor"
|
|
856
|
+
},
|
|
857
|
+
/**
|
|
858
|
+
* SVG stroke width.
|
|
859
|
+
* @type {number | string}
|
|
860
|
+
*/
|
|
861
|
+
strokeWidth: {
|
|
862
|
+
type: [Number, String],
|
|
863
|
+
default: 1.5
|
|
864
|
+
}
|
|
865
|
+
},
|
|
866
|
+
setup(e) {
|
|
867
|
+
const r = e, t = /* @__PURE__ */ new Map(), o = E(null);
|
|
868
|
+
async function s(u) {
|
|
869
|
+
if (t.has(u))
|
|
870
|
+
return t.get(u) ?? null;
|
|
871
|
+
try {
|
|
872
|
+
const d = (await import("lucide-vue-next"))[u];
|
|
873
|
+
return d ? (t.set(u, d), d) : (console.warn(`[LuIcon] Icon "${u}" not found in lucide-vue-next`), t.set(u, null), null);
|
|
874
|
+
} catch {
|
|
875
|
+
return console.warn(`[LuIcon] Failed to load icon "${u}"`), null;
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
async function i(u) {
|
|
879
|
+
if (!u) {
|
|
880
|
+
o.value = null;
|
|
881
|
+
return;
|
|
882
|
+
}
|
|
883
|
+
if (t.has(u)) {
|
|
884
|
+
o.value = t.get(u) ?? null;
|
|
885
|
+
return;
|
|
886
|
+
}
|
|
887
|
+
o.value = null, o.value = await s(u);
|
|
888
|
+
}
|
|
889
|
+
return i(r.name), ie(
|
|
890
|
+
() => r.name,
|
|
891
|
+
(u) => {
|
|
892
|
+
i(u);
|
|
893
|
+
}
|
|
894
|
+
), (u, g) => o.value ? (n(), P(Be(o.value), {
|
|
895
|
+
key: 0,
|
|
896
|
+
size: e.size,
|
|
897
|
+
color: e.color,
|
|
898
|
+
"stroke-width": e.strokeWidth,
|
|
899
|
+
"aria-hidden": "true"
|
|
900
|
+
}, null, 8, ["size", "color", "stroke-width"])) : c("", !0);
|
|
901
|
+
}
|
|
902
|
+
}, tn = ["aria-label"], nn = ["src", "alt"], an = {
|
|
903
|
+
key: 1,
|
|
904
|
+
"aria-hidden": "true"
|
|
905
|
+
}, oe = {
|
|
906
|
+
__name: "LuAvatar",
|
|
907
|
+
props: {
|
|
908
|
+
/**
|
|
909
|
+
* Full name of the person. Used for initials and color computation.
|
|
910
|
+
* @type {string}
|
|
911
|
+
*/
|
|
912
|
+
name: {
|
|
913
|
+
type: String,
|
|
914
|
+
required: !0
|
|
915
|
+
},
|
|
916
|
+
/**
|
|
917
|
+
* Optional image URL. When set and successfully loaded, shows the image.
|
|
918
|
+
* @type {string}
|
|
919
|
+
*/
|
|
920
|
+
src: {
|
|
921
|
+
type: String,
|
|
922
|
+
default: ""
|
|
923
|
+
},
|
|
924
|
+
/**
|
|
925
|
+
* Avatar size. sm=32px, md=40px, lg=48px, xl=64px.
|
|
926
|
+
* @type {'sm' | 'md' | 'lg' | 'xl'}
|
|
927
|
+
*/
|
|
928
|
+
size: {
|
|
929
|
+
type: String,
|
|
930
|
+
default: "md",
|
|
931
|
+
validator: (e) => ["sm", "md", "lg", "xl"].includes(e)
|
|
932
|
+
}
|
|
933
|
+
},
|
|
934
|
+
setup(e) {
|
|
935
|
+
const r = e, t = [
|
|
936
|
+
{ bg: "bg-teal-100", text: "text-teal-700" },
|
|
937
|
+
{ bg: "bg-blue-100", text: "text-blue-700" },
|
|
938
|
+
{ bg: "bg-violet-100", text: "text-violet-700" },
|
|
939
|
+
{ bg: "bg-amber-100", text: "text-amber-700" },
|
|
940
|
+
{ bg: "bg-rose-100", text: "text-rose-700" },
|
|
941
|
+
{ bg: "bg-emerald-100", text: "text-emerald-700" }
|
|
942
|
+
], o = {
|
|
943
|
+
sm: "w-8 h-8 text-xs",
|
|
944
|
+
md: "w-10 h-10 text-sm",
|
|
945
|
+
lg: "w-12 h-12 text-base",
|
|
946
|
+
xl: "w-16 h-16 text-lg"
|
|
947
|
+
}, s = E(!1), i = E(!1);
|
|
948
|
+
function u(m) {
|
|
949
|
+
let f = 0;
|
|
950
|
+
for (let p = 0; p < m.length; p++)
|
|
951
|
+
f = (f << 5) - f + m.charCodeAt(p), f |= 0;
|
|
952
|
+
return Math.abs(f);
|
|
953
|
+
}
|
|
954
|
+
const g = b(() => {
|
|
955
|
+
const m = u(r.name) % t.length;
|
|
956
|
+
return t[m];
|
|
957
|
+
}), d = b(() => {
|
|
958
|
+
var f;
|
|
959
|
+
const m = r.name.trim().split(/\s+/);
|
|
960
|
+
return m.length >= 2 ? (m[0][0] + m[m.length - 1][0]).toUpperCase() : (((f = m[0]) == null ? void 0 : f[0]) || "?").toUpperCase();
|
|
961
|
+
}), v = b(() => !!r.src && s.value && !i.value);
|
|
962
|
+
return ie(
|
|
963
|
+
() => r.src,
|
|
964
|
+
(m) => {
|
|
965
|
+
if (s.value = !1, i.value = !1, m) {
|
|
966
|
+
const f = new Image();
|
|
967
|
+
f.onload = () => {
|
|
968
|
+
s.value = !0;
|
|
969
|
+
}, f.onerror = () => {
|
|
970
|
+
i.value = !0;
|
|
971
|
+
}, f.src = m;
|
|
972
|
+
}
|
|
973
|
+
},
|
|
974
|
+
{ immediate: !0 }
|
|
975
|
+
), (m, f) => (n(), a("div", {
|
|
976
|
+
class: w([
|
|
977
|
+
"inline-flex items-center justify-center rounded-full font-medium overflow-hidden shrink-0 select-none",
|
|
978
|
+
o[e.size],
|
|
979
|
+
v.value ? "" : [g.value.bg, g.value.text]
|
|
980
|
+
]),
|
|
981
|
+
"aria-label": e.name,
|
|
982
|
+
role: "img"
|
|
983
|
+
}, [
|
|
984
|
+
v.value ? (n(), a("img", {
|
|
985
|
+
key: 0,
|
|
986
|
+
src: e.src,
|
|
987
|
+
alt: e.name,
|
|
988
|
+
class: "w-full h-full object-cover"
|
|
989
|
+
}, null, 8, nn)) : (n(), a("span", an, y(d.value), 1))
|
|
990
|
+
], 10, tn));
|
|
991
|
+
}
|
|
992
|
+
};
|
|
993
|
+
let rn = 0;
|
|
994
|
+
const Y = Ee(
|
|
995
|
+
/** @type {Toast[]} */
|
|
996
|
+
[]
|
|
997
|
+
);
|
|
998
|
+
function sn() {
|
|
999
|
+
function e({ variant: t = "info", title: o = "", message: s, duration: i = 5e3 }) {
|
|
1000
|
+
const u = ++rn;
|
|
1001
|
+
return Y.push({ id: u, variant: t, title: o, message: s, duration: i }), i > 0 && setTimeout(() => r(u), i), u;
|
|
1002
|
+
}
|
|
1003
|
+
function r(t) {
|
|
1004
|
+
const o = Y.findIndex((s) => s.id === t);
|
|
1005
|
+
o > -1 && Y.splice(o, 1);
|
|
1006
|
+
}
|
|
1007
|
+
return { toasts: Y, addToast: e, removeToast: r };
|
|
1008
|
+
}
|
|
1009
|
+
const W = (e, r) => {
|
|
1010
|
+
const t = e.__vccOpts || e;
|
|
1011
|
+
for (const [o, s] of r)
|
|
1012
|
+
t[o] = s;
|
|
1013
|
+
return t;
|
|
1014
|
+
}, ln = {
|
|
1015
|
+
class: "fixed bottom-6 right-6 z-toast flex flex-col gap-3 pointer-events-none",
|
|
1016
|
+
"aria-live": "polite",
|
|
1017
|
+
"aria-atomic": "false"
|
|
1018
|
+
}, on = { class: "flex-1 min-w-0" }, un = {
|
|
1019
|
+
key: 0,
|
|
1020
|
+
class: "text-sm font-semibold text-gray-900"
|
|
1021
|
+
}, dn = { class: "text-sm text-gray-600" }, cn = ["onClick"], fn = {
|
|
1022
|
+
__name: "LuToast",
|
|
1023
|
+
setup(e) {
|
|
1024
|
+
const { toasts: r, removeToast: t } = sn(), o = {
|
|
1025
|
+
success: "CircleCheck",
|
|
1026
|
+
warning: "TriangleAlert",
|
|
1027
|
+
error: "XCircle",
|
|
1028
|
+
info: "Info"
|
|
1029
|
+
}, s = {
|
|
1030
|
+
success: "text-green-500",
|
|
1031
|
+
warning: "text-amber-500",
|
|
1032
|
+
error: "text-red-500",
|
|
1033
|
+
info: "text-blue-500"
|
|
1034
|
+
}, i = {
|
|
1035
|
+
success: "border-green-200",
|
|
1036
|
+
warning: "border-amber-200",
|
|
1037
|
+
error: "border-red-200",
|
|
1038
|
+
info: "border-blue-200"
|
|
1039
|
+
};
|
|
1040
|
+
return (u, g) => (n(), P(ye, { to: "body" }, [
|
|
1041
|
+
l("div", ln, [
|
|
1042
|
+
A(Ie, { name: "lu-toast" }, {
|
|
1043
|
+
default: T(() => [
|
|
1044
|
+
(n(!0), a(z, null, j(R(r), (d) => (n(), a("div", {
|
|
1045
|
+
key: d.id,
|
|
1046
|
+
class: w([
|
|
1047
|
+
"pointer-events-auto flex items-start gap-3 p-4 rounded-card bg-white shadow-lg border max-w-sm",
|
|
1048
|
+
i[d.variant]
|
|
1049
|
+
]),
|
|
1050
|
+
role: "alert"
|
|
1051
|
+
}, [
|
|
1052
|
+
A(O, {
|
|
1053
|
+
name: o[d.variant],
|
|
1054
|
+
size: 20,
|
|
1055
|
+
class: w(["shrink-0 mt-0.5", s[d.variant]])
|
|
1056
|
+
}, null, 8, ["name", "class"]),
|
|
1057
|
+
l("div", on, [
|
|
1058
|
+
d.title ? (n(), a("p", un, y(d.title), 1)) : c("", !0),
|
|
1059
|
+
l("p", dn, y(d.message), 1)
|
|
1060
|
+
]),
|
|
1061
|
+
l("button", {
|
|
1062
|
+
class: "shrink-0 p-1 text-gray-400 hover:text-gray-600 transition-colors duration-150 rounded-full hover:bg-gray-100",
|
|
1063
|
+
"aria-label": "Schließen",
|
|
1064
|
+
onClick: (v) => R(t)(d.id)
|
|
1065
|
+
}, [
|
|
1066
|
+
A(O, {
|
|
1067
|
+
name: "X",
|
|
1068
|
+
size: 16
|
|
1069
|
+
})
|
|
1070
|
+
], 8, cn)
|
|
1071
|
+
], 2))), 128))
|
|
1072
|
+
]),
|
|
1073
|
+
_: 1
|
|
1074
|
+
})
|
|
1075
|
+
])
|
|
1076
|
+
]));
|
|
1077
|
+
}
|
|
1078
|
+
}, bn = /* @__PURE__ */ W(fn, [["__scopeId", "data-v-d20ffd9e"]]), gn = { class: "flex-1 min-w-0" }, yn = {
|
|
1079
|
+
key: 0,
|
|
1080
|
+
class: "text-sm font-semibold"
|
|
1081
|
+
}, vn = {
|
|
1082
|
+
__name: "LuAlert",
|
|
1083
|
+
props: {
|
|
1084
|
+
/**
|
|
1085
|
+
* Semantic color variant.
|
|
1086
|
+
* @type {'info' | 'warning' | 'error' | 'success'}
|
|
1087
|
+
*/
|
|
1088
|
+
variant: {
|
|
1089
|
+
type: String,
|
|
1090
|
+
default: "info",
|
|
1091
|
+
validator: (e) => ["info", "warning", "error", "success"].includes(e)
|
|
1092
|
+
},
|
|
1093
|
+
/**
|
|
1094
|
+
* Optional bold title line.
|
|
1095
|
+
* @type {string}
|
|
1096
|
+
*/
|
|
1097
|
+
title: {
|
|
1098
|
+
type: String,
|
|
1099
|
+
default: ""
|
|
1100
|
+
},
|
|
1101
|
+
/**
|
|
1102
|
+
* Alert message body text.
|
|
1103
|
+
* @type {string}
|
|
1104
|
+
*/
|
|
1105
|
+
message: {
|
|
1106
|
+
type: String,
|
|
1107
|
+
default: ""
|
|
1108
|
+
},
|
|
1109
|
+
/**
|
|
1110
|
+
* Whether to show a dismiss/close button.
|
|
1111
|
+
* @type {boolean}
|
|
1112
|
+
*/
|
|
1113
|
+
dismissible: {
|
|
1114
|
+
type: Boolean,
|
|
1115
|
+
default: !1
|
|
1116
|
+
}
|
|
1117
|
+
},
|
|
1118
|
+
emits: ["dismiss"],
|
|
1119
|
+
setup(e, { emit: r }) {
|
|
1120
|
+
const t = e, o = r, s = E(!1);
|
|
1121
|
+
function i() {
|
|
1122
|
+
s.value = !0, o("dismiss");
|
|
1123
|
+
}
|
|
1124
|
+
const u = {
|
|
1125
|
+
success: "bg-green-50 border-green-200 text-green-800",
|
|
1126
|
+
warning: "bg-amber-50 border-amber-200 text-amber-800",
|
|
1127
|
+
error: "bg-red-50 border-red-200 text-red-800",
|
|
1128
|
+
info: "bg-blue-50 border-blue-200 text-blue-800"
|
|
1129
|
+
}, g = {
|
|
1130
|
+
success: "CircleCheck",
|
|
1131
|
+
warning: "TriangleAlert",
|
|
1132
|
+
error: "XCircle",
|
|
1133
|
+
info: "Info"
|
|
1134
|
+
}, d = {
|
|
1135
|
+
success: "text-green-500",
|
|
1136
|
+
warning: "text-amber-500",
|
|
1137
|
+
error: "text-red-500",
|
|
1138
|
+
info: "text-blue-500"
|
|
1139
|
+
}, v = b(() => [
|
|
1140
|
+
"flex items-start gap-3 p-4 rounded-card border",
|
|
1141
|
+
u[t.variant]
|
|
1142
|
+
]);
|
|
1143
|
+
return (m, f) => s.value ? c("", !0) : (n(), a("div", {
|
|
1144
|
+
key: 0,
|
|
1145
|
+
class: w(v.value),
|
|
1146
|
+
role: "alert"
|
|
1147
|
+
}, [
|
|
1148
|
+
A(O, {
|
|
1149
|
+
name: g[e.variant],
|
|
1150
|
+
size: 20,
|
|
1151
|
+
class: w(["shrink-0 mt-0.5", d[e.variant]])
|
|
1152
|
+
}, null, 8, ["name", "class"]),
|
|
1153
|
+
l("div", gn, [
|
|
1154
|
+
e.title ? (n(), a("p", yn, y(e.title), 1)) : c("", !0),
|
|
1155
|
+
e.message ? (n(), a("p", {
|
|
1156
|
+
key: 1,
|
|
1157
|
+
class: w(["text-sm", e.title ? "mt-1 opacity-90" : ""])
|
|
1158
|
+
}, y(e.message), 3)) : c("", !0)
|
|
1159
|
+
]),
|
|
1160
|
+
e.dismissible ? (n(), a("button", {
|
|
1161
|
+
key: 0,
|
|
1162
|
+
class: "shrink-0 p-1 text-current opacity-60 hover:opacity-100 transition-opacity duration-150 rounded-full",
|
|
1163
|
+
"aria-label": "Schließen",
|
|
1164
|
+
onClick: i
|
|
1165
|
+
}, [
|
|
1166
|
+
A(O, {
|
|
1167
|
+
name: "X",
|
|
1168
|
+
size: 16
|
|
1169
|
+
})
|
|
1170
|
+
])) : c("", !0)
|
|
1171
|
+
], 2));
|
|
1172
|
+
}
|
|
1173
|
+
}, mn = {
|
|
1174
|
+
__name: "LuSkeleton",
|
|
1175
|
+
props: {
|
|
1176
|
+
/**
|
|
1177
|
+
* Skeleton width. Accepts any CSS width value.
|
|
1178
|
+
* @type {string}
|
|
1179
|
+
*/
|
|
1180
|
+
width: {
|
|
1181
|
+
type: String,
|
|
1182
|
+
default: "100%"
|
|
1183
|
+
},
|
|
1184
|
+
/**
|
|
1185
|
+
* Skeleton height. Accepts any CSS height value.
|
|
1186
|
+
* @type {string}
|
|
1187
|
+
*/
|
|
1188
|
+
height: {
|
|
1189
|
+
type: String,
|
|
1190
|
+
default: "16px"
|
|
1191
|
+
},
|
|
1192
|
+
/**
|
|
1193
|
+
* Whether to use fully rounded corners (circle/pill shape).
|
|
1194
|
+
* @type {boolean}
|
|
1195
|
+
*/
|
|
1196
|
+
rounded: {
|
|
1197
|
+
type: Boolean,
|
|
1198
|
+
default: !1
|
|
1199
|
+
}
|
|
1200
|
+
},
|
|
1201
|
+
setup(e) {
|
|
1202
|
+
return (r, t) => (n(), a("div", {
|
|
1203
|
+
class: w(["lu-skeleton", e.rounded ? "rounded-full" : "rounded-input"]),
|
|
1204
|
+
style: H({ width: e.width, height: e.height }),
|
|
1205
|
+
"aria-hidden": "true"
|
|
1206
|
+
}, null, 6));
|
|
1207
|
+
}
|
|
1208
|
+
}, pn = /* @__PURE__ */ W(mn, [["__scopeId", "data-v-19bd1245"]]), hn = { class: "flex flex-col items-center justify-center py-12 px-4 text-center" }, xn = {
|
|
1209
|
+
key: 0,
|
|
1210
|
+
class: "mb-4 text-gray-300"
|
|
1211
|
+
}, wn = { class: "text-base font-semibold text-gray-900 mb-1" }, kn = {
|
|
1212
|
+
key: 1,
|
|
1213
|
+
class: "text-sm text-gray-500 mb-6 max-w-sm"
|
|
1214
|
+
}, $n = {
|
|
1215
|
+
__name: "LuEmptyState",
|
|
1216
|
+
props: {
|
|
1217
|
+
/**
|
|
1218
|
+
* Lucide icon name to display above the title.
|
|
1219
|
+
* @type {string}
|
|
1220
|
+
*/
|
|
1221
|
+
icon: {
|
|
1222
|
+
type: String,
|
|
1223
|
+
default: ""
|
|
1224
|
+
},
|
|
1225
|
+
/**
|
|
1226
|
+
* Bold headline text.
|
|
1227
|
+
* @type {string}
|
|
1228
|
+
*/
|
|
1229
|
+
title: {
|
|
1230
|
+
type: String,
|
|
1231
|
+
required: !0
|
|
1232
|
+
},
|
|
1233
|
+
/**
|
|
1234
|
+
* Descriptive text below the title.
|
|
1235
|
+
* @type {string}
|
|
1236
|
+
*/
|
|
1237
|
+
description: {
|
|
1238
|
+
type: String,
|
|
1239
|
+
default: ""
|
|
1240
|
+
},
|
|
1241
|
+
/**
|
|
1242
|
+
* Label for the optional action button.
|
|
1243
|
+
* @type {string}
|
|
1244
|
+
*/
|
|
1245
|
+
actionLabel: {
|
|
1246
|
+
type: String,
|
|
1247
|
+
default: ""
|
|
1248
|
+
},
|
|
1249
|
+
/**
|
|
1250
|
+
* Click handler for the action button.
|
|
1251
|
+
* @type {Function | null}
|
|
1252
|
+
*/
|
|
1253
|
+
actionHandler: {
|
|
1254
|
+
type: Function,
|
|
1255
|
+
default: null
|
|
1256
|
+
}
|
|
1257
|
+
},
|
|
1258
|
+
setup(e) {
|
|
1259
|
+
return (r, t) => (n(), a("div", hn, [
|
|
1260
|
+
e.icon ? (n(), a("div", xn, [
|
|
1261
|
+
A(O, {
|
|
1262
|
+
name: e.icon,
|
|
1263
|
+
size: 48,
|
|
1264
|
+
"stroke-width": 1.5
|
|
1265
|
+
}, null, 8, ["name"])
|
|
1266
|
+
])) : c("", !0),
|
|
1267
|
+
l("h3", wn, y(e.title), 1),
|
|
1268
|
+
e.description ? (n(), a("p", kn, y(e.description), 1)) : c("", !0),
|
|
1269
|
+
e.actionLabel && e.actionHandler ? (n(), P(K, {
|
|
1270
|
+
key: 2,
|
|
1271
|
+
variant: "primary",
|
|
1272
|
+
size: "md",
|
|
1273
|
+
onClick: e.actionHandler
|
|
1274
|
+
}, {
|
|
1275
|
+
default: T(() => [
|
|
1276
|
+
M(y(e.actionLabel), 1)
|
|
1277
|
+
]),
|
|
1278
|
+
_: 1
|
|
1279
|
+
}, 8, ["onClick"])) : c("", !0)
|
|
1280
|
+
]));
|
|
1281
|
+
}
|
|
1282
|
+
};
|
|
1283
|
+
function ne(e, r) {
|
|
1284
|
+
function t(o) {
|
|
1285
|
+
e.value && !e.value.contains(
|
|
1286
|
+
/** @type {Node} */
|
|
1287
|
+
o.target
|
|
1288
|
+
) && r();
|
|
1289
|
+
}
|
|
1290
|
+
ve(() => {
|
|
1291
|
+
document.addEventListener("mousedown", t), document.addEventListener("touchstart", t);
|
|
1292
|
+
}), me(() => {
|
|
1293
|
+
document.removeEventListener("mousedown", t), document.removeEventListener("touchstart", t);
|
|
1294
|
+
});
|
|
1295
|
+
}
|
|
1296
|
+
const Sn = { class: "relative" }, Cn = ["tabindex", "aria-expanded", "aria-invalid", "aria-describedby", "aria-disabled", "onKeydown"], Ln = { class: "flex-1 flex flex-wrap items-center gap-1 px-3 py-1.5 text-sm min-w-0" }, An = { class: "truncate" }, _n = ["aria-label", "onClick"], Bn = {
|
|
1297
|
+
key: 1,
|
|
1298
|
+
class: "text-gray-900 truncate"
|
|
1299
|
+
}, En = {
|
|
1300
|
+
key: 2,
|
|
1301
|
+
class: "text-gray-400 truncate"
|
|
1302
|
+
}, In = { class: "pr-3 shrink-0 text-gray-400" }, zn = {
|
|
1303
|
+
key: 0,
|
|
1304
|
+
class: "absolute top-full left-0 right-0 z-dropdown mt-1 bg-white border border-lu-border rounded-card shadow-card max-h-60 overflow-auto"
|
|
1305
|
+
}, Tn = {
|
|
1306
|
+
key: 0,
|
|
1307
|
+
class: "p-2 border-b border-lu-border"
|
|
1308
|
+
}, Mn = ["aria-multiselectable"], jn = {
|
|
1309
|
+
key: 0,
|
|
1310
|
+
class: "px-3 py-1.5 text-xs font-semibold text-gray-500 uppercase tracking-wider",
|
|
1311
|
+
role: "presentation"
|
|
1312
|
+
}, On = ["aria-selected", "onClick"], Dn = { class: "flex-1 truncate" }, Vn = {
|
|
1313
|
+
key: 0,
|
|
1314
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1315
|
+
class: "h-4 w-4 shrink-0 text-teal-500 ml-2",
|
|
1316
|
+
viewBox: "0 0 24 24",
|
|
1317
|
+
fill: "none",
|
|
1318
|
+
stroke: "currentColor",
|
|
1319
|
+
"stroke-width": "2",
|
|
1320
|
+
"stroke-linecap": "round",
|
|
1321
|
+
"stroke-linejoin": "round",
|
|
1322
|
+
"aria-hidden": "true"
|
|
1323
|
+
}, Pn = {
|
|
1324
|
+
key: 0,
|
|
1325
|
+
class: "px-3 py-3 text-sm text-gray-400 text-center"
|
|
1326
|
+
}, Rn = ["id"], Nn = {
|
|
1327
|
+
__name: "LuSelect",
|
|
1328
|
+
props: /* @__PURE__ */ te({
|
|
1329
|
+
/**
|
|
1330
|
+
* Options to display.
|
|
1331
|
+
* Flat: Array<{value: string|number, label: string}>
|
|
1332
|
+
* Grouped: Array<{group: string, items: Array<{value: string|number, label: string}>}>
|
|
1333
|
+
* @type {Array<{value?: string|number, label?: string, group?: string, items?: Array<{value: string|number, label: string}>}>}
|
|
1334
|
+
*/
|
|
1335
|
+
options: {
|
|
1336
|
+
type: Array,
|
|
1337
|
+
default: () => []
|
|
1338
|
+
},
|
|
1339
|
+
/** Label text displayed above the select. */
|
|
1340
|
+
label: {
|
|
1341
|
+
type: String,
|
|
1342
|
+
default: ""
|
|
1343
|
+
},
|
|
1344
|
+
/** Error message displayed below the select. Triggers red border styling. */
|
|
1345
|
+
error: {
|
|
1346
|
+
type: String,
|
|
1347
|
+
default: ""
|
|
1348
|
+
},
|
|
1349
|
+
/** Placeholder text when no option is selected. */
|
|
1350
|
+
placeholder: {
|
|
1351
|
+
type: String,
|
|
1352
|
+
default: "Bitte waehlen…"
|
|
1353
|
+
},
|
|
1354
|
+
/** Enable search input inside the dropdown for live filtering. */
|
|
1355
|
+
searchable: {
|
|
1356
|
+
type: Boolean,
|
|
1357
|
+
default: !1
|
|
1358
|
+
},
|
|
1359
|
+
/** Enable multi-select with chip/tag display in the trigger. */
|
|
1360
|
+
multiple: {
|
|
1361
|
+
type: Boolean,
|
|
1362
|
+
default: !1
|
|
1363
|
+
},
|
|
1364
|
+
/** Whether the select is disabled. */
|
|
1365
|
+
disabled: {
|
|
1366
|
+
type: Boolean,
|
|
1367
|
+
default: !1
|
|
1368
|
+
}
|
|
1369
|
+
}, {
|
|
1370
|
+
modelValue: { default: null },
|
|
1371
|
+
modelModifiers: {}
|
|
1372
|
+
}),
|
|
1373
|
+
emits: ["update:modelValue"],
|
|
1374
|
+
setup(e) {
|
|
1375
|
+
const r = G(e, "modelValue"), t = e, o = E(!1), s = E(""), i = E(null), u = E(null), g = `lu-select-${q()}`;
|
|
1376
|
+
ne(i, () => {
|
|
1377
|
+
o.value = !1;
|
|
1378
|
+
});
|
|
1379
|
+
const d = b(() => {
|
|
1380
|
+
const $ = [];
|
|
1381
|
+
for (const L of t.options)
|
|
1382
|
+
if (L.group && Array.isArray(L.items)) {
|
|
1383
|
+
$.push({ type: "group", label: L.group });
|
|
1384
|
+
for (const C of L.items)
|
|
1385
|
+
$.push({ type: "option", value: C.value, label: C.label });
|
|
1386
|
+
} else
|
|
1387
|
+
$.push({ type: "option", value: L.value, label: L.label });
|
|
1388
|
+
return $;
|
|
1389
|
+
});
|
|
1390
|
+
function v($) {
|
|
1391
|
+
return $.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "");
|
|
1392
|
+
}
|
|
1393
|
+
const m = b(() => {
|
|
1394
|
+
if (!s.value) return d.value;
|
|
1395
|
+
const $ = v(s.value);
|
|
1396
|
+
return d.value.filter((C) => C.type === "group" ? !0 : v(C.label).includes($)).filter((C, _, D) => {
|
|
1397
|
+
if (C.type === "group") {
|
|
1398
|
+
const V = D[_ + 1];
|
|
1399
|
+
return V && V.type === "option";
|
|
1400
|
+
}
|
|
1401
|
+
return !0;
|
|
1402
|
+
});
|
|
1403
|
+
}), f = b(() => m.value.some(($) => $.type === "option")), p = b(() => {
|
|
1404
|
+
if (t.multiple || r.value == null) return "";
|
|
1405
|
+
const $ = d.value.find((L) => L.type === "option" && L.value === r.value);
|
|
1406
|
+
return $ ? $.label : "";
|
|
1407
|
+
}), x = b(() => !t.multiple || !Array.isArray(r.value) ? [] : r.value.map(($) => {
|
|
1408
|
+
const L = d.value.find((C) => C.type === "option" && C.value === $);
|
|
1409
|
+
return { value: $, label: L ? L.label : String($) };
|
|
1410
|
+
})), S = b(() => [
|
|
1411
|
+
"flex items-center w-full min-h-[40px] rounded-input border bg-white transition-colors",
|
|
1412
|
+
"duration-150 cursor-pointer text-left",
|
|
1413
|
+
"focus-visible:ring-2 focus-visible:ring-offset-[2px] focus-visible:outline-none",
|
|
1414
|
+
t.error ? "border-red-500 focus-visible:ring-red-500" : "border-lu-border focus-visible:ring-teal-500 focus-visible:border-teal-500",
|
|
1415
|
+
t.disabled ? "opacity-50 cursor-not-allowed bg-gray-50" : ""
|
|
1416
|
+
]);
|
|
1417
|
+
function k($) {
|
|
1418
|
+
return t.multiple ? Array.isArray(r.value) && r.value.includes($) : r.value === $;
|
|
1419
|
+
}
|
|
1420
|
+
function h() {
|
|
1421
|
+
t.disabled || (o.value = !o.value, o.value && (s.value = "", pe(() => {
|
|
1422
|
+
var $;
|
|
1423
|
+
($ = u.value) == null || $.focus();
|
|
1424
|
+
})));
|
|
1425
|
+
}
|
|
1426
|
+
function I($) {
|
|
1427
|
+
if (t.multiple) {
|
|
1428
|
+
const L = Array.isArray(r.value) ? [...r.value] : [], C = L.indexOf($);
|
|
1429
|
+
C >= 0 ? L.splice(C, 1) : L.push($), r.value = L;
|
|
1430
|
+
} else
|
|
1431
|
+
r.value = $, o.value = !1;
|
|
1432
|
+
}
|
|
1433
|
+
function F($) {
|
|
1434
|
+
if (t.disabled) return;
|
|
1435
|
+
const L = Array.isArray(r.value) ? [...r.value] : [];
|
|
1436
|
+
r.value = L.filter((C) => C !== $);
|
|
1437
|
+
}
|
|
1438
|
+
function N($) {
|
|
1439
|
+
$.key === "Escape" && (o.value = !1);
|
|
1440
|
+
}
|
|
1441
|
+
return ($, L) => (n(), a("div", {
|
|
1442
|
+
ref_key: "containerRef",
|
|
1443
|
+
ref: i,
|
|
1444
|
+
class: "flex flex-col gap-1",
|
|
1445
|
+
onKeydown: N
|
|
1446
|
+
}, [
|
|
1447
|
+
e.label ? (n(), a("label", {
|
|
1448
|
+
key: 0,
|
|
1449
|
+
for: g,
|
|
1450
|
+
class: "text-sm font-medium text-gray-700"
|
|
1451
|
+
}, y(e.label), 1)) : c("", !0),
|
|
1452
|
+
l("div", Sn, [
|
|
1453
|
+
l("div", {
|
|
1454
|
+
id: g,
|
|
1455
|
+
role: "combobox",
|
|
1456
|
+
class: w(S.value),
|
|
1457
|
+
tabindex: e.disabled ? -1 : 0,
|
|
1458
|
+
"aria-expanded": o.value,
|
|
1459
|
+
"aria-haspopup": "listbox",
|
|
1460
|
+
"aria-invalid": !!e.error || void 0,
|
|
1461
|
+
"aria-describedby": e.error ? `${g}-error` : void 0,
|
|
1462
|
+
"aria-disabled": e.disabled || void 0,
|
|
1463
|
+
onClick: h,
|
|
1464
|
+
onKeydown: [
|
|
1465
|
+
Q(U(h, ["prevent"]), ["enter"]),
|
|
1466
|
+
Q(U(h, ["prevent"]), ["space"])
|
|
1467
|
+
]
|
|
1468
|
+
}, [
|
|
1469
|
+
l("div", Ln, [
|
|
1470
|
+
e.multiple && x.value.length > 0 ? (n(!0), a(z, { key: 0 }, j(x.value, (C) => (n(), a("span", {
|
|
1471
|
+
key: C.value,
|
|
1472
|
+
class: "inline-flex items-center gap-1 bg-teal-50 text-teal-700 px-2 py-0.5 rounded text-xs font-medium max-w-[160px]"
|
|
1473
|
+
}, [
|
|
1474
|
+
l("span", An, y(C.label), 1),
|
|
1475
|
+
l("button", {
|
|
1476
|
+
type: "button",
|
|
1477
|
+
class: "shrink-0 hover:text-teal-900 focus:outline-none",
|
|
1478
|
+
"aria-label": `${C.label} entfernen`,
|
|
1479
|
+
onClick: U((_) => F(C.value), ["stop"])
|
|
1480
|
+
}, [...L[2] || (L[2] = [
|
|
1481
|
+
l("svg", {
|
|
1482
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1483
|
+
class: "h-3 w-3",
|
|
1484
|
+
viewBox: "0 0 24 24",
|
|
1485
|
+
fill: "none",
|
|
1486
|
+
stroke: "currentColor",
|
|
1487
|
+
"stroke-width": "2",
|
|
1488
|
+
"stroke-linecap": "round",
|
|
1489
|
+
"stroke-linejoin": "round",
|
|
1490
|
+
"aria-hidden": "true"
|
|
1491
|
+
}, [
|
|
1492
|
+
l("line", {
|
|
1493
|
+
x1: "18",
|
|
1494
|
+
y1: "6",
|
|
1495
|
+
x2: "6",
|
|
1496
|
+
y2: "18"
|
|
1497
|
+
}),
|
|
1498
|
+
l("line", {
|
|
1499
|
+
x1: "6",
|
|
1500
|
+
y1: "6",
|
|
1501
|
+
x2: "18",
|
|
1502
|
+
y2: "18"
|
|
1503
|
+
})
|
|
1504
|
+
], -1)
|
|
1505
|
+
])], 8, _n)
|
|
1506
|
+
]))), 128)) : p.value ? (n(), a("span", Bn, y(p.value), 1)) : (n(), a("span", En, y(e.placeholder), 1))
|
|
1507
|
+
]),
|
|
1508
|
+
l("span", In, [
|
|
1509
|
+
(n(), a("svg", {
|
|
1510
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1511
|
+
class: w(["h-5 w-5 transition-transform duration-150", o.value ? "rotate-180" : ""]),
|
|
1512
|
+
viewBox: "0 0 24 24",
|
|
1513
|
+
fill: "none",
|
|
1514
|
+
stroke: "currentColor",
|
|
1515
|
+
"stroke-width": "2",
|
|
1516
|
+
"stroke-linecap": "round",
|
|
1517
|
+
"stroke-linejoin": "round",
|
|
1518
|
+
"aria-hidden": "true"
|
|
1519
|
+
}, [...L[3] || (L[3] = [
|
|
1520
|
+
l("polyline", { points: "6 9 12 15 18 9" }, null, -1)
|
|
1521
|
+
])], 2))
|
|
1522
|
+
])
|
|
1523
|
+
], 42, Cn),
|
|
1524
|
+
o.value ? (n(), a("div", zn, [
|
|
1525
|
+
e.searchable ? (n(), a("div", Tn, [
|
|
1526
|
+
ee(l("input", {
|
|
1527
|
+
ref_key: "searchInputRef",
|
|
1528
|
+
ref: u,
|
|
1529
|
+
"onUpdate:modelValue": L[0] || (L[0] = (C) => s.value = C),
|
|
1530
|
+
type: "text",
|
|
1531
|
+
class: "w-full px-3 py-1.5 text-sm border border-lu-border rounded-input outline-none focus:ring-2 focus:ring-teal-500 focus:border-teal-500 placeholder-gray-400",
|
|
1532
|
+
placeholder: "Suchen\\u2026",
|
|
1533
|
+
onClick: L[1] || (L[1] = U(() => {
|
|
1534
|
+
}, ["stop"]))
|
|
1535
|
+
}, null, 512), [
|
|
1536
|
+
[ge, s.value]
|
|
1537
|
+
])
|
|
1538
|
+
])) : c("", !0),
|
|
1539
|
+
l("ul", {
|
|
1540
|
+
role: "listbox",
|
|
1541
|
+
"aria-multiselectable": e.multiple || void 0,
|
|
1542
|
+
class: "py-1"
|
|
1543
|
+
}, [
|
|
1544
|
+
(n(!0), a(z, null, j(m.value, (C) => (n(), a(z, {
|
|
1545
|
+
key: C.type === "option" ? String(C.value) : "group-" + C.label
|
|
1546
|
+
}, [
|
|
1547
|
+
C.type === "group" ? (n(), a("li", jn, y(C.label), 1)) : (n(), a("li", {
|
|
1548
|
+
key: 1,
|
|
1549
|
+
role: "option",
|
|
1550
|
+
"aria-selected": k(C.value),
|
|
1551
|
+
class: w([
|
|
1552
|
+
"flex items-center h-10 px-3 text-sm cursor-pointer transition-colors duration-100",
|
|
1553
|
+
k(C.value) ? "text-teal-500 bg-teal-50/50" : "text-gray-900 hover:bg-gray-50"
|
|
1554
|
+
]),
|
|
1555
|
+
onClick: (_) => I(C.value)
|
|
1556
|
+
}, [
|
|
1557
|
+
l("span", Dn, y(C.label), 1),
|
|
1558
|
+
k(C.value) ? (n(), a("svg", Vn, [...L[4] || (L[4] = [
|
|
1559
|
+
l("polyline", { points: "20 6 9 17 4 12" }, null, -1)
|
|
1560
|
+
])])) : c("", !0)
|
|
1561
|
+
], 10, On))
|
|
1562
|
+
], 64))), 128)),
|
|
1563
|
+
f.value ? c("", !0) : (n(), a("li", Pn, " Keine Ergebnisse "))
|
|
1564
|
+
], 8, Mn)
|
|
1565
|
+
])) : c("", !0)
|
|
1566
|
+
]),
|
|
1567
|
+
e.error ? (n(), a("p", {
|
|
1568
|
+
key: 1,
|
|
1569
|
+
id: `${g}-error`,
|
|
1570
|
+
class: "text-xs text-red-500",
|
|
1571
|
+
role: "alert"
|
|
1572
|
+
}, y(e.error), 9, Rn)) : c("", !0)
|
|
1573
|
+
], 544));
|
|
1574
|
+
}
|
|
1575
|
+
}, Fn = {
|
|
1576
|
+
key: 0,
|
|
1577
|
+
class: "text-red-500 ml-0.5"
|
|
1578
|
+
}, qn = { class: "relative" }, Kn = ["disabled", "aria-expanded", "aria-invalid"], Un = {
|
|
1579
|
+
key: 0,
|
|
1580
|
+
class: "absolute top-full left-0 z-dropdown mt-1 bg-white border border-lu-border rounded-card shadow-card p-3 w-[296px]"
|
|
1581
|
+
}, Hn = { class: "flex items-center justify-between mb-2" }, Zn = { class: "text-sm font-semibold text-gray-900 capitalize" }, Wn = { class: "grid grid-cols-7 mb-1" }, Gn = { class: "grid grid-cols-7" }, Xn = ["onClick"], Jn = ["id"], Yn = {
|
|
1582
|
+
__name: "LuDatePicker",
|
|
1583
|
+
props: /* @__PURE__ */ te({
|
|
1584
|
+
/** Label text displayed above the input. */
|
|
1585
|
+
label: {
|
|
1586
|
+
type: String,
|
|
1587
|
+
default: ""
|
|
1588
|
+
},
|
|
1589
|
+
/** Placeholder text when no date is selected. */
|
|
1590
|
+
placeholder: {
|
|
1591
|
+
type: String,
|
|
1592
|
+
default: "TT.MM.JJJJ"
|
|
1593
|
+
},
|
|
1594
|
+
/** Error message displayed below the input. Triggers red border styling. */
|
|
1595
|
+
error: {
|
|
1596
|
+
type: String,
|
|
1597
|
+
default: ""
|
|
1598
|
+
},
|
|
1599
|
+
/** Whether the date picker is disabled. */
|
|
1600
|
+
disabled: {
|
|
1601
|
+
type: Boolean,
|
|
1602
|
+
default: !1
|
|
1603
|
+
},
|
|
1604
|
+
/** Whether the field is required. */
|
|
1605
|
+
required: {
|
|
1606
|
+
type: Boolean,
|
|
1607
|
+
default: !1
|
|
1608
|
+
},
|
|
1609
|
+
/** ISO date string (YYYY-MM-DD) for range-mode start highlight. */
|
|
1610
|
+
rangeStart: {
|
|
1611
|
+
type: String,
|
|
1612
|
+
default: ""
|
|
1613
|
+
},
|
|
1614
|
+
/** ISO date string (YYYY-MM-DD) for range-mode end highlight. */
|
|
1615
|
+
rangeEnd: {
|
|
1616
|
+
type: String,
|
|
1617
|
+
default: ""
|
|
1618
|
+
}
|
|
1619
|
+
}, {
|
|
1620
|
+
modelValue: { type: String, default: "" },
|
|
1621
|
+
modelModifiers: {}
|
|
1622
|
+
}),
|
|
1623
|
+
emits: ["update:modelValue"],
|
|
1624
|
+
setup(e) {
|
|
1625
|
+
const r = G(e, "modelValue"), t = e, o = E(!1), s = E(/* @__PURE__ */ new Date()), i = E(null), u = `lu-datepicker-${q()}`;
|
|
1626
|
+
ne(i, () => {
|
|
1627
|
+
o.value = !1;
|
|
1628
|
+
});
|
|
1629
|
+
const g = ["Mo", "Di", "Mi", "Do", "Fr", "Sa", "So"];
|
|
1630
|
+
function d(_) {
|
|
1631
|
+
if (!_) return null;
|
|
1632
|
+
const D = Ne(_);
|
|
1633
|
+
return isNaN(D.getTime()) ? null : D;
|
|
1634
|
+
}
|
|
1635
|
+
const v = b(() => d(r.value)), m = b(() => d(t.rangeStart)), f = b(() => d(t.rangeEnd)), p = b(() => {
|
|
1636
|
+
const _ = v.value;
|
|
1637
|
+
return _ ? se(_, "dd.MM.yyyy") : "";
|
|
1638
|
+
}), x = b(() => se(s.value, "MMMM yyyy", { locale: We })), S = b(() => {
|
|
1639
|
+
const _ = J(s.value), D = De(s.value), V = Ve(_, { weekStartsOn: 1 }), X = Pe(D, { weekStartsOn: 1 });
|
|
1640
|
+
return Re({ start: V, end: X });
|
|
1641
|
+
}), k = b(() => [
|
|
1642
|
+
"flex items-center w-full h-10 rounded-input border bg-white transition-colors",
|
|
1643
|
+
"duration-150 cursor-pointer",
|
|
1644
|
+
"focus-within:ring-2 focus-within:ring-offset-[2px]",
|
|
1645
|
+
t.error ? "border-red-500 focus-within:ring-red-500" : "border-lu-border focus-within:ring-teal-500 focus-within:border-teal-500",
|
|
1646
|
+
t.disabled ? "opacity-50 cursor-not-allowed bg-gray-50" : ""
|
|
1647
|
+
]);
|
|
1648
|
+
function h(_) {
|
|
1649
|
+
return !m.value || !f.value ? !1 : Ze(_, {
|
|
1650
|
+
start: m.value,
|
|
1651
|
+
end: f.value
|
|
1652
|
+
});
|
|
1653
|
+
}
|
|
1654
|
+
function I(_) {
|
|
1655
|
+
const D = v.value && Ke(_, v.value), V = Ue(_, s.value), X = He(_), Le = h(_), fe = _.getDay() === 0;
|
|
1656
|
+
return D ? "bg-teal-500 text-white font-medium" : V ? X ? "bg-teal-50 text-teal-700 font-semibold" : Le ? fe ? "bg-teal-50 text-gray-400" : "bg-teal-50 text-gray-900" : fe ? "text-gray-400 hover:bg-gray-50" : "text-gray-900 hover:bg-gray-50" : "text-gray-300";
|
|
1657
|
+
}
|
|
1658
|
+
function F() {
|
|
1659
|
+
t.disabled || (o.value || (s.value = v.value ? J(v.value) : J(/* @__PURE__ */ new Date())), o.value = !o.value);
|
|
1660
|
+
}
|
|
1661
|
+
function N() {
|
|
1662
|
+
s.value = Fe(s.value, 1);
|
|
1663
|
+
}
|
|
1664
|
+
function $() {
|
|
1665
|
+
s.value = qe(s.value, 1);
|
|
1666
|
+
}
|
|
1667
|
+
function L(_) {
|
|
1668
|
+
r.value = se(_, "yyyy-MM-dd"), s.value = J(_), o.value = !1;
|
|
1669
|
+
}
|
|
1670
|
+
function C(_) {
|
|
1671
|
+
_.key === "Escape" && (o.value = !1);
|
|
1672
|
+
}
|
|
1673
|
+
return (_, D) => (n(), a("div", {
|
|
1674
|
+
ref_key: "containerRef",
|
|
1675
|
+
ref: i,
|
|
1676
|
+
class: "flex flex-col gap-1",
|
|
1677
|
+
onKeydown: C
|
|
1678
|
+
}, [
|
|
1679
|
+
e.label ? (n(), a("label", {
|
|
1680
|
+
key: 0,
|
|
1681
|
+
for: u,
|
|
1682
|
+
class: "text-sm font-medium text-gray-700"
|
|
1683
|
+
}, [
|
|
1684
|
+
M(y(e.label) + " ", 1),
|
|
1685
|
+
e.required ? (n(), a("span", Fn, "*")) : c("", !0)
|
|
1686
|
+
])) : c("", !0),
|
|
1687
|
+
l("div", qn, [
|
|
1688
|
+
l("button", {
|
|
1689
|
+
id: u,
|
|
1690
|
+
type: "button",
|
|
1691
|
+
class: w(k.value),
|
|
1692
|
+
disabled: e.disabled,
|
|
1693
|
+
"aria-expanded": o.value,
|
|
1694
|
+
"aria-invalid": !!e.error || void 0,
|
|
1695
|
+
onClick: F
|
|
1696
|
+
}, [
|
|
1697
|
+
l("span", {
|
|
1698
|
+
class: w(["flex-1 px-3 text-sm text-left truncate", p.value ? "text-gray-900" : "text-gray-400"])
|
|
1699
|
+
}, y(p.value || e.placeholder), 3),
|
|
1700
|
+
D[0] || (D[0] = ze('<span class="pr-3 shrink-0 text-gray-400"><svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="3" y="4" width="18" height="18" rx="2" ry="2"></rect><line x1="16" y1="2" x2="16" y2="6"></line><line x1="8" y1="2" x2="8" y2="6"></line><line x1="3" y1="10" x2="21" y2="10"></line></svg></span>', 1))
|
|
1701
|
+
], 10, Kn),
|
|
1702
|
+
o.value ? (n(), a("div", Un, [
|
|
1703
|
+
l("div", Hn, [
|
|
1704
|
+
l("button", {
|
|
1705
|
+
type: "button",
|
|
1706
|
+
class: "h-8 w-8 flex items-center justify-center rounded-full text-gray-500 hover:bg-gray-100 transition-colors duration-100 focus:outline-none focus-visible:ring-2 focus-visible:ring-teal-500",
|
|
1707
|
+
"aria-label": "Vorheriger Monat",
|
|
1708
|
+
onClick: N
|
|
1709
|
+
}, [...D[1] || (D[1] = [
|
|
1710
|
+
l("svg", {
|
|
1711
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1712
|
+
class: "h-5 w-5",
|
|
1713
|
+
viewBox: "0 0 24 24",
|
|
1714
|
+
fill: "none",
|
|
1715
|
+
stroke: "currentColor",
|
|
1716
|
+
"stroke-width": "2",
|
|
1717
|
+
"stroke-linecap": "round",
|
|
1718
|
+
"stroke-linejoin": "round",
|
|
1719
|
+
"aria-hidden": "true"
|
|
1720
|
+
}, [
|
|
1721
|
+
l("polyline", { points: "15 18 9 12 15 6" })
|
|
1722
|
+
], -1)
|
|
1723
|
+
])]),
|
|
1724
|
+
l("span", Zn, y(x.value), 1),
|
|
1725
|
+
l("button", {
|
|
1726
|
+
type: "button",
|
|
1727
|
+
class: "h-8 w-8 flex items-center justify-center rounded-full text-gray-500 hover:bg-gray-100 transition-colors duration-100 focus:outline-none focus-visible:ring-2 focus-visible:ring-teal-500",
|
|
1728
|
+
"aria-label": "Naechster Monat",
|
|
1729
|
+
onClick: $
|
|
1730
|
+
}, [...D[2] || (D[2] = [
|
|
1731
|
+
l("svg", {
|
|
1732
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1733
|
+
class: "h-5 w-5",
|
|
1734
|
+
viewBox: "0 0 24 24",
|
|
1735
|
+
fill: "none",
|
|
1736
|
+
stroke: "currentColor",
|
|
1737
|
+
"stroke-width": "2",
|
|
1738
|
+
"stroke-linecap": "round",
|
|
1739
|
+
"stroke-linejoin": "round",
|
|
1740
|
+
"aria-hidden": "true"
|
|
1741
|
+
}, [
|
|
1742
|
+
l("polyline", { points: "9 6 15 12 9 18" })
|
|
1743
|
+
], -1)
|
|
1744
|
+
])])
|
|
1745
|
+
]),
|
|
1746
|
+
l("div", Wn, [
|
|
1747
|
+
(n(), a(z, null, j(g, (V) => l("span", {
|
|
1748
|
+
key: V,
|
|
1749
|
+
class: "h-8 flex items-center justify-center text-xs font-medium text-gray-500"
|
|
1750
|
+
}, y(V), 1)), 64))
|
|
1751
|
+
]),
|
|
1752
|
+
l("div", Gn, [
|
|
1753
|
+
(n(!0), a(z, null, j(S.value, (V) => (n(), a("button", {
|
|
1754
|
+
key: V.toISOString(),
|
|
1755
|
+
type: "button",
|
|
1756
|
+
class: w(["h-9 w-9 mx-auto flex items-center justify-center text-sm rounded-full transition-colors duration-100 focus:outline-none focus-visible:ring-2 focus-visible:ring-teal-500", I(V)]),
|
|
1757
|
+
onClick: (X) => L(V)
|
|
1758
|
+
}, y(V.getDate()), 11, Xn))), 128))
|
|
1759
|
+
])
|
|
1760
|
+
])) : c("", !0)
|
|
1761
|
+
]),
|
|
1762
|
+
e.error ? (n(), a("p", {
|
|
1763
|
+
key: 1,
|
|
1764
|
+
id: `${u}-error`,
|
|
1765
|
+
class: "text-xs text-red-500",
|
|
1766
|
+
role: "alert"
|
|
1767
|
+
}, y(e.error), 9, Jn)) : c("", !0)
|
|
1768
|
+
], 544));
|
|
1769
|
+
}
|
|
1770
|
+
}, Qn = { class: "lu-tabs" }, ea = {
|
|
1771
|
+
__name: "LuTabs",
|
|
1772
|
+
props: {
|
|
1773
|
+
modelValue: { type: String, default: "" },
|
|
1774
|
+
modelModifiers: {}
|
|
1775
|
+
},
|
|
1776
|
+
emits: ["update:modelValue"],
|
|
1777
|
+
setup(e) {
|
|
1778
|
+
const r = G(e, "modelValue");
|
|
1779
|
+
return Te("lu-tabs", {
|
|
1780
|
+
/** @type {import('vue').ComputedRef<string>} */
|
|
1781
|
+
activeTab: b(() => r.value),
|
|
1782
|
+
/**
|
|
1783
|
+
* Set the active tab (called by LuTab on click).
|
|
1784
|
+
* @param {string} value
|
|
1785
|
+
*/
|
|
1786
|
+
setActiveTab(t) {
|
|
1787
|
+
r.value = t;
|
|
1788
|
+
},
|
|
1789
|
+
/** Shared ID prefix for ARIA cross-references. */
|
|
1790
|
+
tabsId: `lu-tabs-${q()}`
|
|
1791
|
+
}), (t, o) => (n(), a("div", Qn, [
|
|
1792
|
+
B(t.$slots, "default")
|
|
1793
|
+
]));
|
|
1794
|
+
}
|
|
1795
|
+
}, ta = {
|
|
1796
|
+
__name: "LuTabList",
|
|
1797
|
+
setup(e) {
|
|
1798
|
+
const r = E(null);
|
|
1799
|
+
function t(o) {
|
|
1800
|
+
var d;
|
|
1801
|
+
const s = r.value;
|
|
1802
|
+
if (!s) return;
|
|
1803
|
+
const i = (
|
|
1804
|
+
/** @type {HTMLElement[]} */
|
|
1805
|
+
[...s.querySelectorAll('[role="tab"]')]
|
|
1806
|
+
);
|
|
1807
|
+
if (i.length === 0) return;
|
|
1808
|
+
const u = i.indexOf(
|
|
1809
|
+
/** @type {HTMLElement} */
|
|
1810
|
+
document.activeElement
|
|
1811
|
+
);
|
|
1812
|
+
if (u === -1) return;
|
|
1813
|
+
let g = null;
|
|
1814
|
+
switch (o.key) {
|
|
1815
|
+
case "ArrowRight":
|
|
1816
|
+
g = (u + 1) % i.length;
|
|
1817
|
+
break;
|
|
1818
|
+
case "ArrowLeft":
|
|
1819
|
+
g = (u - 1 + i.length) % i.length;
|
|
1820
|
+
break;
|
|
1821
|
+
case "Home":
|
|
1822
|
+
g = 0;
|
|
1823
|
+
break;
|
|
1824
|
+
case "End":
|
|
1825
|
+
g = i.length - 1;
|
|
1826
|
+
break;
|
|
1827
|
+
default:
|
|
1828
|
+
return;
|
|
1829
|
+
}
|
|
1830
|
+
o.preventDefault(), (d = i[g]) == null || d.focus();
|
|
1831
|
+
}
|
|
1832
|
+
return (o, s) => (n(), a("div", {
|
|
1833
|
+
ref_key: "tabListRef",
|
|
1834
|
+
ref: r,
|
|
1835
|
+
role: "tablist",
|
|
1836
|
+
class: "flex border-b border-lu-border",
|
|
1837
|
+
onKeydown: t
|
|
1838
|
+
}, [
|
|
1839
|
+
B(o.$slots, "default")
|
|
1840
|
+
], 544));
|
|
1841
|
+
}
|
|
1842
|
+
}, na = ["id", "aria-selected", "aria-controls", "tabindex"], aa = {
|
|
1843
|
+
__name: "LuTab",
|
|
1844
|
+
props: {
|
|
1845
|
+
/**
|
|
1846
|
+
* Unique identifier that links this tab to its corresponding LuTabPanel.
|
|
1847
|
+
*/
|
|
1848
|
+
value: {
|
|
1849
|
+
type: String,
|
|
1850
|
+
required: !0
|
|
1851
|
+
}
|
|
1852
|
+
},
|
|
1853
|
+
setup(e) {
|
|
1854
|
+
const r = e, t = he("lu-tabs"), o = b(() => t.activeTab.value === r.value), s = b(() => `${t.tabsId}-tab-${r.value}`), i = b(() => `${t.tabsId}-panel-${r.value}`), u = b(() => [
|
|
1855
|
+
"px-4 py-3 text-sm font-medium transition-colors duration-150 -mb-px",
|
|
1856
|
+
"focus:outline-none focus-visible:ring-2 focus-visible:ring-teal-500 focus-visible:ring-offset-[-2px]",
|
|
1857
|
+
"cursor-pointer whitespace-nowrap",
|
|
1858
|
+
o.value ? "text-gray-900 border-b-2 border-teal-500" : "text-gray-500 border-b-2 border-transparent hover:text-gray-700"
|
|
1859
|
+
]);
|
|
1860
|
+
return (g, d) => (n(), a("button", {
|
|
1861
|
+
id: s.value,
|
|
1862
|
+
type: "button",
|
|
1863
|
+
role: "tab",
|
|
1864
|
+
"aria-selected": o.value,
|
|
1865
|
+
"aria-controls": i.value,
|
|
1866
|
+
tabindex: o.value ? 0 : -1,
|
|
1867
|
+
class: w(u.value),
|
|
1868
|
+
onClick: d[0] || (d[0] = (v) => R(t).setActiveTab(e.value))
|
|
1869
|
+
}, [
|
|
1870
|
+
B(g.$slots, "default")
|
|
1871
|
+
], 10, na));
|
|
1872
|
+
}
|
|
1873
|
+
}, ra = ["id", "aria-labelledby"], sa = {
|
|
1874
|
+
__name: "LuTabPanel",
|
|
1875
|
+
props: {
|
|
1876
|
+
/**
|
|
1877
|
+
* Must match the `value` prop of the corresponding LuTab.
|
|
1878
|
+
*/
|
|
1879
|
+
value: {
|
|
1880
|
+
type: String,
|
|
1881
|
+
required: !0
|
|
1882
|
+
}
|
|
1883
|
+
},
|
|
1884
|
+
setup(e) {
|
|
1885
|
+
const r = e, t = he("lu-tabs"), o = b(() => t.activeTab.value === r.value), s = b(() => `${t.tabsId}-panel-${r.value}`), i = b(() => `${t.tabsId}-tab-${r.value}`);
|
|
1886
|
+
return (u, g) => o.value ? (n(), a("div", {
|
|
1887
|
+
key: 0,
|
|
1888
|
+
id: s.value,
|
|
1889
|
+
role: "tabpanel",
|
|
1890
|
+
"aria-labelledby": i.value,
|
|
1891
|
+
tabindex: 0
|
|
1892
|
+
}, [
|
|
1893
|
+
B(u.$slots, "default")
|
|
1894
|
+
], 8, ra)) : c("", !0);
|
|
1895
|
+
}
|
|
1896
|
+
}, la = {
|
|
1897
|
+
"aria-label": "Seitennavigation",
|
|
1898
|
+
class: "flex flex-wrap items-center justify-between gap-4"
|
|
1899
|
+
}, oa = { class: "flex items-center gap-2 text-sm text-gray-600" }, ia = ["value"], ua = ["value"], da = { class: "flex items-center gap-1" }, ca = ["disabled"], fa = {
|
|
1900
|
+
key: 0,
|
|
1901
|
+
class: "h-8 min-w-[32px] flex items-center justify-center text-sm text-gray-400 select-none",
|
|
1902
|
+
"aria-hidden": "true"
|
|
1903
|
+
}, ba = ["aria-current", "aria-label", "onClick"], ga = ["disabled"], ya = { class: "text-sm text-gray-500" }, le = "h-8 min-w-[32px] px-2 flex items-center justify-center text-sm rounded-input transition-colors duration-100 focus:outline-none focus-visible:ring-2 focus-visible:ring-teal-500 focus-visible:ring-offset-1", va = {
|
|
1904
|
+
__name: "LuPagination",
|
|
1905
|
+
props: {
|
|
1906
|
+
/** Current active page (1-based). */
|
|
1907
|
+
currentPage: {
|
|
1908
|
+
type: Number,
|
|
1909
|
+
required: !0
|
|
1910
|
+
},
|
|
1911
|
+
/** Total number of pages. */
|
|
1912
|
+
totalPages: {
|
|
1913
|
+
type: Number,
|
|
1914
|
+
required: !0
|
|
1915
|
+
},
|
|
1916
|
+
/** Total number of items across all pages. */
|
|
1917
|
+
totalItems: {
|
|
1918
|
+
type: Number,
|
|
1919
|
+
default: 0
|
|
1920
|
+
},
|
|
1921
|
+
/** Number of items shown per page. */
|
|
1922
|
+
itemsPerPage: {
|
|
1923
|
+
type: Number,
|
|
1924
|
+
default: 10
|
|
1925
|
+
}
|
|
1926
|
+
},
|
|
1927
|
+
emits: {
|
|
1928
|
+
/**
|
|
1929
|
+
* Emitted when the user navigates to a different page.
|
|
1930
|
+
* @param {number} page
|
|
1931
|
+
*/
|
|
1932
|
+
change: (e) => typeof e == "number",
|
|
1933
|
+
/**
|
|
1934
|
+
* Emitted when the user changes the items-per-page setting.
|
|
1935
|
+
* @param {number} perPage
|
|
1936
|
+
*/
|
|
1937
|
+
"change-per-page": (e) => typeof e == "number"
|
|
1938
|
+
},
|
|
1939
|
+
setup(e, { emit: r }) {
|
|
1940
|
+
const t = e, o = r, s = [10, 25, 50], i = b(() => t.currentPage <= 1), u = b(() => t.currentPage >= t.totalPages), g = b(() => {
|
|
1941
|
+
const x = t.totalPages, S = t.currentPage;
|
|
1942
|
+
if (x <= 7)
|
|
1943
|
+
return Array.from({ length: x }, (h, I) => ({ type: "page", value: I + 1 }));
|
|
1944
|
+
const k = [];
|
|
1945
|
+
if (S <= 4) {
|
|
1946
|
+
for (let h = 1; h <= 5; h++) k.push({ type: "page", value: h });
|
|
1947
|
+
k.push({ type: "ellipsis" }), k.push({ type: "page", value: x });
|
|
1948
|
+
} else if (S >= x - 3) {
|
|
1949
|
+
k.push({ type: "page", value: 1 }), k.push({ type: "ellipsis" });
|
|
1950
|
+
for (let h = x - 4; h <= x; h++) k.push({ type: "page", value: h });
|
|
1951
|
+
} else {
|
|
1952
|
+
k.push({ type: "page", value: 1 }), k.push({ type: "ellipsis" });
|
|
1953
|
+
for (let h = S - 1; h <= S + 1; h++) k.push({ type: "page", value: h });
|
|
1954
|
+
k.push({ type: "ellipsis" }), k.push({ type: "page", value: x });
|
|
1955
|
+
}
|
|
1956
|
+
return k;
|
|
1957
|
+
});
|
|
1958
|
+
function d(x) {
|
|
1959
|
+
x < 1 || x > t.totalPages || x === t.currentPage || o("change", x);
|
|
1960
|
+
}
|
|
1961
|
+
function v() {
|
|
1962
|
+
d(t.currentPage - 1);
|
|
1963
|
+
}
|
|
1964
|
+
function m() {
|
|
1965
|
+
d(t.currentPage + 1);
|
|
1966
|
+
}
|
|
1967
|
+
function f(x) {
|
|
1968
|
+
const S = Number(
|
|
1969
|
+
/** @type {HTMLSelectElement} */
|
|
1970
|
+
x.target.value
|
|
1971
|
+
);
|
|
1972
|
+
o("change-per-page", S);
|
|
1973
|
+
}
|
|
1974
|
+
const p = b(() => {
|
|
1975
|
+
if (t.totalItems > 0) {
|
|
1976
|
+
const x = (t.currentPage - 1) * t.itemsPerPage + 1, S = Math.min(t.currentPage * t.itemsPerPage, t.totalItems);
|
|
1977
|
+
return `${x}–${S} von ${t.totalItems} Eintraegen`;
|
|
1978
|
+
}
|
|
1979
|
+
return `Seite ${t.currentPage} von ${t.totalPages}`;
|
|
1980
|
+
});
|
|
1981
|
+
return (x, S) => (n(), a("nav", la, [
|
|
1982
|
+
l("div", oa, [
|
|
1983
|
+
S[0] || (S[0] = l("span", null, "Eintraege pro Seite", -1)),
|
|
1984
|
+
l("select", {
|
|
1985
|
+
value: e.itemsPerPage,
|
|
1986
|
+
class: "lu-pagination-select h-8 pl-2 pr-6 text-sm border border-lu-border rounded-input bg-white text-gray-900 outline-none focus:ring-2 focus:ring-teal-500 focus:border-teal-500 cursor-pointer appearance-none",
|
|
1987
|
+
onChange: f
|
|
1988
|
+
}, [
|
|
1989
|
+
(n(), a(z, null, j(s, (k) => l("option", {
|
|
1990
|
+
key: k,
|
|
1991
|
+
value: k
|
|
1992
|
+
}, y(k), 9, ua)), 64))
|
|
1993
|
+
], 40, ia)
|
|
1994
|
+
]),
|
|
1995
|
+
l("div", da, [
|
|
1996
|
+
l("button", {
|
|
1997
|
+
type: "button",
|
|
1998
|
+
class: w([
|
|
1999
|
+
le,
|
|
2000
|
+
i.value ? "text-gray-300 cursor-not-allowed" : "text-gray-600 hover:bg-gray-100"
|
|
2001
|
+
]),
|
|
2002
|
+
disabled: i.value,
|
|
2003
|
+
"aria-label": "Vorherige Seite",
|
|
2004
|
+
onClick: v
|
|
2005
|
+
}, [...S[1] || (S[1] = [
|
|
2006
|
+
l("svg", {
|
|
2007
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2008
|
+
class: "h-4 w-4",
|
|
2009
|
+
viewBox: "0 0 24 24",
|
|
2010
|
+
fill: "none",
|
|
2011
|
+
stroke: "currentColor",
|
|
2012
|
+
"stroke-width": "2",
|
|
2013
|
+
"stroke-linecap": "round",
|
|
2014
|
+
"stroke-linejoin": "round",
|
|
2015
|
+
"aria-hidden": "true"
|
|
2016
|
+
}, [
|
|
2017
|
+
l("polyline", { points: "15 18 9 12 15 6" })
|
|
2018
|
+
], -1)
|
|
2019
|
+
])], 10, ca),
|
|
2020
|
+
(n(!0), a(z, null, j(g.value, (k, h) => (n(), a(z, { key: h }, [
|
|
2021
|
+
k.type === "ellipsis" ? (n(), a("span", fa, " … ")) : (n(), a("button", {
|
|
2022
|
+
key: 1,
|
|
2023
|
+
type: "button",
|
|
2024
|
+
class: w([
|
|
2025
|
+
le,
|
|
2026
|
+
k.value === e.currentPage ? "bg-teal-500 text-white font-medium" : "text-gray-700 hover:bg-gray-100"
|
|
2027
|
+
]),
|
|
2028
|
+
"aria-current": k.value === e.currentPage ? "page" : void 0,
|
|
2029
|
+
"aria-label": `Seite ${k.value}`,
|
|
2030
|
+
onClick: (I) => d(k.value)
|
|
2031
|
+
}, y(k.value), 11, ba))
|
|
2032
|
+
], 64))), 128)),
|
|
2033
|
+
l("button", {
|
|
2034
|
+
type: "button",
|
|
2035
|
+
class: w([
|
|
2036
|
+
le,
|
|
2037
|
+
u.value ? "text-gray-300 cursor-not-allowed" : "text-gray-600 hover:bg-gray-100"
|
|
2038
|
+
]),
|
|
2039
|
+
disabled: u.value,
|
|
2040
|
+
"aria-label": "Naechste Seite",
|
|
2041
|
+
onClick: m
|
|
2042
|
+
}, [...S[2] || (S[2] = [
|
|
2043
|
+
l("svg", {
|
|
2044
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2045
|
+
class: "h-4 w-4",
|
|
2046
|
+
viewBox: "0 0 24 24",
|
|
2047
|
+
fill: "none",
|
|
2048
|
+
stroke: "currentColor",
|
|
2049
|
+
"stroke-width": "2",
|
|
2050
|
+
"stroke-linecap": "round",
|
|
2051
|
+
"stroke-linejoin": "round",
|
|
2052
|
+
"aria-hidden": "true"
|
|
2053
|
+
}, [
|
|
2054
|
+
l("polyline", { points: "9 6 15 12 9 18" })
|
|
2055
|
+
], -1)
|
|
2056
|
+
])], 10, ga)
|
|
2057
|
+
]),
|
|
2058
|
+
l("div", ya, y(p.value), 1)
|
|
2059
|
+
]));
|
|
2060
|
+
}
|
|
2061
|
+
}, ma = /* @__PURE__ */ W(va, [["__scopeId", "data-v-5ee36a88"]]), pa = ["checked", "disabled", "value"], ha = {
|
|
2062
|
+
key: 0,
|
|
2063
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2064
|
+
class: "w-3 h-3 text-white",
|
|
2065
|
+
viewBox: "0 0 24 24",
|
|
2066
|
+
fill: "none",
|
|
2067
|
+
stroke: "currentColor",
|
|
2068
|
+
"stroke-width": "3",
|
|
2069
|
+
"stroke-linecap": "round",
|
|
2070
|
+
"stroke-linejoin": "round",
|
|
2071
|
+
"aria-hidden": "true"
|
|
2072
|
+
}, xa = {
|
|
2073
|
+
key: 1,
|
|
2074
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2075
|
+
class: "w-3 h-3 text-white",
|
|
2076
|
+
viewBox: "0 0 24 24",
|
|
2077
|
+
fill: "none",
|
|
2078
|
+
stroke: "currentColor",
|
|
2079
|
+
"stroke-width": "3",
|
|
2080
|
+
"stroke-linecap": "round",
|
|
2081
|
+
"stroke-linejoin": "round",
|
|
2082
|
+
"aria-hidden": "true"
|
|
2083
|
+
}, wa = {
|
|
2084
|
+
key: 0,
|
|
2085
|
+
class: "text-sm text-gray-700 select-none"
|
|
2086
|
+
}, ka = {
|
|
2087
|
+
__name: "LuCheckbox",
|
|
2088
|
+
props: {
|
|
2089
|
+
/**
|
|
2090
|
+
* Current value – Boolean for single checkbox, Array for multi-select mode.
|
|
2091
|
+
* @type {boolean | Array<string | number>}
|
|
2092
|
+
*/
|
|
2093
|
+
modelValue: {
|
|
2094
|
+
type: [Boolean, Array],
|
|
2095
|
+
default: !1
|
|
2096
|
+
},
|
|
2097
|
+
/**
|
|
2098
|
+
* Value used in Array-mode. Each checkbox pushes/removes this value.
|
|
2099
|
+
* @type {string | number}
|
|
2100
|
+
*/
|
|
2101
|
+
value: {
|
|
2102
|
+
type: [String, Number],
|
|
2103
|
+
default: void 0
|
|
2104
|
+
},
|
|
2105
|
+
/**
|
|
2106
|
+
* Label text displayed next to the checkbox.
|
|
2107
|
+
*/
|
|
2108
|
+
label: {
|
|
2109
|
+
type: String,
|
|
2110
|
+
default: ""
|
|
2111
|
+
},
|
|
2112
|
+
/**
|
|
2113
|
+
* Whether the checkbox is disabled.
|
|
2114
|
+
*/
|
|
2115
|
+
disabled: {
|
|
2116
|
+
type: Boolean,
|
|
2117
|
+
default: !1
|
|
2118
|
+
},
|
|
2119
|
+
/**
|
|
2120
|
+
* Indeterminate state – shows a dash instead of checkmark.
|
|
2121
|
+
* Useful for "select all" checkboxes when some (but not all) items are selected.
|
|
2122
|
+
*/
|
|
2123
|
+
indeterminate: {
|
|
2124
|
+
type: Boolean,
|
|
2125
|
+
default: !1
|
|
2126
|
+
}
|
|
2127
|
+
},
|
|
2128
|
+
emits: ["update:modelValue"],
|
|
2129
|
+
setup(e, { emit: r }) {
|
|
2130
|
+
const t = e, o = r, s = `lu-checkbox-${q()}`, i = b(() => Array.isArray(t.modelValue) ? t.modelValue.includes(t.value) : !!t.modelValue);
|
|
2131
|
+
function u() {
|
|
2132
|
+
if (!t.disabled)
|
|
2133
|
+
if (Array.isArray(t.modelValue)) {
|
|
2134
|
+
const d = [...t.modelValue], v = d.indexOf(t.value);
|
|
2135
|
+
v === -1 ? d.push(t.value) : d.splice(v, 1), o("update:modelValue", d);
|
|
2136
|
+
} else
|
|
2137
|
+
o("update:modelValue", !t.modelValue);
|
|
2138
|
+
}
|
|
2139
|
+
const g = b(() => [
|
|
2140
|
+
"relative flex items-center justify-center shrink-0",
|
|
2141
|
+
"w-[18px] h-[18px] rounded-[4px] border-2 transition-colors duration-150",
|
|
2142
|
+
i.value || t.indeterminate ? "bg-teal-500 border-teal-500" : "bg-white border-gray-300",
|
|
2143
|
+
!t.disabled && "cursor-pointer"
|
|
2144
|
+
]);
|
|
2145
|
+
return (d, v) => (n(), a("label", {
|
|
2146
|
+
for: s,
|
|
2147
|
+
class: w(["inline-flex items-center gap-2", e.disabled ? "opacity-50 cursor-not-allowed pointer-events-none" : "cursor-pointer"])
|
|
2148
|
+
}, [
|
|
2149
|
+
l("input", {
|
|
2150
|
+
id: s,
|
|
2151
|
+
type: "checkbox",
|
|
2152
|
+
class: "sr-only peer",
|
|
2153
|
+
checked: i.value,
|
|
2154
|
+
disabled: e.disabled,
|
|
2155
|
+
value: e.value,
|
|
2156
|
+
onChange: u
|
|
2157
|
+
}, null, 40, pa),
|
|
2158
|
+
l("span", {
|
|
2159
|
+
class: w([g.value, "peer-focus-visible:ring-2 peer-focus-visible:ring-teal-500 peer-focus-visible:ring-offset-[2px]"]),
|
|
2160
|
+
"aria-hidden": "true"
|
|
2161
|
+
}, [
|
|
2162
|
+
i.value && !t.indeterminate ? (n(), a("svg", ha, [...v[0] || (v[0] = [
|
|
2163
|
+
l("polyline", { points: "20 6 9 17 4 12" }, null, -1)
|
|
2164
|
+
])])) : t.indeterminate ? (n(), a("svg", xa, [...v[1] || (v[1] = [
|
|
2165
|
+
l("line", {
|
|
2166
|
+
x1: "5",
|
|
2167
|
+
y1: "12",
|
|
2168
|
+
x2: "19",
|
|
2169
|
+
y2: "12"
|
|
2170
|
+
}, null, -1)
|
|
2171
|
+
])])) : c("", !0)
|
|
2172
|
+
], 2),
|
|
2173
|
+
e.label ? (n(), a("span", wa, y(e.label), 1)) : c("", !0)
|
|
2174
|
+
], 2));
|
|
2175
|
+
}
|
|
2176
|
+
}, $a = ["checked", "disabled", "name", "value"], Sa = {
|
|
2177
|
+
key: 0,
|
|
2178
|
+
class: "w-[10px] h-[10px] rounded-full bg-teal-500",
|
|
2179
|
+
"aria-hidden": "true"
|
|
2180
|
+
}, Ca = {
|
|
2181
|
+
key: 0,
|
|
2182
|
+
class: "text-sm text-gray-700 select-none"
|
|
2183
|
+
}, La = {
|
|
2184
|
+
__name: "LuRadio",
|
|
2185
|
+
props: {
|
|
2186
|
+
/**
|
|
2187
|
+
* Currently selected value of the radio group.
|
|
2188
|
+
* @type {string | number | boolean}
|
|
2189
|
+
*/
|
|
2190
|
+
modelValue: {
|
|
2191
|
+
type: [String, Number, Boolean],
|
|
2192
|
+
default: ""
|
|
2193
|
+
},
|
|
2194
|
+
/**
|
|
2195
|
+
* Value that this radio option represents.
|
|
2196
|
+
* @type {string | number | boolean}
|
|
2197
|
+
*/
|
|
2198
|
+
value: {
|
|
2199
|
+
type: [String, Number, Boolean],
|
|
2200
|
+
required: !0
|
|
2201
|
+
},
|
|
2202
|
+
/**
|
|
2203
|
+
* Label text displayed next to the radio button.
|
|
2204
|
+
*/
|
|
2205
|
+
label: {
|
|
2206
|
+
type: String,
|
|
2207
|
+
default: ""
|
|
2208
|
+
},
|
|
2209
|
+
/**
|
|
2210
|
+
* Name attribute to group radio buttons together.
|
|
2211
|
+
*/
|
|
2212
|
+
name: {
|
|
2213
|
+
type: String,
|
|
2214
|
+
default: ""
|
|
2215
|
+
},
|
|
2216
|
+
/**
|
|
2217
|
+
* Whether the radio button is disabled.
|
|
2218
|
+
*/
|
|
2219
|
+
disabled: {
|
|
2220
|
+
type: Boolean,
|
|
2221
|
+
default: !1
|
|
2222
|
+
}
|
|
2223
|
+
},
|
|
2224
|
+
emits: ["update:modelValue"],
|
|
2225
|
+
setup(e, { emit: r }) {
|
|
2226
|
+
const t = e, o = r, s = `lu-radio-${q()}`, i = b(() => t.modelValue === t.value);
|
|
2227
|
+
function u() {
|
|
2228
|
+
t.disabled || o("update:modelValue", t.value);
|
|
2229
|
+
}
|
|
2230
|
+
const g = b(() => [
|
|
2231
|
+
"relative flex items-center justify-center shrink-0",
|
|
2232
|
+
"w-[18px] h-[18px] rounded-full border-2 transition-colors duration-150",
|
|
2233
|
+
i.value ? "border-teal-500" : "border-gray-300",
|
|
2234
|
+
!t.disabled && "cursor-pointer"
|
|
2235
|
+
]);
|
|
2236
|
+
return (d, v) => (n(), a("label", {
|
|
2237
|
+
for: s,
|
|
2238
|
+
class: w(["inline-flex items-center gap-2", e.disabled ? "opacity-50 cursor-not-allowed pointer-events-none" : "cursor-pointer"])
|
|
2239
|
+
}, [
|
|
2240
|
+
l("input", {
|
|
2241
|
+
id: s,
|
|
2242
|
+
type: "radio",
|
|
2243
|
+
class: "sr-only peer",
|
|
2244
|
+
checked: i.value,
|
|
2245
|
+
disabled: e.disabled,
|
|
2246
|
+
name: e.name,
|
|
2247
|
+
value: e.value,
|
|
2248
|
+
onChange: u
|
|
2249
|
+
}, null, 40, $a),
|
|
2250
|
+
l("span", {
|
|
2251
|
+
class: w([g.value, "peer-focus-visible:ring-2 peer-focus-visible:ring-teal-500 peer-focus-visible:ring-offset-[2px]"]),
|
|
2252
|
+
"aria-hidden": "true"
|
|
2253
|
+
}, [
|
|
2254
|
+
i.value ? (n(), a("span", Sa)) : c("", !0)
|
|
2255
|
+
], 2),
|
|
2256
|
+
e.label ? (n(), a("span", Ca, y(e.label), 1)) : c("", !0)
|
|
2257
|
+
], 2));
|
|
2258
|
+
}
|
|
2259
|
+
}, Aa = ["aria-checked", "aria-label", "disabled"], _a = {
|
|
2260
|
+
__name: "LuToggle",
|
|
2261
|
+
props: {
|
|
2262
|
+
/**
|
|
2263
|
+
* Whether the toggle is on (true) or off (false).
|
|
2264
|
+
*/
|
|
2265
|
+
modelValue: {
|
|
2266
|
+
type: Boolean,
|
|
2267
|
+
default: !1
|
|
2268
|
+
},
|
|
2269
|
+
/**
|
|
2270
|
+
* Label text displayed next to the toggle.
|
|
2271
|
+
*/
|
|
2272
|
+
label: {
|
|
2273
|
+
type: String,
|
|
2274
|
+
default: ""
|
|
2275
|
+
},
|
|
2276
|
+
/**
|
|
2277
|
+
* Whether the toggle is disabled.
|
|
2278
|
+
*/
|
|
2279
|
+
disabled: {
|
|
2280
|
+
type: Boolean,
|
|
2281
|
+
default: !1
|
|
2282
|
+
}
|
|
2283
|
+
},
|
|
2284
|
+
emits: ["update:modelValue"],
|
|
2285
|
+
setup(e, { emit: r }) {
|
|
2286
|
+
const t = e, o = r, s = `lu-toggle-${q()}`;
|
|
2287
|
+
function i() {
|
|
2288
|
+
t.disabled || o("update:modelValue", !t.modelValue);
|
|
2289
|
+
}
|
|
2290
|
+
const u = b(() => [
|
|
2291
|
+
"relative inline-flex shrink-0",
|
|
2292
|
+
"w-[44px] h-[24px] rounded-full transition-colors duration-200",
|
|
2293
|
+
t.modelValue ? "bg-teal-500" : "bg-gray-300",
|
|
2294
|
+
!t.disabled && "cursor-pointer"
|
|
2295
|
+
]), g = b(() => [
|
|
2296
|
+
"absolute top-[2px] left-[2px]",
|
|
2297
|
+
"w-[20px] h-[20px] rounded-full bg-white shadow-sm",
|
|
2298
|
+
"transition-transform duration-200",
|
|
2299
|
+
t.modelValue ? "translate-x-[20px]" : "translate-x-0"
|
|
2300
|
+
]);
|
|
2301
|
+
return (d, v) => (n(), a("div", {
|
|
2302
|
+
class: w(["inline-flex items-center gap-2", e.disabled ? "opacity-50 cursor-not-allowed pointer-events-none" : ""])
|
|
2303
|
+
}, [
|
|
2304
|
+
l("button", {
|
|
2305
|
+
id: s,
|
|
2306
|
+
type: "button",
|
|
2307
|
+
role: "switch",
|
|
2308
|
+
"aria-checked": String(e.modelValue),
|
|
2309
|
+
"aria-label": e.label ? void 0 : "Toggle",
|
|
2310
|
+
disabled: e.disabled,
|
|
2311
|
+
class: w([u.value, "focus-visible:ring-2 focus-visible:ring-teal-500 focus-visible:ring-offset-[2px]"]),
|
|
2312
|
+
onClick: i
|
|
2313
|
+
}, [
|
|
2314
|
+
l("span", {
|
|
2315
|
+
class: w(g.value),
|
|
2316
|
+
"aria-hidden": "true"
|
|
2317
|
+
}, null, 2)
|
|
2318
|
+
], 10, Aa),
|
|
2319
|
+
e.label ? (n(), a("label", {
|
|
2320
|
+
key: 0,
|
|
2321
|
+
for: s,
|
|
2322
|
+
class: w(["text-sm text-gray-700 select-none", e.disabled ? "cursor-not-allowed" : "cursor-pointer"])
|
|
2323
|
+
}, y(e.label), 3)) : c("", !0)
|
|
2324
|
+
], 2));
|
|
2325
|
+
}
|
|
2326
|
+
}, Ba = { class: "flex flex-col gap-1.5" }, Ea = ["for"], Ia = {
|
|
2327
|
+
key: 0,
|
|
2328
|
+
class: "text-red-500 ml-0.5"
|
|
2329
|
+
}, za = {
|
|
2330
|
+
key: 1,
|
|
2331
|
+
class: "text-xs text-red-500 flex items-center gap-1",
|
|
2332
|
+
role: "alert"
|
|
2333
|
+
}, Ta = {
|
|
2334
|
+
key: 2,
|
|
2335
|
+
class: "text-xs text-gray-400"
|
|
2336
|
+
}, Ma = {
|
|
2337
|
+
__name: "LuFormGroup",
|
|
2338
|
+
props: {
|
|
2339
|
+
/**
|
|
2340
|
+
* Label text displayed above the slot content.
|
|
2341
|
+
*/
|
|
2342
|
+
label: {
|
|
2343
|
+
type: String,
|
|
2344
|
+
default: ""
|
|
2345
|
+
},
|
|
2346
|
+
/**
|
|
2347
|
+
* Error message displayed below the slot content in red.
|
|
2348
|
+
*/
|
|
2349
|
+
error: {
|
|
2350
|
+
type: String,
|
|
2351
|
+
default: ""
|
|
2352
|
+
},
|
|
2353
|
+
/**
|
|
2354
|
+
* Hint text displayed below the slot content in gray (hidden when error is shown).
|
|
2355
|
+
*/
|
|
2356
|
+
hint: {
|
|
2357
|
+
type: String,
|
|
2358
|
+
default: ""
|
|
2359
|
+
},
|
|
2360
|
+
/**
|
|
2361
|
+
* HTML `for` attribute to associate the label with a specific input element.
|
|
2362
|
+
* Improves accessibility by allowing Screenreaders to link label to input (WCAG 2.1 AA).
|
|
2363
|
+
*/
|
|
2364
|
+
for: {
|
|
2365
|
+
type: String,
|
|
2366
|
+
default: ""
|
|
2367
|
+
},
|
|
2368
|
+
/**
|
|
2369
|
+
* Whether a required indicator (*) is shown next to the label.
|
|
2370
|
+
*/
|
|
2371
|
+
required: {
|
|
2372
|
+
type: Boolean,
|
|
2373
|
+
default: !1
|
|
2374
|
+
}
|
|
2375
|
+
},
|
|
2376
|
+
setup(e) {
|
|
2377
|
+
return (r, t) => (n(), a("div", Ba, [
|
|
2378
|
+
e.label ? (n(), a("label", {
|
|
2379
|
+
key: 0,
|
|
2380
|
+
for: r.$props.for || void 0,
|
|
2381
|
+
class: "text-xs font-medium text-gray-500 uppercase tracking-wide"
|
|
2382
|
+
}, [
|
|
2383
|
+
M(y(e.label), 1),
|
|
2384
|
+
e.required ? (n(), a("span", Ia, "*")) : c("", !0)
|
|
2385
|
+
], 8, Ea)) : c("", !0),
|
|
2386
|
+
B(r.$slots, "default"),
|
|
2387
|
+
e.error ? (n(), a("p", za, [
|
|
2388
|
+
A(R(Ge), {
|
|
2389
|
+
size: 12,
|
|
2390
|
+
class: "shrink-0",
|
|
2391
|
+
"aria-hidden": "true"
|
|
2392
|
+
}),
|
|
2393
|
+
M(" " + y(e.error), 1)
|
|
2394
|
+
])) : c("", !0),
|
|
2395
|
+
e.hint && !e.error ? (n(), a("p", Ta, y(e.hint), 1)) : c("", !0)
|
|
2396
|
+
]));
|
|
2397
|
+
}
|
|
2398
|
+
}, ja = {
|
|
2399
|
+
key: 0,
|
|
2400
|
+
class: "flex items-center justify-center"
|
|
2401
|
+
}, Oa = {
|
|
2402
|
+
key: 1,
|
|
2403
|
+
class: "flex items-center"
|
|
2404
|
+
}, Da = {
|
|
2405
|
+
class: "flex-1 flex flex-col gap-2 pb-6",
|
|
2406
|
+
"aria-label": "Hauptnavigation"
|
|
2407
|
+
}, Va = {
|
|
2408
|
+
key: 0,
|
|
2409
|
+
class: "px-4 py-2 text-xs font-medium tracking-widest uppercase text-gray-400 select-none",
|
|
2410
|
+
"aria-hidden": "true"
|
|
2411
|
+
}, Pa = {
|
|
2412
|
+
key: 1,
|
|
2413
|
+
class: "h-4",
|
|
2414
|
+
"aria-hidden": "true"
|
|
2415
|
+
}, Ra = ["href", "title", "aria-current", "onClick"], Na = {
|
|
2416
|
+
key: 0,
|
|
2417
|
+
class: "truncate"
|
|
2418
|
+
}, Fa = ["aria-label", "title"], qa = {
|
|
2419
|
+
key: 0,
|
|
2420
|
+
class: "ml-2 text-sm"
|
|
2421
|
+
}, Ka = {
|
|
2422
|
+
__name: "LuSidebar",
|
|
2423
|
+
props: {
|
|
2424
|
+
/**
|
|
2425
|
+
* Navigation groups with labeled sections.
|
|
2426
|
+
* @type {NavGroup[]}
|
|
2427
|
+
*/
|
|
2428
|
+
items: {
|
|
2429
|
+
type: Array,
|
|
2430
|
+
default: () => []
|
|
2431
|
+
},
|
|
2432
|
+
/**
|
|
2433
|
+
* Controls sidebar visibility on tablet/mobile breakpoints.
|
|
2434
|
+
* @type {boolean}
|
|
2435
|
+
*/
|
|
2436
|
+
open: {
|
|
2437
|
+
type: Boolean,
|
|
2438
|
+
default: !1
|
|
2439
|
+
},
|
|
2440
|
+
/**
|
|
2441
|
+
* Controls sidebar collapsed state (icons-only vs full).
|
|
2442
|
+
* Only applies on desktop breakpoint.
|
|
2443
|
+
* @type {boolean}
|
|
2444
|
+
*/
|
|
2445
|
+
collapsed: {
|
|
2446
|
+
type: Boolean,
|
|
2447
|
+
default: !1
|
|
2448
|
+
},
|
|
2449
|
+
/**
|
|
2450
|
+
* Current user roles for RBAC-based nav item filtering.
|
|
2451
|
+
* Items with a `roles` array are only shown if at least one role matches.
|
|
2452
|
+
* Items without `roles` are always shown.
|
|
2453
|
+
* @type {string[]}
|
|
2454
|
+
*/
|
|
2455
|
+
currentUserRoles: {
|
|
2456
|
+
type: Array,
|
|
2457
|
+
default: () => []
|
|
2458
|
+
}
|
|
2459
|
+
},
|
|
2460
|
+
emits: ["update:open", "update:collapsed"],
|
|
2461
|
+
setup(e, { emit: r }) {
|
|
2462
|
+
const t = e, o = r, s = E(!1), i = E(!1), u = E(!1);
|
|
2463
|
+
function g() {
|
|
2464
|
+
const h = window.innerWidth;
|
|
2465
|
+
s.value = h < 768, i.value = h >= 768 && h < 1024;
|
|
2466
|
+
}
|
|
2467
|
+
ve(() => {
|
|
2468
|
+
g(), window.addEventListener("resize", g), document.addEventListener("keydown", k), u.value = !0;
|
|
2469
|
+
}), Me(() => {
|
|
2470
|
+
window.removeEventListener("resize", g), document.removeEventListener("keydown", k);
|
|
2471
|
+
});
|
|
2472
|
+
const d = b(() => !s.value && !i.value && t.collapsed), v = b(
|
|
2473
|
+
() => t.items.map((h) => ({
|
|
2474
|
+
...h,
|
|
2475
|
+
items: h.items.filter(
|
|
2476
|
+
(I) => {
|
|
2477
|
+
var F;
|
|
2478
|
+
return !((F = I.roles) != null && F.length) || I.roles.some((N) => t.currentUserRoles.includes(N));
|
|
2479
|
+
}
|
|
2480
|
+
)
|
|
2481
|
+
})).filter((h) => h.items.length > 0)
|
|
2482
|
+
), m = b(() => s.value && t.open), f = b(() => !s.value && !i.value ? !0 : t.open);
|
|
2483
|
+
function p() {
|
|
2484
|
+
o("update:open", !1);
|
|
2485
|
+
}
|
|
2486
|
+
function x() {
|
|
2487
|
+
o("update:collapsed", !t.collapsed);
|
|
2488
|
+
}
|
|
2489
|
+
function S(h) {
|
|
2490
|
+
h.key === "Escape" && p();
|
|
2491
|
+
}
|
|
2492
|
+
function k(h) {
|
|
2493
|
+
h.key === "Escape" && t.open && (s.value || i.value) && p();
|
|
2494
|
+
}
|
|
2495
|
+
return (h, I) => {
|
|
2496
|
+
const F = xe("router-link");
|
|
2497
|
+
return n(), a(z, null, [
|
|
2498
|
+
A(Z, { name: "lu-fade" }, {
|
|
2499
|
+
default: T(() => [
|
|
2500
|
+
m.value ? (n(), a("div", {
|
|
2501
|
+
key: 0,
|
|
2502
|
+
class: "fixed inset-0 bg-black/50 z-sidebar",
|
|
2503
|
+
"aria-hidden": "true",
|
|
2504
|
+
onClick: p,
|
|
2505
|
+
onKeydown: S
|
|
2506
|
+
}, null, 32)) : c("", !0)
|
|
2507
|
+
]),
|
|
2508
|
+
_: 1
|
|
2509
|
+
}),
|
|
2510
|
+
A(Z, {
|
|
2511
|
+
name: u.value ? "lu-slide" : void 0
|
|
2512
|
+
}, {
|
|
2513
|
+
default: T(() => [
|
|
2514
|
+
ee(l("aside", {
|
|
2515
|
+
class: w(["bg-navy-900 flex flex-col shrink-0 overflow-y-auto overflow-x-hidden transition-[width] duration-200 ease-out", [
|
|
2516
|
+
d.value ? "w-16" : "w-[240px]",
|
|
2517
|
+
s.value || i.value ? "fixed inset-y-0 left-0 z-sidebar w-[240px]" : "relative"
|
|
2518
|
+
]])
|
|
2519
|
+
}, [
|
|
2520
|
+
l("div", {
|
|
2521
|
+
class: w(["shrink-0", d.value ? "p-3 flex justify-center" : "p-6"])
|
|
2522
|
+
}, [
|
|
2523
|
+
B(h.$slots, "logo", {}, () => [
|
|
2524
|
+
d.value ? (n(), a("div", ja, [...I[0] || (I[0] = [
|
|
2525
|
+
l("span", { class: "text-teal-500 font-bold text-xl" }, ".h", -1)
|
|
2526
|
+
])])) : (n(), a("div", Oa, [...I[1] || (I[1] = [
|
|
2527
|
+
l("span", { class: "text-white font-bold text-xl tracking-tight" }, "lumen", -1),
|
|
2528
|
+
l("span", { class: "text-teal-500 font-bold text-xl" }, ".hr", -1)
|
|
2529
|
+
])]))
|
|
2530
|
+
], !0)
|
|
2531
|
+
], 2),
|
|
2532
|
+
l("nav", Da, [
|
|
2533
|
+
(n(!0), a(z, null, j(v.value, (N) => (n(), a("div", {
|
|
2534
|
+
key: N.label
|
|
2535
|
+
}, [
|
|
2536
|
+
N.label && !d.value ? (n(), a("div", Va, y(N.label), 1)) : N.label && d.value ? (n(), a("div", Pa)) : c("", !0),
|
|
2537
|
+
(n(!0), a(z, null, j(N.items, ($) => (n(), P(F, {
|
|
2538
|
+
key: $.to,
|
|
2539
|
+
to: $.to,
|
|
2540
|
+
custom: ""
|
|
2541
|
+
}, {
|
|
2542
|
+
default: T(({ navigate: L, isExactActive: C, href: _ }) => [
|
|
2543
|
+
l("a", {
|
|
2544
|
+
href: _,
|
|
2545
|
+
title: d.value ? $.label : void 0,
|
|
2546
|
+
class: w([
|
|
2547
|
+
"flex items-center h-10 text-sm transition-colors duration-150",
|
|
2548
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-teal-500 focus-visible:ring-offset-2 focus-visible:ring-offset-navy-900",
|
|
2549
|
+
d.value ? "justify-center mx-2 rounded-input" : "gap-3 px-4 mx-2 rounded-input border-l-[3px] pl-[13px]",
|
|
2550
|
+
C ? d.value ? "text-teal-500 bg-navy-800" : "text-teal-500 bg-navy-800 border-teal-500" : d.value ? "text-gray-400 hover:bg-navy-800 hover:text-white" : "text-gray-400 hover:bg-navy-800 hover:text-white border-transparent"
|
|
2551
|
+
]),
|
|
2552
|
+
"aria-current": C ? "page" : void 0,
|
|
2553
|
+
onClick: L
|
|
2554
|
+
}, [
|
|
2555
|
+
A(O, {
|
|
2556
|
+
name: $.icon,
|
|
2557
|
+
size: 20,
|
|
2558
|
+
class: "shrink-0",
|
|
2559
|
+
"aria-hidden": "true"
|
|
2560
|
+
}, null, 8, ["name"]),
|
|
2561
|
+
d.value ? c("", !0) : (n(), a("span", Na, y($.label), 1))
|
|
2562
|
+
], 10, Ra)
|
|
2563
|
+
]),
|
|
2564
|
+
_: 2
|
|
2565
|
+
}, 1032, ["to"]))), 128))
|
|
2566
|
+
]))), 128))
|
|
2567
|
+
]),
|
|
2568
|
+
h.$slots.bottom ? (n(), a("div", {
|
|
2569
|
+
key: 0,
|
|
2570
|
+
class: w(["shrink-0 border-t border-navy-800", d.value ? "p-2" : "p-4"])
|
|
2571
|
+
}, [
|
|
2572
|
+
B(h.$slots, "bottom", {}, void 0, !0)
|
|
2573
|
+
], 2)) : c("", !0),
|
|
2574
|
+
!s.value && !i.value ? (n(), a("div", {
|
|
2575
|
+
key: 1,
|
|
2576
|
+
class: w(["shrink-0 border-t border-navy-800", d.value ? "p-2" : "p-3"])
|
|
2577
|
+
}, [
|
|
2578
|
+
l("button", {
|
|
2579
|
+
type: "button",
|
|
2580
|
+
class: "flex items-center justify-center w-full h-9 rounded-input text-gray-400 hover:bg-navy-800 hover:text-white transition-colors duration-150 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-teal-500 focus-visible:ring-offset-2 focus-visible:ring-offset-navy-900",
|
|
2581
|
+
"aria-label": d.value ? "Sidebar erweitern" : "Sidebar einklappen",
|
|
2582
|
+
title: d.value ? "Sidebar erweitern" : "Sidebar einklappen",
|
|
2583
|
+
onClick: x
|
|
2584
|
+
}, [
|
|
2585
|
+
A(O, {
|
|
2586
|
+
name: d.value ? "ChevronsRight" : "ChevronsLeft",
|
|
2587
|
+
size: 18,
|
|
2588
|
+
"aria-hidden": "true"
|
|
2589
|
+
}, null, 8, ["name"]),
|
|
2590
|
+
d.value ? c("", !0) : (n(), a("span", qa, y("Einklappen")))
|
|
2591
|
+
], 8, Fa)
|
|
2592
|
+
], 2)) : c("", !0)
|
|
2593
|
+
], 2), [
|
|
2594
|
+
[je, f.value]
|
|
2595
|
+
])
|
|
2596
|
+
]),
|
|
2597
|
+
_: 3
|
|
2598
|
+
}, 8, ["name"])
|
|
2599
|
+
], 64);
|
|
2600
|
+
};
|
|
2601
|
+
}
|
|
2602
|
+
}, $e = /* @__PURE__ */ W(Ka, [["__scopeId", "data-v-9c5163f7"]]), Ua = { class: "h-16 bg-white border-b border-lu-border flex items-center justify-between px-4 shrink-0 z-header" }, Ha = { class: "flex items-center gap-3" }, Za = { class: "flex items-center gap-2" }, Wa = ["aria-label"], Ga = {
|
|
2603
|
+
class: "absolute -top-0.5 -right-0.5 flex items-center justify-center min-w-[18px] h-[18px] px-1 text-[11px] font-medium text-white bg-amber-500 rounded-full leading-none",
|
|
2604
|
+
"aria-hidden": "true"
|
|
2605
|
+
}, Xa = ["aria-label"], Ja = {
|
|
2606
|
+
key: 0,
|
|
2607
|
+
class: "absolute -top-0.5 -right-0.5 flex items-center justify-center min-w-[18px] h-[18px] px-1 text-[11px] font-medium text-white bg-red-500 rounded-full leading-none",
|
|
2608
|
+
"aria-hidden": "true"
|
|
2609
|
+
}, Ya = ["aria-label", "aria-expanded"], Qa = { class: "hidden sm:block text-sm font-medium text-gray-700 max-w-[150px] truncate" }, er = {
|
|
2610
|
+
key: 0,
|
|
2611
|
+
class: "absolute right-0 top-full mt-1 w-64 bg-white rounded-card border border-lu-border shadow-card z-dropdown origin-top-right",
|
|
2612
|
+
role: "menu",
|
|
2613
|
+
"aria-orientation": "vertical"
|
|
2614
|
+
}, tr = { class: "px-4 py-3 border-b border-lu-border" }, nr = { class: "flex items-center gap-3" }, ar = { class: "min-w-0" }, rr = { class: "text-sm font-semibold text-gray-900 truncate" }, sr = {
|
|
2615
|
+
key: 0,
|
|
2616
|
+
class: "text-xs text-gray-500 truncate"
|
|
2617
|
+
}, lr = {
|
|
2618
|
+
key: 0,
|
|
2619
|
+
class: "py-1"
|
|
2620
|
+
}, or = ["onClick"], Se = {
|
|
2621
|
+
__name: "LuHeader",
|
|
2622
|
+
props: {
|
|
2623
|
+
/**
|
|
2624
|
+
* Current user information for avatar, name, and role display.
|
|
2625
|
+
* @type {HeaderUser}
|
|
2626
|
+
*/
|
|
2627
|
+
user: {
|
|
2628
|
+
type: Object,
|
|
2629
|
+
default: () => ({ name: "Benutzer" })
|
|
2630
|
+
},
|
|
2631
|
+
/**
|
|
2632
|
+
* Number of unread notifications. Displays badge when > 0.
|
|
2633
|
+
* @type {number}
|
|
2634
|
+
*/
|
|
2635
|
+
notificationCount: {
|
|
2636
|
+
type: Number,
|
|
2637
|
+
default: 0
|
|
2638
|
+
},
|
|
2639
|
+
/**
|
|
2640
|
+
* Number of pending booking corrections. Displays badge when > 0 (TEAMLEITUNG/HR only).
|
|
2641
|
+
* @type {number}
|
|
2642
|
+
*/
|
|
2643
|
+
pendingCorrectionsCount: {
|
|
2644
|
+
type: Number,
|
|
2645
|
+
default: 0
|
|
2646
|
+
},
|
|
2647
|
+
/**
|
|
2648
|
+
* Items to display in the user dropdown menu.
|
|
2649
|
+
* Each item has a label, optional icon, and an action string emitted on click.
|
|
2650
|
+
* @type {UserMenuItem[]}
|
|
2651
|
+
*/
|
|
2652
|
+
userMenuItems: {
|
|
2653
|
+
type: Array,
|
|
2654
|
+
default: () => []
|
|
2655
|
+
}
|
|
2656
|
+
},
|
|
2657
|
+
emits: [
|
|
2658
|
+
"toggle-sidebar",
|
|
2659
|
+
"notifications-click",
|
|
2660
|
+
"corrections-click",
|
|
2661
|
+
"user-menu-action"
|
|
2662
|
+
],
|
|
2663
|
+
setup(e, { emit: r }) {
|
|
2664
|
+
const t = e, o = r, s = E(!1), i = E(null);
|
|
2665
|
+
ne(i, () => {
|
|
2666
|
+
s.value = !1;
|
|
2667
|
+
});
|
|
2668
|
+
function u() {
|
|
2669
|
+
s.value = !s.value;
|
|
2670
|
+
}
|
|
2671
|
+
function g(f) {
|
|
2672
|
+
s.value = !1, o("user-menu-action", f);
|
|
2673
|
+
}
|
|
2674
|
+
function d(f) {
|
|
2675
|
+
f.key === "Escape" && (s.value = !1);
|
|
2676
|
+
}
|
|
2677
|
+
const v = b(() => t.notificationCount <= 0 ? "" : t.notificationCount > 99 ? "99+" : String(t.notificationCount)), m = b(() => t.notificationCount <= 0 ? "Benachrichtigungen" : `${t.notificationCount} ungelesene Benachrichtigungen`);
|
|
2678
|
+
return (f, p) => (n(), a("header", Ua, [
|
|
2679
|
+
l("div", Ha, [
|
|
2680
|
+
l("button", {
|
|
2681
|
+
type: "button",
|
|
2682
|
+
class: "lg:hidden inline-flex items-center justify-center w-10 h-10 rounded-input text-gray-500 hover:bg-gray-100 hover:text-gray-700 transition-colors duration-150 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-teal-500 focus-visible:ring-offset-2",
|
|
2683
|
+
"aria-label": "Navigation ein-/ausblenden",
|
|
2684
|
+
onClick: p[0] || (p[0] = (x) => o("toggle-sidebar"))
|
|
2685
|
+
}, [
|
|
2686
|
+
A(O, {
|
|
2687
|
+
name: "Menu",
|
|
2688
|
+
size: 20,
|
|
2689
|
+
"aria-hidden": "true"
|
|
2690
|
+
})
|
|
2691
|
+
]),
|
|
2692
|
+
B(f.$slots, "breadcrumb")
|
|
2693
|
+
]),
|
|
2694
|
+
l("div", Za, [
|
|
2695
|
+
e.pendingCorrectionsCount > 0 ? (n(), a("button", {
|
|
2696
|
+
key: 0,
|
|
2697
|
+
type: "button",
|
|
2698
|
+
class: "relative inline-flex items-center justify-center w-10 h-10 rounded-input text-gray-500 hover:bg-gray-100 hover:text-gray-700 transition-colors duration-150 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-teal-500 focus-visible:ring-offset-2",
|
|
2699
|
+
"aria-label": `${e.pendingCorrectionsCount} ausstehende Korrekturantraege`,
|
|
2700
|
+
onClick: p[1] || (p[1] = (x) => o("corrections-click"))
|
|
2701
|
+
}, [
|
|
2702
|
+
A(O, {
|
|
2703
|
+
name: "FilePen",
|
|
2704
|
+
size: 20,
|
|
2705
|
+
"aria-hidden": "true"
|
|
2706
|
+
}),
|
|
2707
|
+
l("span", Ga, y(e.pendingCorrectionsCount > 99 ? "99+" : e.pendingCorrectionsCount), 1)
|
|
2708
|
+
], 8, Wa)) : c("", !0),
|
|
2709
|
+
l("button", {
|
|
2710
|
+
type: "button",
|
|
2711
|
+
class: "relative inline-flex items-center justify-center w-10 h-10 rounded-input text-gray-500 hover:bg-gray-100 hover:text-gray-700 transition-colors duration-150 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-teal-500 focus-visible:ring-offset-2",
|
|
2712
|
+
"aria-label": m.value,
|
|
2713
|
+
onClick: p[2] || (p[2] = (x) => o("notifications-click"))
|
|
2714
|
+
}, [
|
|
2715
|
+
A(O, {
|
|
2716
|
+
name: "Bell",
|
|
2717
|
+
size: 20,
|
|
2718
|
+
"aria-hidden": "true"
|
|
2719
|
+
}),
|
|
2720
|
+
e.notificationCount > 0 ? (n(), a("span", Ja, y(v.value), 1)) : c("", !0)
|
|
2721
|
+
], 8, Xa),
|
|
2722
|
+
l("div", {
|
|
2723
|
+
ref_key: "userMenuRef",
|
|
2724
|
+
ref: i,
|
|
2725
|
+
class: "relative",
|
|
2726
|
+
onKeydown: d
|
|
2727
|
+
}, [
|
|
2728
|
+
l("button", {
|
|
2729
|
+
type: "button",
|
|
2730
|
+
class: "flex items-center gap-2 px-2 py-1 rounded-input hover:bg-gray-100 transition-colors duration-150 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-teal-500 focus-visible:ring-offset-2",
|
|
2731
|
+
"aria-label": `Benutzermenue fuer ${e.user.name}`,
|
|
2732
|
+
"aria-expanded": s.value,
|
|
2733
|
+
"aria-haspopup": "true",
|
|
2734
|
+
onClick: u
|
|
2735
|
+
}, [
|
|
2736
|
+
A(oe, {
|
|
2737
|
+
name: e.user.name,
|
|
2738
|
+
src: e.user.avatarSrc,
|
|
2739
|
+
size: "sm"
|
|
2740
|
+
}, null, 8, ["name", "src"]),
|
|
2741
|
+
l("span", Qa, y(e.user.name), 1),
|
|
2742
|
+
A(O, {
|
|
2743
|
+
name: "ChevronDown",
|
|
2744
|
+
size: 16,
|
|
2745
|
+
class: w(["hidden sm:block text-gray-400 transition-transform duration-150", { "rotate-180": s.value }]),
|
|
2746
|
+
"aria-hidden": "true"
|
|
2747
|
+
}, null, 8, ["class"])
|
|
2748
|
+
], 8, Ya),
|
|
2749
|
+
A(Z, {
|
|
2750
|
+
"enter-active-class": "transition ease-out duration-150",
|
|
2751
|
+
"enter-from-class": "opacity-0 scale-95 translate-y-1",
|
|
2752
|
+
"enter-to-class": "opacity-100 scale-100 translate-y-0",
|
|
2753
|
+
"leave-active-class": "transition ease-in duration-100",
|
|
2754
|
+
"leave-from-class": "opacity-100 scale-100 translate-y-0",
|
|
2755
|
+
"leave-to-class": "opacity-0 scale-95 translate-y-1"
|
|
2756
|
+
}, {
|
|
2757
|
+
default: T(() => [
|
|
2758
|
+
s.value ? (n(), a("div", er, [
|
|
2759
|
+
l("div", tr, [
|
|
2760
|
+
l("div", nr, [
|
|
2761
|
+
A(oe, {
|
|
2762
|
+
name: e.user.name,
|
|
2763
|
+
src: e.user.avatarSrc,
|
|
2764
|
+
size: "md"
|
|
2765
|
+
}, null, 8, ["name", "src"]),
|
|
2766
|
+
l("div", ar, [
|
|
2767
|
+
l("p", rr, y(e.user.name), 1),
|
|
2768
|
+
e.user.roleLabel || e.user.role ? (n(), a("p", sr, y(e.user.roleLabel || e.user.role), 1)) : c("", !0)
|
|
2769
|
+
])
|
|
2770
|
+
])
|
|
2771
|
+
]),
|
|
2772
|
+
e.userMenuItems.length > 0 ? (n(), a("div", lr, [
|
|
2773
|
+
(n(!0), a(z, null, j(e.userMenuItems, (x) => (n(), a("button", {
|
|
2774
|
+
key: x.action,
|
|
2775
|
+
type: "button",
|
|
2776
|
+
class: "flex items-center gap-3 w-full px-4 py-2 text-sm text-gray-700 hover:bg-gray-50 hover:text-gray-900 transition-colors duration-150 focus-visible:outline-none focus-visible:bg-gray-50",
|
|
2777
|
+
role: "menuitem",
|
|
2778
|
+
onClick: (S) => g(x.action)
|
|
2779
|
+
}, [
|
|
2780
|
+
x.icon ? (n(), P(O, {
|
|
2781
|
+
key: 0,
|
|
2782
|
+
name: x.icon,
|
|
2783
|
+
size: 16,
|
|
2784
|
+
class: "text-gray-400 shrink-0",
|
|
2785
|
+
"aria-hidden": "true"
|
|
2786
|
+
}, null, 8, ["name"])) : c("", !0),
|
|
2787
|
+
l("span", null, y(x.label), 1)
|
|
2788
|
+
], 8, or))), 128))
|
|
2789
|
+
])) : c("", !0)
|
|
2790
|
+
])) : c("", !0)
|
|
2791
|
+
]),
|
|
2792
|
+
_: 1
|
|
2793
|
+
})
|
|
2794
|
+
], 544)
|
|
2795
|
+
])
|
|
2796
|
+
]));
|
|
2797
|
+
}
|
|
2798
|
+
}, ir = { class: "flex h-screen overflow-hidden bg-lu-bg" }, ur = { class: "flex flex-col flex-1 overflow-hidden min-w-0" }, dr = { class: "flex-1 overflow-auto bg-lu-bg p-6" }, cr = { class: "max-w-[1440px] mx-auto" }, fr = {
|
|
2799
|
+
__name: "LuAppLayout",
|
|
2800
|
+
props: {
|
|
2801
|
+
/**
|
|
2802
|
+
* Navigation groups passed to LuSidebar.
|
|
2803
|
+
* @type {NavGroup[]}
|
|
2804
|
+
*/
|
|
2805
|
+
navItems: {
|
|
2806
|
+
type: Array,
|
|
2807
|
+
default: () => []
|
|
2808
|
+
},
|
|
2809
|
+
/**
|
|
2810
|
+
* Current user information passed to LuHeader.
|
|
2811
|
+
* @type {{ name: string, role?: string, roleLabel?: string, avatarSrc?: string }}
|
|
2812
|
+
*/
|
|
2813
|
+
user: {
|
|
2814
|
+
type: Object,
|
|
2815
|
+
default: () => ({ name: "Benutzer" })
|
|
2816
|
+
},
|
|
2817
|
+
/**
|
|
2818
|
+
* Notification count passed to LuHeader.
|
|
2819
|
+
* @type {number}
|
|
2820
|
+
*/
|
|
2821
|
+
notificationCount: {
|
|
2822
|
+
type: Number,
|
|
2823
|
+
default: 0
|
|
2824
|
+
},
|
|
2825
|
+
/**
|
|
2826
|
+
* Current user roles for RBAC-based nav filtering, passed to LuSidebar.
|
|
2827
|
+
* @type {string[]}
|
|
2828
|
+
*/
|
|
2829
|
+
currentUserRoles: {
|
|
2830
|
+
type: Array,
|
|
2831
|
+
default: () => []
|
|
2832
|
+
},
|
|
2833
|
+
/**
|
|
2834
|
+
* Whether the sidebar is collapsed (icons-only mode).
|
|
2835
|
+
* @type {boolean}
|
|
2836
|
+
*/
|
|
2837
|
+
sidebarCollapsed: {
|
|
2838
|
+
type: Boolean,
|
|
2839
|
+
default: !1
|
|
2840
|
+
},
|
|
2841
|
+
/**
|
|
2842
|
+
* User menu items passed to LuHeader.
|
|
2843
|
+
* @type {Array<{ label: string, icon?: string, action: string }>}
|
|
2844
|
+
*/
|
|
2845
|
+
userMenuItems: {
|
|
2846
|
+
type: Array,
|
|
2847
|
+
default: () => []
|
|
2848
|
+
}
|
|
2849
|
+
},
|
|
2850
|
+
emits: ["notifications-click", "user-menu-action", "update:sidebarCollapsed"],
|
|
2851
|
+
setup(e, { emit: r }) {
|
|
2852
|
+
const t = r, o = E(!1);
|
|
2853
|
+
return (s, i) => (n(), a("div", ir, [
|
|
2854
|
+
A($e, {
|
|
2855
|
+
items: e.navItems,
|
|
2856
|
+
"current-user-roles": e.currentUserRoles,
|
|
2857
|
+
collapsed: e.sidebarCollapsed,
|
|
2858
|
+
open: o.value,
|
|
2859
|
+
"onUpdate:open": i[0] || (i[0] = (u) => o.value = u),
|
|
2860
|
+
"onUpdate:collapsed": i[1] || (i[1] = (u) => t("update:sidebarCollapsed", u))
|
|
2861
|
+
}, Oe({ _: 2 }, [
|
|
2862
|
+
s.$slots["sidebar-logo"] ? {
|
|
2863
|
+
name: "logo",
|
|
2864
|
+
fn: T(() => [
|
|
2865
|
+
B(s.$slots, "sidebar-logo")
|
|
2866
|
+
]),
|
|
2867
|
+
key: "0"
|
|
2868
|
+
} : void 0,
|
|
2869
|
+
s.$slots["sidebar-bottom"] ? {
|
|
2870
|
+
name: "bottom",
|
|
2871
|
+
fn: T(() => [
|
|
2872
|
+
B(s.$slots, "sidebar-bottom")
|
|
2873
|
+
]),
|
|
2874
|
+
key: "1"
|
|
2875
|
+
} : void 0
|
|
2876
|
+
]), 1032, ["items", "current-user-roles", "collapsed", "open"]),
|
|
2877
|
+
l("div", ur, [
|
|
2878
|
+
A(Se, {
|
|
2879
|
+
user: e.user,
|
|
2880
|
+
"notification-count": e.notificationCount,
|
|
2881
|
+
"user-menu-items": e.userMenuItems,
|
|
2882
|
+
onToggleSidebar: i[2] || (i[2] = (u) => o.value = !o.value),
|
|
2883
|
+
onNotificationsClick: i[3] || (i[3] = (u) => t("notifications-click")),
|
|
2884
|
+
onUserMenuAction: i[4] || (i[4] = (u) => t("user-menu-action", u))
|
|
2885
|
+
}, {
|
|
2886
|
+
breadcrumb: T(() => [
|
|
2887
|
+
B(s.$slots, "breadcrumb")
|
|
2888
|
+
]),
|
|
2889
|
+
_: 3
|
|
2890
|
+
}, 8, ["user", "notification-count", "user-menu-items"]),
|
|
2891
|
+
l("main", dr, [
|
|
2892
|
+
l("div", cr, [
|
|
2893
|
+
B(s.$slots, "default")
|
|
2894
|
+
])
|
|
2895
|
+
])
|
|
2896
|
+
])
|
|
2897
|
+
]));
|
|
2898
|
+
}
|
|
2899
|
+
}, br = {
|
|
2900
|
+
"aria-label": "Breadcrumb",
|
|
2901
|
+
class: "flex items-center text-sm"
|
|
2902
|
+
}, gr = { class: "flex items-center gap-1" }, yr = {
|
|
2903
|
+
key: 0,
|
|
2904
|
+
class: "text-gray-300 select-none",
|
|
2905
|
+
"aria-hidden": "true"
|
|
2906
|
+
}, vr = {
|
|
2907
|
+
key: 1,
|
|
2908
|
+
class: "text-gray-900 font-medium",
|
|
2909
|
+
"aria-current": "page"
|
|
2910
|
+
}, mr = {
|
|
2911
|
+
key: 3,
|
|
2912
|
+
class: "text-gray-500"
|
|
2913
|
+
}, pr = {
|
|
2914
|
+
__name: "LuBreadcrumb",
|
|
2915
|
+
props: {
|
|
2916
|
+
/**
|
|
2917
|
+
* Breadcrumb items to display. If provided, takes precedence over route.meta.breadcrumb.
|
|
2918
|
+
* @type {BreadcrumbItem[]}
|
|
2919
|
+
*/
|
|
2920
|
+
items: {
|
|
2921
|
+
type: Array,
|
|
2922
|
+
default: void 0
|
|
2923
|
+
}
|
|
2924
|
+
},
|
|
2925
|
+
setup(e) {
|
|
2926
|
+
const r = e, t = Qe(), o = b(() => {
|
|
2927
|
+
var i;
|
|
2928
|
+
if (Array.isArray(r.items)) return r.items;
|
|
2929
|
+
const s = (i = t.meta) == null ? void 0 : i.breadcrumb;
|
|
2930
|
+
return Array.isArray(s) ? s : [];
|
|
2931
|
+
});
|
|
2932
|
+
return (s, i) => {
|
|
2933
|
+
const u = xe("router-link");
|
|
2934
|
+
return n(), a("nav", br, [
|
|
2935
|
+
l("ol", gr, [
|
|
2936
|
+
(n(!0), a(z, null, j(o.value, (g, d) => (n(), a("li", {
|
|
2937
|
+
key: d,
|
|
2938
|
+
class: "flex items-center gap-1"
|
|
2939
|
+
}, [
|
|
2940
|
+
d > 0 ? (n(), a("span", yr, "/")) : c("", !0),
|
|
2941
|
+
d === o.value.length - 1 ? (n(), a("span", vr, y(g.label), 1)) : g.to ? (n(), P(u, {
|
|
2942
|
+
key: 2,
|
|
2943
|
+
to: g.to,
|
|
2944
|
+
class: "text-gray-500 transition-colors duration-150 hover:text-teal-500 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-teal-500 focus-visible:ring-offset-2 rounded-sm"
|
|
2945
|
+
}, {
|
|
2946
|
+
default: T(() => [
|
|
2947
|
+
M(y(g.label), 1)
|
|
2948
|
+
]),
|
|
2949
|
+
_: 2
|
|
2950
|
+
}, 1032, ["to"])) : (n(), a("span", mr, y(g.label), 1))
|
|
2951
|
+
]))), 128))
|
|
2952
|
+
])
|
|
2953
|
+
]);
|
|
2954
|
+
};
|
|
2955
|
+
}
|
|
2956
|
+
}, hr = {
|
|
2957
|
+
key: 0,
|
|
2958
|
+
class: "fixed inset-0 z-modal-backdrop overflow-y-auto"
|
|
2959
|
+
}, xr = ["aria-labelledby"], wr = { class: "flex items-center justify-between px-6 py-4 border-b border-lu-border shrink-0" }, kr = ["id"], $r = { class: "flex-1 overflow-y-auto px-6 py-4" }, Sr = {
|
|
2960
|
+
key: 0,
|
|
2961
|
+
class: "shrink-0 px-6 py-4 border-t border-lu-border flex items-center justify-end gap-3"
|
|
2962
|
+
}, Cr = /* @__PURE__ */ Object.assign({ name: "LuModal" }, {
|
|
2963
|
+
__name: "LuModal",
|
|
2964
|
+
props: {
|
|
2965
|
+
/** Steuert die Sichtbarkeit des Modals (v-model) */
|
|
2966
|
+
modelValue: {
|
|
2967
|
+
type: Boolean,
|
|
2968
|
+
required: !0
|
|
2969
|
+
},
|
|
2970
|
+
/** Titel im Modal-Header */
|
|
2971
|
+
title: {
|
|
2972
|
+
type: String,
|
|
2973
|
+
default: ""
|
|
2974
|
+
},
|
|
2975
|
+
/** Breite des Dialogs (sm: 400px, md: 560px, lg: 768px, xl: 1024px) */
|
|
2976
|
+
size: {
|
|
2977
|
+
type: String,
|
|
2978
|
+
default: "md",
|
|
2979
|
+
validator: (e) => ["sm", "md", "lg", "xl"].includes(e)
|
|
2980
|
+
},
|
|
2981
|
+
/** Verhindert Schliessen durch Backdrop-Klick */
|
|
2982
|
+
persistent: {
|
|
2983
|
+
type: Boolean,
|
|
2984
|
+
default: !1
|
|
2985
|
+
}
|
|
2986
|
+
},
|
|
2987
|
+
emits: ["update:modelValue"],
|
|
2988
|
+
setup(e, { emit: r }) {
|
|
2989
|
+
const t = e, o = r, s = E(null), i = E(""), u = q(), g = {
|
|
2990
|
+
sm: "md:max-w-[400px]",
|
|
2991
|
+
md: "md:max-w-[560px]",
|
|
2992
|
+
lg: "md:max-w-[768px]",
|
|
2993
|
+
xl: "md:max-w-[1024px]"
|
|
2994
|
+
}, d = b(() => g[t.size]);
|
|
2995
|
+
function v() {
|
|
2996
|
+
o("update:modelValue", !1);
|
|
2997
|
+
}
|
|
2998
|
+
function m() {
|
|
2999
|
+
t.persistent || v();
|
|
3000
|
+
}
|
|
3001
|
+
const f = [
|
|
3002
|
+
"a[href]",
|
|
3003
|
+
"button:not([disabled])",
|
|
3004
|
+
"textarea:not([disabled])",
|
|
3005
|
+
"input:not([disabled])",
|
|
3006
|
+
"select:not([disabled])",
|
|
3007
|
+
'[tabindex]:not([tabindex="-1"])'
|
|
3008
|
+
].join(", ");
|
|
3009
|
+
function p(S) {
|
|
3010
|
+
if (S.key !== "Tab" || !s.value) return;
|
|
3011
|
+
const k = s.value.querySelectorAll(f);
|
|
3012
|
+
if (k.length === 0) return;
|
|
3013
|
+
const h = (
|
|
3014
|
+
/** @type {HTMLElement} */
|
|
3015
|
+
k[0]
|
|
3016
|
+
), I = (
|
|
3017
|
+
/** @type {HTMLElement} */
|
|
3018
|
+
k[k.length - 1]
|
|
3019
|
+
);
|
|
3020
|
+
S.shiftKey ? (document.activeElement === h || document.activeElement === s.value) && (S.preventDefault(), I.focus()) : document.activeElement === I && (S.preventDefault(), h.focus());
|
|
3021
|
+
}
|
|
3022
|
+
function x(S) {
|
|
3023
|
+
if (S.key === "Escape" && t.modelValue && !t.persistent) {
|
|
3024
|
+
S.preventDefault(), v();
|
|
3025
|
+
return;
|
|
3026
|
+
}
|
|
3027
|
+
p(S);
|
|
3028
|
+
}
|
|
3029
|
+
return ie(
|
|
3030
|
+
() => t.modelValue,
|
|
3031
|
+
(S) => {
|
|
3032
|
+
S ? (i.value = document.body.style.overflow, document.body.style.overflow = "hidden", document.addEventListener("keydown", x), pe(() => {
|
|
3033
|
+
var k;
|
|
3034
|
+
(k = s.value) == null || k.focus();
|
|
3035
|
+
})) : (document.body.style.overflow = i.value, document.removeEventListener("keydown", x));
|
|
3036
|
+
},
|
|
3037
|
+
{ immediate: !0 }
|
|
3038
|
+
), me(() => {
|
|
3039
|
+
document.body.style.overflow = i.value, document.removeEventListener("keydown", x);
|
|
3040
|
+
}), (S, k) => (n(), P(ye, { to: "body" }, [
|
|
3041
|
+
A(Z, { name: "lu-modal" }, {
|
|
3042
|
+
default: T(() => [
|
|
3043
|
+
e.modelValue ? (n(), a("div", hr, [
|
|
3044
|
+
k[0] || (k[0] = l("div", {
|
|
3045
|
+
class: "lu-modal-backdrop fixed inset-0 bg-black/50 pointer-events-none",
|
|
3046
|
+
"aria-hidden": "true"
|
|
3047
|
+
}, null, -1)),
|
|
3048
|
+
l("div", {
|
|
3049
|
+
class: "flex min-h-full items-end justify-center md:items-center md:p-6",
|
|
3050
|
+
onClick: U(m, ["self"])
|
|
3051
|
+
}, [
|
|
3052
|
+
l("div", {
|
|
3053
|
+
ref_key: "dialogRef",
|
|
3054
|
+
ref: s,
|
|
3055
|
+
role: "dialog",
|
|
3056
|
+
"aria-modal": "true",
|
|
3057
|
+
"aria-labelledby": e.title ? R(u) : void 0,
|
|
3058
|
+
tabindex: "-1",
|
|
3059
|
+
class: w([
|
|
3060
|
+
"lu-modal-dialog relative z-modal flex flex-col bg-lu-surface shadow-xl w-full outline-none",
|
|
3061
|
+
"rounded-t-card md:rounded-card",
|
|
3062
|
+
d.value,
|
|
3063
|
+
"max-h-[90vh]"
|
|
3064
|
+
])
|
|
3065
|
+
}, [
|
|
3066
|
+
l("div", wr, [
|
|
3067
|
+
e.title ? (n(), a("h2", {
|
|
3068
|
+
key: 0,
|
|
3069
|
+
id: R(u),
|
|
3070
|
+
class: "text-lg font-semibold text-gray-900 leading-6"
|
|
3071
|
+
}, y(e.title), 9, kr)) : c("", !0),
|
|
3072
|
+
l("button", {
|
|
3073
|
+
type: "button",
|
|
3074
|
+
class: "ml-auto -mr-1 flex items-center justify-center w-8 h-8 rounded-input text-gray-400 hover:text-gray-600 hover:bg-gray-100 transition-colors duration-150 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-teal-500 focus-visible:ring-offset-2",
|
|
3075
|
+
"aria-label": "Schliessen",
|
|
3076
|
+
onClick: v
|
|
3077
|
+
}, [
|
|
3078
|
+
A(R(Xe), {
|
|
3079
|
+
size: 20,
|
|
3080
|
+
"aria-hidden": "true"
|
|
3081
|
+
})
|
|
3082
|
+
])
|
|
3083
|
+
]),
|
|
3084
|
+
l("div", $r, [
|
|
3085
|
+
B(S.$slots, "default", {}, void 0, !0)
|
|
3086
|
+
]),
|
|
3087
|
+
S.$slots.footer ? (n(), a("div", Sr, [
|
|
3088
|
+
B(S.$slots, "footer", {}, void 0, !0)
|
|
3089
|
+
])) : c("", !0)
|
|
3090
|
+
], 10, xr)
|
|
3091
|
+
])
|
|
3092
|
+
])) : c("", !0)
|
|
3093
|
+
]),
|
|
3094
|
+
_: 3
|
|
3095
|
+
})
|
|
3096
|
+
]));
|
|
3097
|
+
}
|
|
3098
|
+
}), Lr = /* @__PURE__ */ W(Cr, [["__scopeId", "data-v-cb36b591"]]), Ar = ["aria-label"], _r = {
|
|
3099
|
+
class: "text-xs font-medium text-gray-500 uppercase tracking-wide truncate",
|
|
3100
|
+
"aria-hidden": "true"
|
|
3101
|
+
}, Br = {
|
|
3102
|
+
key: 0,
|
|
3103
|
+
class: "mt-2 flex items-center gap-2"
|
|
3104
|
+
}, Er = { class: "sr-only" }, Ir = {
|
|
3105
|
+
key: 1,
|
|
3106
|
+
class: "text-xs text-gray-400"
|
|
3107
|
+
}, zr = {
|
|
3108
|
+
__name: "LuKpiCard",
|
|
3109
|
+
props: {
|
|
3110
|
+
/**
|
|
3111
|
+
* Label text displayed above the value.
|
|
3112
|
+
* @type {string}
|
|
3113
|
+
*/
|
|
3114
|
+
label: {
|
|
3115
|
+
type: String,
|
|
3116
|
+
required: !0
|
|
3117
|
+
},
|
|
3118
|
+
/**
|
|
3119
|
+
* The KPI value to display prominently.
|
|
3120
|
+
* @type {string | number}
|
|
3121
|
+
*/
|
|
3122
|
+
value: {
|
|
3123
|
+
type: [String, Number],
|
|
3124
|
+
required: !0
|
|
3125
|
+
},
|
|
3126
|
+
/**
|
|
3127
|
+
* Status determines the value text color.
|
|
3128
|
+
* @type {'success' | 'warning' | 'error' | 'default'}
|
|
3129
|
+
*/
|
|
3130
|
+
status: {
|
|
3131
|
+
type: String,
|
|
3132
|
+
default: "default",
|
|
3133
|
+
validator: (e) => ["success", "warning", "error", "default"].includes(e)
|
|
3134
|
+
},
|
|
3135
|
+
/**
|
|
3136
|
+
* Trend percentage (e.g. +5 or -3). Positive shows TrendingUp, negative shows TrendingDown.
|
|
3137
|
+
* @type {number}
|
|
3138
|
+
*/
|
|
3139
|
+
trend: {
|
|
3140
|
+
type: Number,
|
|
3141
|
+
default: void 0
|
|
3142
|
+
},
|
|
3143
|
+
/**
|
|
3144
|
+
* Subtext displayed below the value (e.g. "vs. Vorwoche").
|
|
3145
|
+
* @type {string}
|
|
3146
|
+
*/
|
|
3147
|
+
subtext: {
|
|
3148
|
+
type: String,
|
|
3149
|
+
default: void 0
|
|
3150
|
+
}
|
|
3151
|
+
},
|
|
3152
|
+
setup(e) {
|
|
3153
|
+
const r = e, t = {
|
|
3154
|
+
success: "text-green-500",
|
|
3155
|
+
warning: "text-amber-500",
|
|
3156
|
+
error: "text-red-500",
|
|
3157
|
+
default: "text-gray-900"
|
|
3158
|
+
}, o = b(
|
|
3159
|
+
() => t[r.status] ?? t.default
|
|
3160
|
+
), s = b(() => r.trend != null && r.trend !== 0), i = b(() => r.trend != null && r.trend > 0), u = b(() => r.trend != null && r.trend < 0), g = b(() => i.value ? "text-green-500" : "text-red-500"), d = b(() => r.trend == null ? "" : `${r.trend > 0 ? "+" : ""}${r.trend}%`), v = b(() => i.value ? "Aufwaertstrend" : "Abwaertstrend");
|
|
3161
|
+
return (m, f) => (n(), a("div", {
|
|
3162
|
+
class: "bg-white border border-lu-border rounded-card shadow-card p-4",
|
|
3163
|
+
role: "group",
|
|
3164
|
+
"aria-label": e.label
|
|
3165
|
+
}, [
|
|
3166
|
+
l("p", _r, y(e.label), 1),
|
|
3167
|
+
l("p", {
|
|
3168
|
+
class: w(["mt-2 text-[30px] font-bold tabular-nums leading-tight", o.value])
|
|
3169
|
+
}, y(e.value), 3),
|
|
3170
|
+
s.value || e.subtext ? (n(), a("div", Br, [
|
|
3171
|
+
s.value ? (n(), a("span", {
|
|
3172
|
+
key: 0,
|
|
3173
|
+
class: w(["inline-flex items-center gap-1 text-sm font-medium", g.value])
|
|
3174
|
+
}, [
|
|
3175
|
+
l("span", Er, y(v.value), 1),
|
|
3176
|
+
i.value ? (n(), P(R(Je), {
|
|
3177
|
+
key: 0,
|
|
3178
|
+
size: 16,
|
|
3179
|
+
"aria-hidden": "true"
|
|
3180
|
+
})) : c("", !0),
|
|
3181
|
+
u.value ? (n(), P(R(Ye), {
|
|
3182
|
+
key: 1,
|
|
3183
|
+
size: 16,
|
|
3184
|
+
"aria-hidden": "true"
|
|
3185
|
+
})) : c("", !0),
|
|
3186
|
+
M(" " + y(d.value), 1)
|
|
3187
|
+
], 2)) : c("", !0),
|
|
3188
|
+
e.subtext ? (n(), a("span", Ir, y(e.subtext), 1)) : c("", !0)
|
|
3189
|
+
])) : c("", !0)
|
|
3190
|
+
], 8, Ar));
|
|
3191
|
+
}
|
|
3192
|
+
}, Tr = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
3193
|
+
function ae(e, r) {
|
|
3194
|
+
const t = { ...e };
|
|
3195
|
+
for (const o of Object.keys(r)) {
|
|
3196
|
+
if (Tr.has(o)) continue;
|
|
3197
|
+
const s = e[o], i = r[o];
|
|
3198
|
+
i !== null && typeof i == "object" && !Array.isArray(i) && s !== null && typeof s == "object" && !Array.isArray(s) ? t[o] = ae(
|
|
3199
|
+
/** @type {Record<string, unknown>} */
|
|
3200
|
+
s,
|
|
3201
|
+
/** @type {Record<string, unknown>} */
|
|
3202
|
+
i
|
|
3203
|
+
) : t[o] = i;
|
|
3204
|
+
}
|
|
3205
|
+
return t;
|
|
3206
|
+
}
|
|
3207
|
+
function re(e) {
|
|
3208
|
+
for (const r of Object.values(e))
|
|
3209
|
+
r !== null && typeof r == "object" && !Object.isFrozen(r) && re(
|
|
3210
|
+
/** @type {Record<string, unknown>} */
|
|
3211
|
+
r
|
|
3212
|
+
);
|
|
3213
|
+
return Object.freeze(e);
|
|
3214
|
+
}
|
|
3215
|
+
const Ce = re({
|
|
3216
|
+
responsive: !0,
|
|
3217
|
+
maintainAspectRatio: !1,
|
|
3218
|
+
interaction: {
|
|
3219
|
+
mode: "nearest",
|
|
3220
|
+
intersect: !1
|
|
3221
|
+
},
|
|
3222
|
+
scales: {
|
|
3223
|
+
x: {
|
|
3224
|
+
grid: {
|
|
3225
|
+
display: !1
|
|
3226
|
+
},
|
|
3227
|
+
ticks: {
|
|
3228
|
+
color: "#64748B",
|
|
3229
|
+
font: {
|
|
3230
|
+
size: 12
|
|
3231
|
+
}
|
|
3232
|
+
}
|
|
3233
|
+
},
|
|
3234
|
+
y: {
|
|
3235
|
+
grid: {
|
|
3236
|
+
color: "#F1F5F9"
|
|
3237
|
+
},
|
|
3238
|
+
ticks: {
|
|
3239
|
+
color: "#64748B",
|
|
3240
|
+
font: {
|
|
3241
|
+
size: 12
|
|
3242
|
+
}
|
|
3243
|
+
}
|
|
3244
|
+
}
|
|
3245
|
+
},
|
|
3246
|
+
plugins: {
|
|
3247
|
+
legend: {
|
|
3248
|
+
display: !1
|
|
3249
|
+
},
|
|
3250
|
+
tooltip: {
|
|
3251
|
+
backgroundColor: "#0B1929",
|
|
3252
|
+
titleFont: { size: 13 },
|
|
3253
|
+
bodyFont: { size: 12 },
|
|
3254
|
+
cornerRadius: 6,
|
|
3255
|
+
padding: 10
|
|
3256
|
+
}
|
|
3257
|
+
}
|
|
3258
|
+
}), Mr = re({
|
|
3259
|
+
borderColor: "#00BFA6",
|
|
3260
|
+
backgroundColor: "rgba(0, 191, 166, 0.1)",
|
|
3261
|
+
pointBackgroundColor: "#00BFA6",
|
|
3262
|
+
pointBorderColor: "#ffffff",
|
|
3263
|
+
pointRadius: 3,
|
|
3264
|
+
pointHoverRadius: 5,
|
|
3265
|
+
borderWidth: 2,
|
|
3266
|
+
tension: 0.3
|
|
3267
|
+
}), jr = re({
|
|
3268
|
+
backgroundColor: "#00BFA6",
|
|
3269
|
+
borderRadius: 4
|
|
3270
|
+
}), Or = ["aria-label"], Dr = {
|
|
3271
|
+
__name: "LuLineChart",
|
|
3272
|
+
props: {
|
|
3273
|
+
/**
|
|
3274
|
+
* Chart.js data object with labels and datasets.
|
|
3275
|
+
* @type {import('chart.js').ChartData<'line'>}
|
|
3276
|
+
*/
|
|
3277
|
+
data: {
|
|
3278
|
+
type: Object,
|
|
3279
|
+
required: !0
|
|
3280
|
+
},
|
|
3281
|
+
/**
|
|
3282
|
+
* Chart.js options (deep-merged with defaults).
|
|
3283
|
+
* @type {import('chart.js').ChartOptions<'line'>}
|
|
3284
|
+
*/
|
|
3285
|
+
options: {
|
|
3286
|
+
type: Object,
|
|
3287
|
+
default: () => ({})
|
|
3288
|
+
},
|
|
3289
|
+
/**
|
|
3290
|
+
* CSS height for the chart container.
|
|
3291
|
+
* @type {string}
|
|
3292
|
+
*/
|
|
3293
|
+
height: {
|
|
3294
|
+
type: String,
|
|
3295
|
+
default: "100%"
|
|
3296
|
+
},
|
|
3297
|
+
/**
|
|
3298
|
+
* Accessible label for the chart (used as aria-label on the container).
|
|
3299
|
+
* @type {string}
|
|
3300
|
+
*/
|
|
3301
|
+
ariaLabel: {
|
|
3302
|
+
type: String,
|
|
3303
|
+
default: "Liniendiagramm"
|
|
3304
|
+
}
|
|
3305
|
+
},
|
|
3306
|
+
setup(e) {
|
|
3307
|
+
ue.register(we, ke, at, rt, de, ce, st);
|
|
3308
|
+
const r = e, t = b(
|
|
3309
|
+
() => (
|
|
3310
|
+
/** @type {import('chart.js').ChartOptions<'line'>} */
|
|
3311
|
+
ae(Ce, r.options)
|
|
3312
|
+
)
|
|
3313
|
+
), o = b(() => {
|
|
3314
|
+
const s = (r.data.datasets ?? []).map((i) => ({
|
|
3315
|
+
...Mr,
|
|
3316
|
+
...i
|
|
3317
|
+
}));
|
|
3318
|
+
return { ...r.data, datasets: s };
|
|
3319
|
+
});
|
|
3320
|
+
return (s, i) => (n(), a("div", {
|
|
3321
|
+
style: H({ height: e.height, width: "100%", position: "relative" }),
|
|
3322
|
+
role: "img",
|
|
3323
|
+
"aria-label": e.ariaLabel
|
|
3324
|
+
}, [
|
|
3325
|
+
A(R(et), {
|
|
3326
|
+
data: o.value,
|
|
3327
|
+
options: t.value
|
|
3328
|
+
}, null, 8, ["data", "options"])
|
|
3329
|
+
], 12, Or));
|
|
3330
|
+
}
|
|
3331
|
+
}, Vr = ["aria-label"], Pr = {
|
|
3332
|
+
__name: "LuBarChart",
|
|
3333
|
+
props: {
|
|
3334
|
+
/**
|
|
3335
|
+
* Chart.js data object with labels and datasets.
|
|
3336
|
+
* Datasets without explicit backgroundColor will default to teal-500 (#00BFA6).
|
|
3337
|
+
* @type {import('chart.js').ChartData<'bar'>}
|
|
3338
|
+
*/
|
|
3339
|
+
data: {
|
|
3340
|
+
type: Object,
|
|
3341
|
+
required: !0
|
|
3342
|
+
},
|
|
3343
|
+
/**
|
|
3344
|
+
* Chart.js options (deep-merged with defaults).
|
|
3345
|
+
* @type {import('chart.js').ChartOptions<'bar'>}
|
|
3346
|
+
*/
|
|
3347
|
+
options: {
|
|
3348
|
+
type: Object,
|
|
3349
|
+
default: () => ({})
|
|
3350
|
+
},
|
|
3351
|
+
/**
|
|
3352
|
+
* CSS height for the chart container.
|
|
3353
|
+
* @type {string}
|
|
3354
|
+
*/
|
|
3355
|
+
height: {
|
|
3356
|
+
type: String,
|
|
3357
|
+
default: "100%"
|
|
3358
|
+
},
|
|
3359
|
+
/**
|
|
3360
|
+
* Accessible label for the chart (used as aria-label on the container).
|
|
3361
|
+
* @type {string}
|
|
3362
|
+
*/
|
|
3363
|
+
ariaLabel: {
|
|
3364
|
+
type: String,
|
|
3365
|
+
default: "Balkendiagramm"
|
|
3366
|
+
}
|
|
3367
|
+
},
|
|
3368
|
+
setup(e) {
|
|
3369
|
+
ue.register(we, ke, lt, de, ce);
|
|
3370
|
+
const r = e, t = b(
|
|
3371
|
+
() => (
|
|
3372
|
+
/** @type {import('chart.js').ChartOptions<'bar'>} */
|
|
3373
|
+
ae(Ce, r.options)
|
|
3374
|
+
)
|
|
3375
|
+
), o = b(() => {
|
|
3376
|
+
const s = (r.data.datasets ?? []).map((i) => ({
|
|
3377
|
+
...jr,
|
|
3378
|
+
...i
|
|
3379
|
+
}));
|
|
3380
|
+
return { ...r.data, datasets: s };
|
|
3381
|
+
});
|
|
3382
|
+
return (s, i) => (n(), a("div", {
|
|
3383
|
+
style: H({ height: e.height, width: "100%", position: "relative" }),
|
|
3384
|
+
role: "img",
|
|
3385
|
+
"aria-label": e.ariaLabel
|
|
3386
|
+
}, [
|
|
3387
|
+
A(R(tt), {
|
|
3388
|
+
data: o.value,
|
|
3389
|
+
options: t.value
|
|
3390
|
+
}, null, 8, ["data", "options"])
|
|
3391
|
+
], 12, Vr));
|
|
3392
|
+
}
|
|
3393
|
+
}, Rr = ["aria-label"], Nr = {
|
|
3394
|
+
responsive: !0,
|
|
3395
|
+
maintainAspectRatio: !1,
|
|
3396
|
+
cutout: "65%",
|
|
3397
|
+
// Donut-style (0% = pie)
|
|
3398
|
+
plugins: {
|
|
3399
|
+
legend: {
|
|
3400
|
+
display: !0,
|
|
3401
|
+
position: "bottom",
|
|
3402
|
+
labels: {
|
|
3403
|
+
usePointStyle: !0,
|
|
3404
|
+
pointStyle: "circle",
|
|
3405
|
+
padding: 16,
|
|
3406
|
+
font: {
|
|
3407
|
+
size: 12,
|
|
3408
|
+
family: "Inter, system-ui, sans-serif"
|
|
3409
|
+
},
|
|
3410
|
+
color: "#475569"
|
|
3411
|
+
}
|
|
3412
|
+
},
|
|
3413
|
+
tooltip: {
|
|
3414
|
+
backgroundColor: "#0B1929",
|
|
3415
|
+
titleFont: { size: 13, family: "Inter, system-ui, sans-serif" },
|
|
3416
|
+
bodyFont: { size: 12, family: "Inter, system-ui, sans-serif" },
|
|
3417
|
+
cornerRadius: 6,
|
|
3418
|
+
padding: 10,
|
|
3419
|
+
callbacks: {
|
|
3420
|
+
label: function(e) {
|
|
3421
|
+
const r = e.label || "", t = e.parsed || 0, o = e.dataset.data.reduce((i, u) => i + u, 0), s = o > 0 ? (t / o * 100).toFixed(1) : 0;
|
|
3422
|
+
return `${r}: ${t} (${s}%)`;
|
|
3423
|
+
}
|
|
3424
|
+
}
|
|
3425
|
+
},
|
|
3426
|
+
title: {
|
|
3427
|
+
display: !1
|
|
3428
|
+
}
|
|
3429
|
+
}
|
|
3430
|
+
}, Fr = {
|
|
3431
|
+
__name: "LuDonutChart",
|
|
3432
|
+
props: {
|
|
3433
|
+
/**
|
|
3434
|
+
* Chart.js data object with labels and datasets.
|
|
3435
|
+
* Datasets without explicit backgroundColor will use default palette.
|
|
3436
|
+
* @type {import('chart.js').ChartData<'doughnut'>}
|
|
3437
|
+
*/
|
|
3438
|
+
data: {
|
|
3439
|
+
type: Object,
|
|
3440
|
+
required: !0
|
|
3441
|
+
},
|
|
3442
|
+
/**
|
|
3443
|
+
* Chart.js options (deep-merged with defaults).
|
|
3444
|
+
* @type {import('chart.js').ChartOptions<'doughnut'>}
|
|
3445
|
+
*/
|
|
3446
|
+
options: {
|
|
3447
|
+
type: Object,
|
|
3448
|
+
default: () => ({})
|
|
3449
|
+
},
|
|
3450
|
+
/**
|
|
3451
|
+
* CSS height for the chart container.
|
|
3452
|
+
* @type {string}
|
|
3453
|
+
*/
|
|
3454
|
+
height: {
|
|
3455
|
+
type: String,
|
|
3456
|
+
default: "300px"
|
|
3457
|
+
},
|
|
3458
|
+
/**
|
|
3459
|
+
* Accessible label for the chart (used as aria-label on the container).
|
|
3460
|
+
* @type {string}
|
|
3461
|
+
*/
|
|
3462
|
+
ariaLabel: {
|
|
3463
|
+
type: String,
|
|
3464
|
+
default: "Kreisdiagramm"
|
|
3465
|
+
}
|
|
3466
|
+
},
|
|
3467
|
+
setup(e) {
|
|
3468
|
+
ue.register(ot, de, ce, it);
|
|
3469
|
+
const r = e, t = b(
|
|
3470
|
+
() => (
|
|
3471
|
+
/** @type {import('chart.js').ChartOptions<'doughnut'>} */
|
|
3472
|
+
ae(Nr, r.options)
|
|
3473
|
+
)
|
|
3474
|
+
), o = b(() => {
|
|
3475
|
+
const i = (r.data.datasets ?? []).map((u) => {
|
|
3476
|
+
var g;
|
|
3477
|
+
if (!u.backgroundColor) {
|
|
3478
|
+
const d = ((g = u.data) == null ? void 0 : g.length) || 0;
|
|
3479
|
+
u.backgroundColor = s(d);
|
|
3480
|
+
}
|
|
3481
|
+
return u;
|
|
3482
|
+
});
|
|
3483
|
+
return { ...r.data, datasets: i };
|
|
3484
|
+
});
|
|
3485
|
+
function s(i) {
|
|
3486
|
+
return [
|
|
3487
|
+
"#00BFA6",
|
|
3488
|
+
// teal-500 - primary
|
|
3489
|
+
"#0EA5E9",
|
|
3490
|
+
// sky-500 - secondary
|
|
3491
|
+
"#8B5CF6",
|
|
3492
|
+
// violet-500 - accent
|
|
3493
|
+
"#F59E0B",
|
|
3494
|
+
// amber-500 - warning
|
|
3495
|
+
"#EF4444",
|
|
3496
|
+
// red-500 - danger
|
|
3497
|
+
"#10B981",
|
|
3498
|
+
// emerald-500 - success
|
|
3499
|
+
"#6366F1",
|
|
3500
|
+
// indigo-500
|
|
3501
|
+
"#EC4899",
|
|
3502
|
+
// pink-500
|
|
3503
|
+
"#14B8A6",
|
|
3504
|
+
// teal-500 variant
|
|
3505
|
+
"#F97316"
|
|
3506
|
+
// orange-500
|
|
3507
|
+
].slice(0, i);
|
|
3508
|
+
}
|
|
3509
|
+
return (i, u) => (n(), a("div", {
|
|
3510
|
+
style: H({ height: e.height, width: "100%", position: "relative" }),
|
|
3511
|
+
role: "img",
|
|
3512
|
+
"aria-label": e.ariaLabel
|
|
3513
|
+
}, [
|
|
3514
|
+
A(R(nt), {
|
|
3515
|
+
data: o.value,
|
|
3516
|
+
options: t.value
|
|
3517
|
+
}, null, 8, ["data", "options"])
|
|
3518
|
+
], 12, Rr));
|
|
3519
|
+
}
|
|
3520
|
+
}, qr = ["aria-expanded"], Kr = {
|
|
3521
|
+
key: 0,
|
|
3522
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
3523
|
+
class: "h-4 w-4 shrink-0",
|
|
3524
|
+
viewBox: "0 0 24 24",
|
|
3525
|
+
fill: "none",
|
|
3526
|
+
stroke: "currentColor",
|
|
3527
|
+
"stroke-width": "2",
|
|
3528
|
+
"stroke-linecap": "round",
|
|
3529
|
+
"stroke-linejoin": "round",
|
|
3530
|
+
"aria-hidden": "true"
|
|
3531
|
+
}, Ur = {
|
|
3532
|
+
key: 0,
|
|
3533
|
+
class: "absolute right-0 top-full z-dropdown mt-1 min-w-[160px] bg-white border border-lu-border rounded-card shadow-card py-1",
|
|
3534
|
+
role: "menu"
|
|
3535
|
+
}, Hr = {
|
|
3536
|
+
key: 0,
|
|
3537
|
+
class: "my-1 border-t border-lu-border",
|
|
3538
|
+
role: "separator"
|
|
3539
|
+
}, Zr = ["disabled", "onClick"], Wr = {
|
|
3540
|
+
key: 0,
|
|
3541
|
+
class: "shrink-0 text-gray-400",
|
|
3542
|
+
"aria-hidden": "true"
|
|
3543
|
+
}, Gr = ["innerHTML"], Xr = {
|
|
3544
|
+
key: 1,
|
|
3545
|
+
class: "ml-auto text-xs text-gray-400"
|
|
3546
|
+
}, Jr = {
|
|
3547
|
+
__name: "LuDropdown",
|
|
3548
|
+
props: {
|
|
3549
|
+
/**
|
|
3550
|
+
* Button label displayed in the trigger.
|
|
3551
|
+
* @type {string}
|
|
3552
|
+
*/
|
|
3553
|
+
label: {
|
|
3554
|
+
type: String,
|
|
3555
|
+
required: !0
|
|
3556
|
+
},
|
|
3557
|
+
/**
|
|
3558
|
+
* Menu options.
|
|
3559
|
+
* @type {Array<{value: string, label: string, description?: string, disabled?: boolean}>}
|
|
3560
|
+
*/
|
|
3561
|
+
options: {
|
|
3562
|
+
type: Array,
|
|
3563
|
+
default: () => []
|
|
3564
|
+
},
|
|
3565
|
+
/**
|
|
3566
|
+
* Icon displayed before the label in the trigger button.
|
|
3567
|
+
* Accepts an SVG string or Vue component.
|
|
3568
|
+
* @type {string | object}
|
|
3569
|
+
*/
|
|
3570
|
+
icon: {
|
|
3571
|
+
type: [String, Object],
|
|
3572
|
+
default: null
|
|
3573
|
+
},
|
|
3574
|
+
/**
|
|
3575
|
+
* Button variant: 'primary' | 'secondary' | 'ghost'.
|
|
3576
|
+
* @type {string}
|
|
3577
|
+
*/
|
|
3578
|
+
variant: {
|
|
3579
|
+
type: String,
|
|
3580
|
+
default: "secondary",
|
|
3581
|
+
validator: (e) => ["primary", "secondary", "ghost"].includes(e)
|
|
3582
|
+
},
|
|
3583
|
+
/**
|
|
3584
|
+
* Button size: 'sm' | 'md' | 'lg'.
|
|
3585
|
+
* @type {string}
|
|
3586
|
+
*/
|
|
3587
|
+
size: {
|
|
3588
|
+
type: String,
|
|
3589
|
+
default: "sm",
|
|
3590
|
+
validator: (e) => ["sm", "md", "lg"].includes(e)
|
|
3591
|
+
}
|
|
3592
|
+
},
|
|
3593
|
+
emits: ["select"],
|
|
3594
|
+
setup(e, { emit: r }) {
|
|
3595
|
+
const t = e, o = r, s = E(!1), i = E(null);
|
|
3596
|
+
ne(i, () => {
|
|
3597
|
+
s.value = !1;
|
|
3598
|
+
});
|
|
3599
|
+
function u() {
|
|
3600
|
+
s.value = !s.value;
|
|
3601
|
+
}
|
|
3602
|
+
function g(m) {
|
|
3603
|
+
m.disabled || (o("select", m.value), s.value = !1);
|
|
3604
|
+
}
|
|
3605
|
+
const d = {
|
|
3606
|
+
primary: "border-teal-600 bg-teal-600 text-white hover:bg-teal-700 focus-visible:ring-teal-500",
|
|
3607
|
+
secondary: "border-lu-border bg-white text-gray-700 hover:bg-gray-50 focus-visible:ring-teal-500",
|
|
3608
|
+
ghost: "border-transparent bg-transparent text-gray-600 hover:bg-gray-100 focus-visible:ring-teal-500"
|
|
3609
|
+
}, v = {
|
|
3610
|
+
sm: "px-3 py-1.5 text-sm",
|
|
3611
|
+
md: "px-4 py-2 text-sm",
|
|
3612
|
+
lg: "px-4 py-2.5 text-base"
|
|
3613
|
+
};
|
|
3614
|
+
return (m, f) => (n(), a("div", {
|
|
3615
|
+
ref_key: "triggerRef",
|
|
3616
|
+
ref: i,
|
|
3617
|
+
class: "relative inline-flex"
|
|
3618
|
+
}, [
|
|
3619
|
+
l("button", {
|
|
3620
|
+
type: "button",
|
|
3621
|
+
class: w([
|
|
3622
|
+
"inline-flex items-center gap-1.5 border rounded-button font-medium transition-colors",
|
|
3623
|
+
"duration-150 focus-visible:ring-2 focus-visible:ring-offset-[2px] focus-visible:outline-none",
|
|
3624
|
+
d[t.variant] ?? d.secondary,
|
|
3625
|
+
v[t.size] ?? v.sm
|
|
3626
|
+
]),
|
|
3627
|
+
"aria-expanded": s.value,
|
|
3628
|
+
"aria-haspopup": "menu",
|
|
3629
|
+
onClick: u
|
|
3630
|
+
}, [
|
|
3631
|
+
t.icon ? c("", !0) : (n(), a("svg", Kr, [...f[0] || (f[0] = [
|
|
3632
|
+
l("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }, null, -1),
|
|
3633
|
+
l("polyline", { points: "7 10 12 15 17 10" }, null, -1),
|
|
3634
|
+
l("line", {
|
|
3635
|
+
x1: "12",
|
|
3636
|
+
y1: "15",
|
|
3637
|
+
x2: "12",
|
|
3638
|
+
y2: "3"
|
|
3639
|
+
}, null, -1)
|
|
3640
|
+
])])),
|
|
3641
|
+
l("span", null, y(t.label), 1),
|
|
3642
|
+
(n(), a("svg", {
|
|
3643
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
3644
|
+
class: w(["h-3.5 w-3.5 shrink-0 transition-transform duration-150", s.value ? "rotate-180" : ""]),
|
|
3645
|
+
viewBox: "0 0 24 24",
|
|
3646
|
+
fill: "none",
|
|
3647
|
+
stroke: "currentColor",
|
|
3648
|
+
"stroke-width": "2",
|
|
3649
|
+
"stroke-linecap": "round",
|
|
3650
|
+
"stroke-linejoin": "round",
|
|
3651
|
+
"aria-hidden": "true"
|
|
3652
|
+
}, [...f[1] || (f[1] = [
|
|
3653
|
+
l("polyline", { points: "6 9 12 15 18 9" }, null, -1)
|
|
3654
|
+
])], 2))
|
|
3655
|
+
], 10, qr),
|
|
3656
|
+
A(Z, {
|
|
3657
|
+
"enter-active-class": "transition ease-out duration-100",
|
|
3658
|
+
"enter-from-class": "transform opacity-0 scale-95",
|
|
3659
|
+
"enter-to-class": "transform opacity-100 scale-100",
|
|
3660
|
+
"leave-active-class": "transition ease-in duration-75",
|
|
3661
|
+
"leave-from-class": "transform opacity-100 scale-100",
|
|
3662
|
+
"leave-to-class": "transform opacity-0 scale-95"
|
|
3663
|
+
}, {
|
|
3664
|
+
default: T(() => [
|
|
3665
|
+
s.value ? (n(), a("div", Ur, [
|
|
3666
|
+
(n(!0), a(z, null, j(t.options, (p) => (n(), a(z, {
|
|
3667
|
+
key: p.value
|
|
3668
|
+
}, [
|
|
3669
|
+
p.divider ? (n(), a("div", Hr)) : (n(), a("button", {
|
|
3670
|
+
key: 1,
|
|
3671
|
+
type: "button",
|
|
3672
|
+
class: w([
|
|
3673
|
+
"w-full flex items-center gap-2 px-4 py-2 text-sm text-left transition-colors duration-100 focus-visible:outline-none focus-visible:bg-gray-50",
|
|
3674
|
+
p.disabled ? "text-gray-300 cursor-not-allowed" : "text-gray-700 hover:bg-gray-50 active:bg-gray-100"
|
|
3675
|
+
]),
|
|
3676
|
+
disabled: p.disabled,
|
|
3677
|
+
role: "menuitem",
|
|
3678
|
+
onClick: (x) => g(p)
|
|
3679
|
+
}, [
|
|
3680
|
+
p.icon ? (n(), a("span", Wr, [
|
|
3681
|
+
l("span", {
|
|
3682
|
+
innerHTML: p.icon
|
|
3683
|
+
}, null, 8, Gr)
|
|
3684
|
+
])) : c("", !0),
|
|
3685
|
+
l("span", {
|
|
3686
|
+
class: w(p.disabled ? "opacity-60" : "")
|
|
3687
|
+
}, y(p.label), 3),
|
|
3688
|
+
p.description ? (n(), a("span", Xr, y(p.description), 1)) : c("", !0)
|
|
3689
|
+
], 10, Zr))
|
|
3690
|
+
], 64))), 128))
|
|
3691
|
+
])) : c("", !0)
|
|
3692
|
+
]),
|
|
3693
|
+
_: 1
|
|
3694
|
+
})
|
|
3695
|
+
], 512));
|
|
3696
|
+
}
|
|
3697
|
+
}, Yr = {
|
|
3698
|
+
key: 0,
|
|
3699
|
+
class: "lu-action-bar fixed bottom-0 left-0 right-0 z-action-bar",
|
|
3700
|
+
role: "region",
|
|
3701
|
+
"aria-label": "Massenauswahl-Aktionen"
|
|
3702
|
+
}, Qr = {
|
|
3703
|
+
class: "lu-action-bar-content bg-gray-900 text-white px-4 py-3 sm:px-6",
|
|
3704
|
+
role: "toolbar",
|
|
3705
|
+
"aria-label": "Ausgewählte Elemente Aktionen"
|
|
3706
|
+
}, es = { class: "max-w-7xl mx-auto flex flex-col sm:flex-row items-center justify-between gap-3" }, ts = { class: "flex items-center gap-3 w-full sm:w-auto" }, ns = { class: "text-sm font-medium text-gray-100 whitespace-nowrap" }, as = { class: "flex items-center gap-2 w-full sm:w-auto justify-end" }, rs = /* @__PURE__ */ Object.assign({ name: "LuActionBar" }, {
|
|
3707
|
+
__name: "LuActionBar",
|
|
3708
|
+
props: {
|
|
3709
|
+
/**
|
|
3710
|
+
* Anzahl ausgewählter Elemente.
|
|
3711
|
+
*/
|
|
3712
|
+
selectedCount: {
|
|
3713
|
+
type: Number,
|
|
3714
|
+
required: !0
|
|
3715
|
+
},
|
|
3716
|
+
/**
|
|
3717
|
+
* Ob sich die Aktion im Ladezustand befindet.
|
|
3718
|
+
*/
|
|
3719
|
+
loading: {
|
|
3720
|
+
type: Boolean,
|
|
3721
|
+
default: !1
|
|
3722
|
+
},
|
|
3723
|
+
/**
|
|
3724
|
+
* Ob der Lösch-Button angezeigt werden soll.
|
|
3725
|
+
*/
|
|
3726
|
+
showDelete: {
|
|
3727
|
+
type: Boolean,
|
|
3728
|
+
default: !0
|
|
3729
|
+
},
|
|
3730
|
+
/**
|
|
3731
|
+
* Ob der Export-Button angezeigt werden soll.
|
|
3732
|
+
*/
|
|
3733
|
+
showExport: {
|
|
3734
|
+
type: Boolean,
|
|
3735
|
+
default: !0
|
|
3736
|
+
},
|
|
3737
|
+
/**
|
|
3738
|
+
* Ob der Status-Button angezeigt werden soll.
|
|
3739
|
+
*/
|
|
3740
|
+
showStatus: {
|
|
3741
|
+
type: Boolean,
|
|
3742
|
+
default: !0
|
|
3743
|
+
},
|
|
3744
|
+
/**
|
|
3745
|
+
* Ob der Abteilung-Button angezeigt werden soll.
|
|
3746
|
+
*/
|
|
3747
|
+
showDepartment: {
|
|
3748
|
+
type: Boolean,
|
|
3749
|
+
default: !0
|
|
3750
|
+
}
|
|
3751
|
+
},
|
|
3752
|
+
emits: [
|
|
3753
|
+
"cancel",
|
|
3754
|
+
"action-status",
|
|
3755
|
+
"action-department",
|
|
3756
|
+
"action-export",
|
|
3757
|
+
"action-delete"
|
|
3758
|
+
],
|
|
3759
|
+
setup(e, { emit: r }) {
|
|
3760
|
+
const t = e, o = r, s = b(() => `${t.selectedCount} ausgewählt`);
|
|
3761
|
+
return (i, u) => (n(), P(Z, { name: "lu-action-bar" }, {
|
|
3762
|
+
default: T(() => [
|
|
3763
|
+
e.selectedCount > 0 ? (n(), a("div", Yr, [
|
|
3764
|
+
u[10] || (u[10] = l("div", { class: "lu-action-bar-backdrop h-4 bg-gradient-to-t from-gray-900/10 to-transparent" }, null, -1)),
|
|
3765
|
+
l("div", Qr, [
|
|
3766
|
+
l("div", es, [
|
|
3767
|
+
l("div", ts, [
|
|
3768
|
+
l("span", ns, y(s.value), 1),
|
|
3769
|
+
A(K, {
|
|
3770
|
+
variant: "ghost",
|
|
3771
|
+
size: "sm",
|
|
3772
|
+
disabled: e.loading,
|
|
3773
|
+
onClick: u[0] || (u[0] = (g) => o("cancel")),
|
|
3774
|
+
class: "text-gray-300 hover:text-white hover:bg-white/10"
|
|
3775
|
+
}, {
|
|
3776
|
+
default: T(() => [...u[5] || (u[5] = [
|
|
3777
|
+
M(" Abbrechen ", -1)
|
|
3778
|
+
])]),
|
|
3779
|
+
_: 1
|
|
3780
|
+
}, 8, ["disabled"])
|
|
3781
|
+
]),
|
|
3782
|
+
l("div", as, [
|
|
3783
|
+
e.showStatus ? (n(), P(K, {
|
|
3784
|
+
key: 0,
|
|
3785
|
+
variant: "secondary",
|
|
3786
|
+
size: "sm",
|
|
3787
|
+
disabled: e.loading,
|
|
3788
|
+
onClick: u[1] || (u[1] = (g) => o("action-status"))
|
|
3789
|
+
}, {
|
|
3790
|
+
"icon-left": T(() => [
|
|
3791
|
+
A(O, {
|
|
3792
|
+
name: "CircleDot",
|
|
3793
|
+
size: 16
|
|
3794
|
+
})
|
|
3795
|
+
]),
|
|
3796
|
+
default: T(() => [
|
|
3797
|
+
u[6] || (u[6] = M(" Status ", -1))
|
|
3798
|
+
]),
|
|
3799
|
+
_: 1
|
|
3800
|
+
}, 8, ["disabled"])) : c("", !0),
|
|
3801
|
+
e.showDepartment ? (n(), P(K, {
|
|
3802
|
+
key: 1,
|
|
3803
|
+
variant: "secondary",
|
|
3804
|
+
size: "sm",
|
|
3805
|
+
disabled: e.loading,
|
|
3806
|
+
onClick: u[2] || (u[2] = (g) => o("action-department"))
|
|
3807
|
+
}, {
|
|
3808
|
+
"icon-left": T(() => [
|
|
3809
|
+
A(O, {
|
|
3810
|
+
name: "Building2",
|
|
3811
|
+
size: 16
|
|
3812
|
+
})
|
|
3813
|
+
]),
|
|
3814
|
+
default: T(() => [
|
|
3815
|
+
u[7] || (u[7] = M(" Abteilung ", -1))
|
|
3816
|
+
]),
|
|
3817
|
+
_: 1
|
|
3818
|
+
}, 8, ["disabled"])) : c("", !0),
|
|
3819
|
+
e.showExport ? (n(), P(K, {
|
|
3820
|
+
key: 2,
|
|
3821
|
+
variant: "secondary",
|
|
3822
|
+
size: "sm",
|
|
3823
|
+
disabled: e.loading,
|
|
3824
|
+
onClick: u[3] || (u[3] = (g) => o("action-export"))
|
|
3825
|
+
}, {
|
|
3826
|
+
"icon-left": T(() => [
|
|
3827
|
+
A(O, {
|
|
3828
|
+
name: "Download",
|
|
3829
|
+
size: 16
|
|
3830
|
+
})
|
|
3831
|
+
]),
|
|
3832
|
+
default: T(() => [
|
|
3833
|
+
u[8] || (u[8] = M(" Export ", -1))
|
|
3834
|
+
]),
|
|
3835
|
+
_: 1
|
|
3836
|
+
}, 8, ["disabled"])) : c("", !0),
|
|
3837
|
+
e.showDelete ? (n(), P(K, {
|
|
3838
|
+
key: 3,
|
|
3839
|
+
variant: "danger",
|
|
3840
|
+
size: "sm",
|
|
3841
|
+
disabled: e.loading,
|
|
3842
|
+
onClick: u[4] || (u[4] = (g) => o("action-delete"))
|
|
3843
|
+
}, {
|
|
3844
|
+
"icon-left": T(() => [
|
|
3845
|
+
A(O, {
|
|
3846
|
+
name: "Trash2",
|
|
3847
|
+
size: 16
|
|
3848
|
+
})
|
|
3849
|
+
]),
|
|
3850
|
+
default: T(() => [
|
|
3851
|
+
u[9] || (u[9] = M(" Löschen ", -1))
|
|
3852
|
+
]),
|
|
3853
|
+
_: 1
|
|
3854
|
+
}, 8, ["disabled"])) : c("", !0),
|
|
3855
|
+
B(i.$slots, "actions", {}, void 0, !0)
|
|
3856
|
+
])
|
|
3857
|
+
])
|
|
3858
|
+
])
|
|
3859
|
+
])) : c("", !0)
|
|
3860
|
+
]),
|
|
3861
|
+
_: 3
|
|
3862
|
+
}));
|
|
3863
|
+
}
|
|
3864
|
+
}), ss = /* @__PURE__ */ W(rs, [["__scopeId", "data-v-25637a88"]]);
|
|
3865
|
+
function gs(e = !1) {
|
|
3866
|
+
const r = E(e);
|
|
3867
|
+
function t() {
|
|
3868
|
+
r.value = !0;
|
|
3869
|
+
}
|
|
3870
|
+
function o() {
|
|
3871
|
+
r.value = !1;
|
|
3872
|
+
}
|
|
3873
|
+
function s() {
|
|
3874
|
+
r.value = !r.value;
|
|
3875
|
+
}
|
|
3876
|
+
return { isOpen: r, open: t, close: o, toggle: s };
|
|
3877
|
+
}
|
|
3878
|
+
const ls = {
|
|
3879
|
+
LuButton: K,
|
|
3880
|
+
LuInput: xt,
|
|
3881
|
+
LuTextarea: Lt,
|
|
3882
|
+
LuCard: Pt,
|
|
3883
|
+
LuTable: Qt,
|
|
3884
|
+
LuBadge: en,
|
|
3885
|
+
LuIcon: O,
|
|
3886
|
+
LuAvatar: oe,
|
|
3887
|
+
LuToast: bn,
|
|
3888
|
+
LuAlert: vn,
|
|
3889
|
+
LuSkeleton: pn,
|
|
3890
|
+
LuEmptyState: $n,
|
|
3891
|
+
LuSelect: Nn,
|
|
3892
|
+
LuDatePicker: Yn,
|
|
3893
|
+
LuTabs: ea,
|
|
3894
|
+
LuTabList: ta,
|
|
3895
|
+
LuTab: aa,
|
|
3896
|
+
LuTabPanel: sa,
|
|
3897
|
+
LuPagination: ma,
|
|
3898
|
+
LuCheckbox: ka,
|
|
3899
|
+
LuRadio: La,
|
|
3900
|
+
LuToggle: _a,
|
|
3901
|
+
LuFormGroup: Ma,
|
|
3902
|
+
LuAppLayout: fr,
|
|
3903
|
+
LuSidebar: $e,
|
|
3904
|
+
LuHeader: Se,
|
|
3905
|
+
LuBreadcrumb: pr,
|
|
3906
|
+
LuModal: Lr,
|
|
3907
|
+
LuKpiCard: zr,
|
|
3908
|
+
LuLineChart: Dr,
|
|
3909
|
+
LuBarChart: Pr,
|
|
3910
|
+
LuDonutChart: Fr,
|
|
3911
|
+
LuDropdown: Jr,
|
|
3912
|
+
LuActionBar: ss
|
|
3913
|
+
}, ys = {
|
|
3914
|
+
/**
|
|
3915
|
+
* @param {import('vue').App} app
|
|
3916
|
+
*/
|
|
3917
|
+
install(e) {
|
|
3918
|
+
for (const [r, t] of Object.entries(ls))
|
|
3919
|
+
e.component(r, t);
|
|
3920
|
+
}
|
|
3921
|
+
};
|
|
3922
|
+
export {
|
|
3923
|
+
ss as LuActionBar,
|
|
3924
|
+
vn as LuAlert,
|
|
3925
|
+
fr as LuAppLayout,
|
|
3926
|
+
oe as LuAvatar,
|
|
3927
|
+
en as LuBadge,
|
|
3928
|
+
Pr as LuBarChart,
|
|
3929
|
+
pr as LuBreadcrumb,
|
|
3930
|
+
K as LuButton,
|
|
3931
|
+
Pt as LuCard,
|
|
3932
|
+
ka as LuCheckbox,
|
|
3933
|
+
Yn as LuDatePicker,
|
|
3934
|
+
Fr as LuDonutChart,
|
|
3935
|
+
Jr as LuDropdown,
|
|
3936
|
+
$n as LuEmptyState,
|
|
3937
|
+
Ma as LuFormGroup,
|
|
3938
|
+
Se as LuHeader,
|
|
3939
|
+
O as LuIcon,
|
|
3940
|
+
xt as LuInput,
|
|
3941
|
+
zr as LuKpiCard,
|
|
3942
|
+
Dr as LuLineChart,
|
|
3943
|
+
Lr as LuModal,
|
|
3944
|
+
ma as LuPagination,
|
|
3945
|
+
La as LuRadio,
|
|
3946
|
+
Nn as LuSelect,
|
|
3947
|
+
$e as LuSidebar,
|
|
3948
|
+
pn as LuSkeleton,
|
|
3949
|
+
aa as LuTab,
|
|
3950
|
+
ta as LuTabList,
|
|
3951
|
+
sa as LuTabPanel,
|
|
3952
|
+
Qt as LuTable,
|
|
3953
|
+
ea as LuTabs,
|
|
3954
|
+
Lt as LuTextarea,
|
|
3955
|
+
bn as LuToast,
|
|
3956
|
+
_a as LuToggle,
|
|
3957
|
+
jr as barDatasetDefaults,
|
|
3958
|
+
Ce as baseChartOptions,
|
|
3959
|
+
ae as deepMerge,
|
|
3960
|
+
ys as default,
|
|
3961
|
+
Mr as lineDatasetDefaults,
|
|
3962
|
+
ne as useClickOutside,
|
|
3963
|
+
gs as useModal,
|
|
3964
|
+
sn as useToast
|
|
3965
|
+
};
|