@moto-nrw/design-system 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,1256 @@
1
+ // src/components/Accordion/Accordion.tsx
2
+ import { useState } from "react";
3
+
4
+ // src/components/Accordion/Accordion.module.css
5
+ var Accordion_default = {};
6
+
7
+ // src/components/Accordion/Accordion.tsx
8
+ import { jsx, jsxs } from "react/jsx-runtime";
9
+ function Accordion({
10
+ label,
11
+ badge,
12
+ defaultOpen = false,
13
+ children,
14
+ className
15
+ }) {
16
+ const [isOpen, setIsOpen] = useState(defaultOpen);
17
+ return /* @__PURE__ */ jsxs("div", { className: [Accordion_default.accordion, className].filter(Boolean).join(" "), children: [
18
+ /* @__PURE__ */ jsxs("button", { type: "button", onClick: () => setIsOpen((prev) => !prev), className: Accordion_default.trigger, children: [
19
+ /* @__PURE__ */ jsxs("span", { className: Accordion_default.label, children: [
20
+ label,
21
+ badge && /* @__PURE__ */ jsx("span", { className: Accordion_default.badge, children: badge })
22
+ ] }),
23
+ /* @__PURE__ */ jsx(
24
+ "svg",
25
+ {
26
+ className: [Accordion_default.chevron, isOpen && Accordion_default.chevronOpen].filter(Boolean).join(" "),
27
+ width: "16",
28
+ height: "16",
29
+ fill: "none",
30
+ viewBox: "0 0 24 24",
31
+ stroke: "currentColor",
32
+ children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 9l-7 7-7-7" })
33
+ }
34
+ )
35
+ ] }),
36
+ /* @__PURE__ */ jsx(
37
+ "div",
38
+ {
39
+ className: [Accordion_default.content, isOpen ? Accordion_default.contentOpen : Accordion_default.contentClosed].join(" "),
40
+ children: /* @__PURE__ */ jsx("div", { className: Accordion_default.contentInner, children })
41
+ }
42
+ )
43
+ ] });
44
+ }
45
+
46
+ // src/components/Alert/Alert.module.css
47
+ var Alert_default = {};
48
+
49
+ // src/components/Alert/Alert.tsx
50
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
51
+ var icons = {
52
+ error: /* @__PURE__ */ jsx2("svg", { width: "20", height: "20", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ jsx2(
53
+ "path",
54
+ {
55
+ fillRule: "evenodd",
56
+ d: "M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z",
57
+ clipRule: "evenodd"
58
+ }
59
+ ) }),
60
+ success: /* @__PURE__ */ jsx2("svg", { width: "20", height: "20", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ jsx2(
61
+ "path",
62
+ {
63
+ fillRule: "evenodd",
64
+ d: "M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z",
65
+ clipRule: "evenodd"
66
+ }
67
+ ) }),
68
+ warning: /* @__PURE__ */ jsx2("svg", { width: "20", height: "20", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ jsx2(
69
+ "path",
70
+ {
71
+ fillRule: "evenodd",
72
+ d: "M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z",
73
+ clipRule: "evenodd"
74
+ }
75
+ ) }),
76
+ info: /* @__PURE__ */ jsx2("svg", { width: "20", height: "20", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ jsx2(
77
+ "path",
78
+ {
79
+ fillRule: "evenodd",
80
+ d: "M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z",
81
+ clipRule: "evenodd"
82
+ }
83
+ ) })
84
+ };
85
+ function Alert({ type, message, className, ...props }) {
86
+ if (!message) return null;
87
+ return /* @__PURE__ */ jsxs2(
88
+ "div",
89
+ {
90
+ role: "alert",
91
+ className: [Alert_default.alert, Alert_default[type], className].filter(Boolean).join(" "),
92
+ ...props,
93
+ children: [
94
+ /* @__PURE__ */ jsx2("span", { className: Alert_default.icon, children: icons[type] }),
95
+ /* @__PURE__ */ jsx2("span", { children: message })
96
+ ]
97
+ }
98
+ );
99
+ }
100
+
101
+ // src/components/Avatar/Avatar.module.css
102
+ var Avatar_default = {};
103
+
104
+ // src/components/Avatar/Avatar.tsx
105
+ import { jsx as jsx3 } from "react/jsx-runtime";
106
+ function getInitials(name) {
107
+ const parts = name.split(" ").filter(Boolean);
108
+ if (parts.length === 0) return "?";
109
+ if (parts.length === 1) return (parts[0]?.[0] ?? "?").toUpperCase();
110
+ return ((parts[0]?.[0] ?? "") + (parts.at(-1)?.[0] ?? "")).toUpperCase();
111
+ }
112
+ function Avatar({ name, src, size = "sm", className, ...props }) {
113
+ const initials = getInitials(name);
114
+ return /* @__PURE__ */ jsx3(
115
+ "div",
116
+ {
117
+ className: [Avatar_default.avatar, Avatar_default[size], className].filter(Boolean).join(" "),
118
+ title: name,
119
+ ...props,
120
+ children: src ? /* @__PURE__ */ jsx3("img", { src, alt: name, className: Avatar_default.image }) : /* @__PURE__ */ jsx3("span", { className: Avatar_default.initials, children: initials })
121
+ }
122
+ );
123
+ }
124
+
125
+ // src/components/Badge/Badge.module.css
126
+ var Badge_default = {};
127
+
128
+ // src/components/Badge/Badge.tsx
129
+ import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
130
+ function Badge({
131
+ count,
132
+ label,
133
+ icon,
134
+ showLabel = true,
135
+ size = "md",
136
+ className,
137
+ ...props
138
+ }) {
139
+ return /* @__PURE__ */ jsxs3("div", { className: [Badge_default.badge, Badge_default[size], className].filter(Boolean).join(" "), ...props, children: [
140
+ icon && /* @__PURE__ */ jsx4("span", { className: Badge_default.icon, children: icon }),
141
+ /* @__PURE__ */ jsx4("span", { className: Badge_default.count, children: count }),
142
+ showLabel && label && /* @__PURE__ */ jsx4("span", { className: Badge_default.label, children: label })
143
+ ] });
144
+ }
145
+ function BadgeCompact({
146
+ count,
147
+ icon,
148
+ className,
149
+ ...props
150
+ }) {
151
+ return /* @__PURE__ */ jsxs3("div", { className: [Badge_default.badge, Badge_default.sm, className].filter(Boolean).join(" "), ...props, children: [
152
+ icon && /* @__PURE__ */ jsx4("span", { className: Badge_default.icon, children: icon }),
153
+ /* @__PURE__ */ jsx4("span", { className: Badge_default.count, children: count })
154
+ ] });
155
+ }
156
+
157
+ // src/components/Button/Button.module.css
158
+ var Button_default = {};
159
+
160
+ // src/components/Button/Button.tsx
161
+ import { jsx as jsx5 } from "react/jsx-runtime";
162
+ function Button({
163
+ variant = "primary",
164
+ size = "md",
165
+ isLoading = false,
166
+ loadingText = "Laden...",
167
+ className,
168
+ children,
169
+ disabled,
170
+ type = "submit",
171
+ ...props
172
+ }) {
173
+ const classNames = [Button_default.button, Button_default[variant], Button_default[size], className].filter(Boolean).join(" ");
174
+ return /* @__PURE__ */ jsx5(
175
+ "button",
176
+ {
177
+ type,
178
+ className: classNames,
179
+ disabled: disabled || isLoading,
180
+ "aria-busy": isLoading || void 0,
181
+ ...props,
182
+ children: isLoading ? loadingText : children
183
+ }
184
+ );
185
+ }
186
+
187
+ // src/components/Card/Card.module.css
188
+ var Card_default = {};
189
+
190
+ // src/components/Card/Card.tsx
191
+ import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
192
+ function Card({
193
+ variant = "default",
194
+ padding = "md",
195
+ hoverable = false,
196
+ className,
197
+ children,
198
+ ...props
199
+ }) {
200
+ const classNames = [
201
+ Card_default.card,
202
+ !hoverable && Card_default[variant],
203
+ hoverable && Card_default.hoverable,
204
+ className
205
+ ].filter(Boolean).join(" ");
206
+ const contentClass = [Card_default.cardContent, padding !== "none" && Card_default[`padding-${padding}`]].filter(Boolean).join(" ");
207
+ if (hoverable) {
208
+ return /* @__PURE__ */ jsxs4("div", { className: classNames, ...props, children: [
209
+ /* @__PURE__ */ jsx6("div", { className: Card_default.gradientOverlay }),
210
+ /* @__PURE__ */ jsx6("div", { className: Card_default.innerGlow }),
211
+ /* @__PURE__ */ jsx6("div", { className: Card_default.ringHighlight }),
212
+ /* @__PURE__ */ jsx6("div", { className: contentClass, children }),
213
+ /* @__PURE__ */ jsx6("div", { className: Card_default.glowBorder })
214
+ ] });
215
+ }
216
+ return /* @__PURE__ */ jsx6("div", { className: classNames, ...props, children: /* @__PURE__ */ jsx6("div", { className: contentClass, children }) });
217
+ }
218
+
219
+ // src/components/Checkbox/Checkbox.module.css
220
+ var Checkbox_default = {};
221
+
222
+ // src/components/Checkbox/Checkbox.tsx
223
+ import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
224
+ function Checkbox({ label, id, name, className, ...props }) {
225
+ const inputId = id || name || label.toLowerCase().replace(/\s+/g, "-");
226
+ return /* @__PURE__ */ jsxs5("label", { htmlFor: inputId, className: [Checkbox_default.wrapper, className].filter(Boolean).join(" "), children: [
227
+ /* @__PURE__ */ jsx7("input", { type: "checkbox", id: inputId, name, className: Checkbox_default.input, ...props }),
228
+ /* @__PURE__ */ jsx7("span", { className: Checkbox_default.label, children: label })
229
+ ] });
230
+ }
231
+
232
+ // src/components/Divider/Divider.module.css
233
+ var Divider_default = {};
234
+
235
+ // src/components/Divider/Divider.tsx
236
+ import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
237
+ function Divider({ spacing = "md", label, className, ...props }) {
238
+ if (label) {
239
+ return /* @__PURE__ */ jsxs6("div", { className: [Divider_default.labeled, Divider_default[spacing], className].filter(Boolean).join(" "), children: [
240
+ /* @__PURE__ */ jsx8("hr", { className: Divider_default.line, ...props }),
241
+ /* @__PURE__ */ jsx8("span", { className: Divider_default.label, children: label }),
242
+ /* @__PURE__ */ jsx8("hr", { className: Divider_default.line, ...props })
243
+ ] });
244
+ }
245
+ return /* @__PURE__ */ jsx8(
246
+ "hr",
247
+ {
248
+ className: [Divider_default.divider, Divider_default[spacing], className].filter(Boolean).join(" "),
249
+ ...props
250
+ }
251
+ );
252
+ }
253
+
254
+ // src/components/DropdownMenu/DropdownMenu.tsx
255
+ import { useCallback, useEffect, useRef, useState as useState2 } from "react";
256
+ import { createPortal } from "react-dom";
257
+
258
+ // src/components/DropdownMenu/DropdownMenu.module.css
259
+ var DropdownMenu_default = {};
260
+
261
+ // src/components/DropdownMenu/DropdownMenu.tsx
262
+ import { Fragment, jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
263
+ function DropdownMenu({ items, trigger, className }) {
264
+ const [isOpen, setIsOpen] = useState2(false);
265
+ const [position, setPosition] = useState2({ top: 0, right: 0 });
266
+ const buttonRef = useRef(null);
267
+ const menuRef = useRef(null);
268
+ const close = useCallback(() => setIsOpen(false), []);
269
+ useEffect(() => {
270
+ if (!isOpen) return;
271
+ function handleClickOutside(event) {
272
+ const target = event.target;
273
+ if (!buttonRef.current?.contains(target) && !menuRef.current?.contains(target)) {
274
+ close();
275
+ }
276
+ }
277
+ function handleScroll() {
278
+ close();
279
+ }
280
+ function handleEscape(e) {
281
+ if (e.key === "Escape") close();
282
+ }
283
+ document.addEventListener("mousedown", handleClickOutside);
284
+ window.addEventListener("scroll", handleScroll, true);
285
+ document.addEventListener("keydown", handleEscape);
286
+ return () => {
287
+ document.removeEventListener("mousedown", handleClickOutside);
288
+ window.removeEventListener("scroll", handleScroll, true);
289
+ document.removeEventListener("keydown", handleEscape);
290
+ };
291
+ }, [isOpen, close]);
292
+ const handleToggle = () => {
293
+ if (!isOpen && buttonRef.current) {
294
+ const rect = buttonRef.current.getBoundingClientRect();
295
+ setPosition({
296
+ top: rect.bottom + 4,
297
+ right: window.innerWidth - rect.right
298
+ });
299
+ }
300
+ setIsOpen((prev) => !prev);
301
+ };
302
+ const menu = isOpen && typeof document !== "undefined" && /* @__PURE__ */ jsx9(
303
+ "div",
304
+ {
305
+ ref: menuRef,
306
+ className: DropdownMenu_default.menu,
307
+ style: { top: position.top, right: position.right },
308
+ role: "menu",
309
+ children: items.map((item) => /* @__PURE__ */ jsx9(
310
+ "button",
311
+ {
312
+ type: "button",
313
+ role: "menuitem",
314
+ onClick: () => {
315
+ close();
316
+ item.onClick();
317
+ },
318
+ className: [DropdownMenu_default.menuItem, item.variant === "danger" && DropdownMenu_default.menuItemDanger].filter(Boolean).join(" "),
319
+ children: item.label
320
+ },
321
+ item.id
322
+ ))
323
+ }
324
+ );
325
+ return /* @__PURE__ */ jsxs7(Fragment, { children: [
326
+ /* @__PURE__ */ jsx9(
327
+ "button",
328
+ {
329
+ ref: buttonRef,
330
+ type: "button",
331
+ onClick: handleToggle,
332
+ className: [DropdownMenu_default.trigger, className].filter(Boolean).join(" "),
333
+ "aria-label": "Aktionen",
334
+ "aria-expanded": isOpen,
335
+ "aria-haspopup": "menu",
336
+ children: trigger || /* @__PURE__ */ jsx9("svg", { className: DropdownMenu_default.dotsIcon, fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ jsx9("path", { d: "M10 6a2 2 0 110-4 2 2 0 010 4zM10 12a2 2 0 110-4 2 2 0 010 4zM10 18a2 2 0 110-4 2 2 0 010 4z" }) })
337
+ }
338
+ ),
339
+ menu && createPortal(menu, document.body)
340
+ ] });
341
+ }
342
+
343
+ // src/components/FilterChips/FilterChips.module.css
344
+ var FilterChips_default = {};
345
+
346
+ // src/components/FilterChips/FilterChips.tsx
347
+ import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
348
+ function FilterChips({ filters, onClearAll, className, ...props }) {
349
+ if (filters.length === 0) return null;
350
+ return /* @__PURE__ */ jsxs8("div", { className: [FilterChips_default.wrapper, className].filter(Boolean).join(" "), ...props, children: [
351
+ /* @__PURE__ */ jsx10("div", { className: FilterChips_default.chips, children: filters.map((filter) => /* @__PURE__ */ jsxs8("span", { className: FilterChips_default.chip, children: [
352
+ filter.label,
353
+ /* @__PURE__ */ jsx10("button", { type: "button", onClick: filter.onRemove, className: FilterChips_default.removeButton, children: /* @__PURE__ */ jsx10("svg", { width: "12", height: "12", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx10(
354
+ "path",
355
+ {
356
+ strokeLinecap: "round",
357
+ strokeLinejoin: "round",
358
+ strokeWidth: 2,
359
+ d: "M6 18L18 6M6 6l12 12"
360
+ }
361
+ ) }) })
362
+ ] }, filter.id)) }),
363
+ onClearAll && filters.length > 1 && /* @__PURE__ */ jsx10("button", { type: "button", onClick: onClearAll, className: FilterChips_default.clearAll, children: "Alle l\xF6schen" })
364
+ ] });
365
+ }
366
+
367
+ // src/components/Input/Input.tsx
368
+ import { useState as useState3 } from "react";
369
+
370
+ // src/components/Input/Input.module.css
371
+ var Input_default = {};
372
+
373
+ // src/components/Input/Input.tsx
374
+ import { jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
375
+ function Input({ label, error, id, name, type = "text", className, ...props }) {
376
+ const [showPassword, setShowPassword] = useState3(false);
377
+ const inputId = id || name;
378
+ const isPassword = type === "password";
379
+ const resolvedType = isPassword && showPassword ? "text" : type;
380
+ return /* @__PURE__ */ jsxs9("div", { className: Input_default.wrapper, children: [
381
+ label && /* @__PURE__ */ jsx11("label", { htmlFor: inputId, className: Input_default.label, children: label }),
382
+ /* @__PURE__ */ jsxs9("div", { className: Input_default.container, children: [
383
+ /* @__PURE__ */ jsx11(
384
+ "input",
385
+ {
386
+ id: inputId,
387
+ name,
388
+ type: resolvedType,
389
+ className: [
390
+ Input_default.input,
391
+ isPassword && Input_default.hasToggle,
392
+ error && Input_default.error,
393
+ className
394
+ ].filter(Boolean).join(" "),
395
+ "aria-invalid": error ? "true" : void 0,
396
+ "aria-describedby": error ? `${inputId}-error` : void 0,
397
+ ...props
398
+ }
399
+ ),
400
+ isPassword && /* @__PURE__ */ jsx11(
401
+ "button",
402
+ {
403
+ type: "button",
404
+ onClick: () => setShowPassword((prev) => !prev),
405
+ className: Input_default.toggle,
406
+ "aria-label": showPassword ? "Passwort verbergen" : "Passwort anzeigen",
407
+ tabIndex: -1,
408
+ children: showPassword ? /* @__PURE__ */ jsx11("svg", { width: "20", height: "20", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx11(
409
+ "path",
410
+ {
411
+ strokeLinecap: "round",
412
+ strokeLinejoin: "round",
413
+ strokeWidth: 2,
414
+ d: "M13.875 18.825A10.05 10.05 0 0112 19c-4.478 0-8.268-2.943-9.543-7a9.97 9.97 0 011.563-3.029m5.858.908a3 3 0 114.243 4.243M9.878 9.878l4.242 4.242M9.88 9.88l-3.29-3.29m7.532 7.532l3.29 3.29M3 3l3.59 3.59m0 0A9.953 9.953 0 0112 5c4.478 0 8.268 2.943 9.543 7a10.025 10.025 0 01-4.132 5.411m0 0L21 21"
415
+ }
416
+ ) }) : /* @__PURE__ */ jsxs9("svg", { width: "20", height: "20", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: [
417
+ /* @__PURE__ */ jsx11(
418
+ "path",
419
+ {
420
+ strokeLinecap: "round",
421
+ strokeLinejoin: "round",
422
+ strokeWidth: 2,
423
+ d: "M15 12a3 3 0 11-6 0 3 3 0 016 0z"
424
+ }
425
+ ),
426
+ /* @__PURE__ */ jsx11(
427
+ "path",
428
+ {
429
+ strokeLinecap: "round",
430
+ strokeLinejoin: "round",
431
+ strokeWidth: 2,
432
+ d: "M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"
433
+ }
434
+ )
435
+ ] })
436
+ }
437
+ )
438
+ ] }),
439
+ error && /* @__PURE__ */ jsx11("p", { id: `${inputId}-error`, className: Input_default.errorText, children: error })
440
+ ] });
441
+ }
442
+
443
+ // src/components/Logo/Logo.tsx
444
+ import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
445
+ function Logo({ size = 48, ...props }) {
446
+ return /* @__PURE__ */ jsx12(
447
+ "svg",
448
+ {
449
+ width: size,
450
+ height: size,
451
+ viewBox: "0 0 1000 1000",
452
+ fill: "none",
453
+ "aria-label": "Ganztagshelden Logo",
454
+ ...props,
455
+ children: /* @__PURE__ */ jsxs10("g", { transform: "matrix(1.62384,0,0,1.62384,-670.097018,-377.993255)", children: [
456
+ /* @__PURE__ */ jsx12(
457
+ "path",
458
+ {
459
+ d: "M659.306,666.563C647.321,692.452 643.608,697.805 636.105,707.186C597.15,755.887 537.182,756.845 535.652,756.159C520.635,749.432 541.639,734.294 543.087,720.432C546.681,686.029 515.354,694.397 490.973,657.204C474.084,631.441 470.729,569.063 491.533,580.44C566.83,621.619 610.108,565.941 697.497,581.514C795.809,599.034 828.378,545.138 873.613,499.611C886.943,486.194 921.218,489.412 905.57,533.525C884.114,594.015 824.679,638.112 824.916,640.467C825.254,643.83 825.708,647.181 826.036,650.545C841.184,805.69 775.341,869.784 748.516,842.485C733.986,827.697 766.215,763.869 753.18,746.69C742.331,732.393 727.791,767.884 690.115,801.076C617.879,864.714 605.932,819.074 607.847,805.541C609.887,791.128 663.09,752.991 674.077,688.423C677.562,667.944 669.794,667.148 667.332,663.505C665.729,661.133 659.929,665.972 659.306,666.563Z",
460
+ fill: "var(--color-steel-800, #1E293B)"
461
+ }
462
+ ),
463
+ /* @__PURE__ */ jsx12(
464
+ "path",
465
+ {
466
+ d: "M675.584,684.76C676.835,613.868 598.89,738.438 567.488,699.03C544.801,670.559 676.869,576.383 715.532,582.995C744.492,587.948 775.313,577.886 789.684,572.171C791.809,570.862 793.873,569.676 795.866,568.627C814.646,558.742 857.526,515.802 873.613,499.611C886.943,486.194 921.218,489.412 905.57,533.525C884.114,594.015 824.679,638.112 824.916,640.467C825.254,643.83 825.708,647.181 826.036,650.545C841.184,805.69 775.341,869.784 748.516,842.485C733.986,827.697 766.215,763.869 753.18,746.69C742.331,732.393 727.791,767.884 690.115,801.076C617.879,864.714 605.932,819.074 607.847,805.541C609.887,791.128 663.09,752.991 674.077,688.423C674.245,687.434 674.757,686.206 675.584,684.76Z",
467
+ fill: "var(--color-steel-500, #64748B)"
468
+ }
469
+ ),
470
+ /* @__PURE__ */ jsx12(
471
+ "path",
472
+ {
473
+ d: "M460.76,425.665C465.048,418.094 676.602,255.297 689.716,245.799C722.985,221.705 734.948,230.838 791.173,274.938C956.769,404.821 957.228,404.054 971.138,415.929C994.202,435.618 980.079,457.145 973.404,463.396C950.46,484.884 936.954,468.134 867.775,414.13C729.691,306.338 729.459,303.94 718.557,304.907C707.569,305.88 567.819,420.024 512.203,461.094C468.741,493.188 448.741,446.89 460.76,425.665Z",
474
+ fill: "var(--color-steel-600, #475569)"
475
+ }
476
+ ),
477
+ /* @__PURE__ */ jsx12(
478
+ "path",
479
+ {
480
+ d: "M706.539,565.374C599.871,517.702 661.839,386.507 747.483,403.592C856.658,425.371 827.324,597.116 706.539,565.374Z",
481
+ fill: "var(--color-steel-400, #94A3B8)"
482
+ }
483
+ )
484
+ ] })
485
+ }
486
+ );
487
+ }
488
+
489
+ // src/components/Modal/Modal.tsx
490
+ import { useCallback as useCallback2, useEffect as useEffect2, useRef as useRef2, useState as useState4 } from "react";
491
+ import { createPortal as createPortal2 } from "react-dom";
492
+
493
+ // src/components/Modal/Modal.module.css
494
+ var Modal_default = {};
495
+
496
+ // src/components/Modal/Modal.tsx
497
+ import { Fragment as Fragment2, jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
498
+ function Modal({ isOpen, onClose, title, children, footer }) {
499
+ const [isAnimating, setIsAnimating] = useState4(false);
500
+ const [isExiting, setIsExiting] = useState4(false);
501
+ const onCloseRef = useRef2(onClose);
502
+ onCloseRef.current = onClose;
503
+ const handleClose = useCallback2(() => {
504
+ setIsExiting(true);
505
+ setIsAnimating(false);
506
+ setTimeout(() => {
507
+ onCloseRef.current();
508
+ }, 250);
509
+ }, []);
510
+ useEffect2(() => {
511
+ if (!isOpen) {
512
+ setIsAnimating(false);
513
+ setIsExiting(false);
514
+ return;
515
+ }
516
+ const handleEscape = (e) => {
517
+ if (e.key === "Escape") handleClose();
518
+ };
519
+ document.addEventListener("keydown", handleEscape);
520
+ document.body.style.overflow = "hidden";
521
+ const timer = setTimeout(() => setIsAnimating(true), 10);
522
+ return () => {
523
+ document.removeEventListener("keydown", handleEscape);
524
+ document.body.style.overflow = "";
525
+ clearTimeout(timer);
526
+ };
527
+ }, [isOpen, handleClose]);
528
+ if (!isOpen) return null;
529
+ const entering = isAnimating && !isExiting;
530
+ const modalContent = /* @__PURE__ */ jsxs11("div", { className: Modal_default.overlay, children: [
531
+ /* @__PURE__ */ jsx13(
532
+ "button",
533
+ {
534
+ type: "button",
535
+ onClick: handleClose,
536
+ className: [Modal_default.backdrop, entering && Modal_default.backdropVisible].filter(Boolean).join(" "),
537
+ "aria-label": "Hintergrund - Klicken zum Schlie\xDFen"
538
+ }
539
+ ),
540
+ /* @__PURE__ */ jsxs11(
541
+ "div",
542
+ {
543
+ className: [Modal_default.dialog, entering ? Modal_default.dialogEnter : Modal_default.dialogExit].join(" "),
544
+ role: "dialog",
545
+ "aria-modal": "true",
546
+ "aria-label": title || void 0,
547
+ children: [
548
+ title ? /* @__PURE__ */ jsxs11("div", { className: Modal_default.header, children: [
549
+ /* @__PURE__ */ jsx13("h3", { className: Modal_default.title, children: title }),
550
+ /* @__PURE__ */ jsx13(CloseButton, { onClick: handleClose })
551
+ ] }) : /* @__PURE__ */ jsx13("div", { className: Modal_default.closeAbsolute, children: /* @__PURE__ */ jsx13(CloseButton, { onClick: handleClose }) }),
552
+ /* @__PURE__ */ jsx13(
553
+ "div",
554
+ {
555
+ className: [Modal_default.content, entering && Modal_default.contentVisible].filter(Boolean).join(" "),
556
+ children
557
+ }
558
+ ),
559
+ footer && /* @__PURE__ */ jsx13("div", { className: Modal_default.footer, children: footer })
560
+ ]
561
+ }
562
+ )
563
+ ] });
564
+ if (typeof document !== "undefined") {
565
+ return createPortal2(modalContent, document.body);
566
+ }
567
+ return modalContent;
568
+ }
569
+ function ConfirmationModal({
570
+ isOpen,
571
+ onClose,
572
+ onConfirm,
573
+ title,
574
+ children,
575
+ confirmText = "Best\xE4tigen",
576
+ cancelText = "Abbrechen",
577
+ isConfirmLoading = false,
578
+ isConfirmDisabled = false,
579
+ variant = "primary"
580
+ }) {
581
+ const confirmClass = variant === "danger" ? Modal_default.confirmDanger : Modal_default.confirmPrimary;
582
+ const footer = /* @__PURE__ */ jsxs11(Fragment2, { children: [
583
+ /* @__PURE__ */ jsx13("button", { type: "button", onClick: onClose, className: Modal_default.cancelButton, children: cancelText }),
584
+ /* @__PURE__ */ jsx13(
585
+ "button",
586
+ {
587
+ type: "button",
588
+ onClick: onConfirm,
589
+ disabled: isConfirmLoading || isConfirmDisabled,
590
+ className: [Modal_default.confirmButton, confirmClass].join(" "),
591
+ children: isConfirmLoading ? /* @__PURE__ */ jsxs11("span", { className: Modal_default.confirmLoading, children: [
592
+ /* @__PURE__ */ jsxs11("svg", { className: Modal_default.confirmSpinner, fill: "none", viewBox: "0 0 24 24", children: [
593
+ /* @__PURE__ */ jsx13("circle", { opacity: 0.25, cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
594
+ /* @__PURE__ */ jsx13(
595
+ "path",
596
+ {
597
+ opacity: 0.75,
598
+ fill: "currentColor",
599
+ d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
600
+ }
601
+ )
602
+ ] }),
603
+ "Wird geladen..."
604
+ ] }) : confirmText
605
+ }
606
+ )
607
+ ] });
608
+ return /* @__PURE__ */ jsx13(Modal, { isOpen, onClose, title, footer, children });
609
+ }
610
+ function CloseButton({ onClick }) {
611
+ return /* @__PURE__ */ jsx13(
612
+ "button",
613
+ {
614
+ type: "button",
615
+ onClick,
616
+ className: Modal_default.closeButton,
617
+ "aria-label": "Modal schlie\xDFen",
618
+ children: /* @__PURE__ */ jsx13(
619
+ "svg",
620
+ {
621
+ className: Modal_default.closeIcon,
622
+ width: "20",
623
+ height: "20",
624
+ fill: "none",
625
+ viewBox: "0 0 24 24",
626
+ stroke: "currentColor",
627
+ strokeWidth: 2,
628
+ children: /* @__PURE__ */ jsx13("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 18L18 6M6 6l12 12" })
629
+ }
630
+ )
631
+ }
632
+ );
633
+ }
634
+
635
+ // src/components/Pill/Pill.module.css
636
+ var Pill_default = {};
637
+
638
+ // src/components/Pill/Pill.tsx
639
+ import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
640
+ function Pill({
641
+ label,
642
+ color = "gray",
643
+ variant = "solid",
644
+ size = "md",
645
+ dot = true,
646
+ className,
647
+ ...props
648
+ }) {
649
+ return /* @__PURE__ */ jsxs12(
650
+ "span",
651
+ {
652
+ className: [Pill_default.pill, Pill_default[`${variant}-${color}`], Pill_default[size], className].filter(Boolean).join(" "),
653
+ ...props,
654
+ children: [
655
+ dot && /* @__PURE__ */ jsx14("span", { className: [Pill_default.dot, Pill_default[`dot-${size}`]].join(" ") }),
656
+ label
657
+ ]
658
+ }
659
+ );
660
+ }
661
+
662
+ // src/components/Radio/Radio.module.css
663
+ var Radio_default = {};
664
+
665
+ // src/components/Radio/Radio.tsx
666
+ import { jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
667
+ function Radio({ label, id, name, className, ...props }) {
668
+ const inputId = id || `${name}-${label.toLowerCase().replace(/\s+/g, "-")}`;
669
+ return /* @__PURE__ */ jsxs13("label", { htmlFor: inputId, className: [Radio_default.wrapper, className].filter(Boolean).join(" "), children: [
670
+ /* @__PURE__ */ jsx15("input", { type: "radio", id: inputId, name, className: Radio_default.input, ...props }),
671
+ /* @__PURE__ */ jsx15("span", { className: Radio_default.label, children: label })
672
+ ] });
673
+ }
674
+
675
+ // src/components/SearchBar/SearchBar.module.css
676
+ var SearchBar_default = {};
677
+
678
+ // src/components/SearchBar/SearchBar.tsx
679
+ import { jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
680
+ function SearchBar({
681
+ value,
682
+ onChange,
683
+ onClear,
684
+ placeholder = "Name suchen...",
685
+ size = "md",
686
+ className,
687
+ ...props
688
+ }) {
689
+ return /* @__PURE__ */ jsxs14("div", { className: [SearchBar_default.wrapper, className].filter(Boolean).join(" "), children: [
690
+ /* @__PURE__ */ jsx16(
691
+ "svg",
692
+ {
693
+ className: [SearchBar_default.searchIcon, SearchBar_default[`icon-${size}`]].join(" "),
694
+ fill: "none",
695
+ viewBox: "0 0 24 24",
696
+ stroke: "currentColor",
697
+ children: /* @__PURE__ */ jsx16(
698
+ "path",
699
+ {
700
+ strokeLinecap: "round",
701
+ strokeLinejoin: "round",
702
+ strokeWidth: 2,
703
+ d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
704
+ }
705
+ )
706
+ }
707
+ ),
708
+ /* @__PURE__ */ jsx16(
709
+ "input",
710
+ {
711
+ type: "text",
712
+ placeholder,
713
+ value,
714
+ onChange: (e) => onChange(e.target.value),
715
+ className: [SearchBar_default.input, SearchBar_default[size]].join(" "),
716
+ ...props
717
+ }
718
+ ),
719
+ value && /* @__PURE__ */ jsx16(
720
+ "button",
721
+ {
722
+ type: "button",
723
+ onClick: () => {
724
+ onChange("");
725
+ onClear?.();
726
+ },
727
+ className: SearchBar_default.clearButton,
728
+ children: /* @__PURE__ */ jsx16(
729
+ "svg",
730
+ {
731
+ className: [SearchBar_default.clearIcon, SearchBar_default[`icon-${size}`]].join(" "),
732
+ fill: "none",
733
+ viewBox: "0 0 24 24",
734
+ stroke: "currentColor",
735
+ children: /* @__PURE__ */ jsx16(
736
+ "path",
737
+ {
738
+ strokeLinecap: "round",
739
+ strokeLinejoin: "round",
740
+ strokeWidth: 2,
741
+ d: "M6 18L18 6M6 6l12 12"
742
+ }
743
+ )
744
+ }
745
+ )
746
+ }
747
+ )
748
+ ] });
749
+ }
750
+
751
+ // src/components/Select/Select.module.css
752
+ var Select_default = {};
753
+
754
+ // src/components/Select/Select.tsx
755
+ import { jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
756
+ function Select({ label, placeholder, options, id, className, ...props }) {
757
+ const selectId = id || (label ? label.toLowerCase().replace(/\s+/g, "-") : void 0);
758
+ return /* @__PURE__ */ jsxs15("div", { className: Select_default.wrapper, children: [
759
+ label && /* @__PURE__ */ jsx17("label", { htmlFor: selectId, className: Select_default.label, children: label }),
760
+ /* @__PURE__ */ jsxs15("div", { className: Select_default.container, children: [
761
+ /* @__PURE__ */ jsxs15(
762
+ "select",
763
+ {
764
+ id: selectId,
765
+ className: [Select_default.select, className].filter(Boolean).join(" "),
766
+ ...props,
767
+ children: [
768
+ placeholder && /* @__PURE__ */ jsx17("option", { value: "", disabled: props.required, children: placeholder }),
769
+ options.map((option) => /* @__PURE__ */ jsx17("option", { value: option.value, disabled: option.disabled, children: option.label }, option.value))
770
+ ]
771
+ }
772
+ ),
773
+ /* @__PURE__ */ jsx17("div", { className: Select_default.chevron, "aria-hidden": "true", children: /* @__PURE__ */ jsx17("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", children: /* @__PURE__ */ jsx17("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 9l-7 7-7-7" }) }) })
774
+ ] })
775
+ ] });
776
+ }
777
+
778
+ // src/components/Skeleton/Skeleton.module.css
779
+ var Skeleton_default = {};
780
+
781
+ // src/components/Skeleton/Skeleton.tsx
782
+ import { jsx as jsx18 } from "react/jsx-runtime";
783
+ function Skeleton({
784
+ width,
785
+ height = 16,
786
+ circle = false,
787
+ borderRadius,
788
+ count = 1,
789
+ gap = 8,
790
+ className,
791
+ style,
792
+ ...props
793
+ }) {
794
+ const resolvedRadius = circle ? "9999px" : borderRadius != null ? typeof borderRadius === "number" ? `${borderRadius}px` : borderRadius : "var(--radius-md)";
795
+ const itemStyle = {
796
+ width: circle ? height : width,
797
+ height,
798
+ borderRadius: resolvedRadius,
799
+ ...style
800
+ };
801
+ if (count === 1) {
802
+ return /* @__PURE__ */ jsx18(
803
+ "div",
804
+ {
805
+ className: [Skeleton_default.skeleton, className].filter(Boolean).join(" "),
806
+ style: itemStyle,
807
+ "aria-hidden": "true",
808
+ ...props
809
+ }
810
+ );
811
+ }
812
+ return /* @__PURE__ */ jsx18("div", { className: Skeleton_default.group, style: { gap }, "aria-hidden": "true", ...props, children: Array.from({ length: count }, (_, i) => /* @__PURE__ */ jsx18(
813
+ "div",
814
+ {
815
+ className: [Skeleton_default.skeleton, className].filter(Boolean).join(" "),
816
+ style: itemStyle
817
+ },
818
+ `skeleton-${i}`
819
+ )) });
820
+ }
821
+
822
+ // src/components/Spinner/Spinner.module.css
823
+ var Spinner_default = {};
824
+
825
+ // src/components/Spinner/Spinner.tsx
826
+ import { jsx as jsx19, jsxs as jsxs16 } from "react/jsx-runtime";
827
+ var sizes = { sm: 20, md: 32, lg: 48 };
828
+ var strokes = { sm: 2.5, md: 3, lg: 3.5 };
829
+ function Spinner({ size = "md", label, className, ...props }) {
830
+ const s = sizes[size];
831
+ const stroke = strokes[size];
832
+ const r = (s - stroke) / 2;
833
+ const circumference = 2 * Math.PI * r;
834
+ return /* @__PURE__ */ jsxs16("div", { className: [Spinner_default.wrapper, className].filter(Boolean).join(" "), role: "status", ...props, children: [
835
+ /* @__PURE__ */ jsxs16("svg", { width: s, height: s, viewBox: `0 0 ${s} ${s}`, className: Spinner_default.svg, children: [
836
+ /* @__PURE__ */ jsx19(
837
+ "circle",
838
+ {
839
+ cx: s / 2,
840
+ cy: s / 2,
841
+ r,
842
+ fill: "none",
843
+ stroke: "var(--semantic-color-border-default)",
844
+ strokeWidth: stroke
845
+ }
846
+ ),
847
+ /* @__PURE__ */ jsx19(
848
+ "circle",
849
+ {
850
+ cx: s / 2,
851
+ cy: s / 2,
852
+ r,
853
+ fill: "none",
854
+ stroke: "var(--semantic-color-brand-primary)",
855
+ strokeWidth: stroke,
856
+ strokeLinecap: "round",
857
+ strokeDasharray: `${circumference * 0.3} ${circumference * 0.7}`
858
+ }
859
+ )
860
+ ] }),
861
+ label && /* @__PURE__ */ jsx19("p", { className: Spinner_default.label, children: label }),
862
+ /* @__PURE__ */ jsx19("span", { className: Spinner_default.srOnly, children: "Laden..." })
863
+ ] });
864
+ }
865
+
866
+ // src/components/StatusDot/StatusDot.module.css
867
+ var StatusDot_default = {};
868
+
869
+ // src/components/StatusDot/StatusDot.tsx
870
+ import { jsx as jsx20 } from "react/jsx-runtime";
871
+ function StatusDot({
872
+ color,
873
+ tooltip,
874
+ size = "sm",
875
+ pulse,
876
+ className,
877
+ ...props
878
+ }) {
879
+ const shouldPulse = pulse ?? color === "green";
880
+ return /* @__PURE__ */ jsx20(
881
+ "div",
882
+ {
883
+ className: [StatusDot_default.dot, StatusDot_default[color], StatusDot_default[size], shouldPulse && StatusDot_default.pulse, className].filter(Boolean).join(" "),
884
+ title: tooltip,
885
+ ...props
886
+ }
887
+ );
888
+ }
889
+
890
+ // src/components/Tabs/Tabs.tsx
891
+ import { useCallback as useCallback3, useEffect as useEffect3, useMemo, useRef as useRef3, useState as useState5 } from "react";
892
+
893
+ // src/components/Tabs/Tabs.module.css
894
+ var Tabs_default = {};
895
+
896
+ // src/components/Tabs/Tabs.tsx
897
+ import { jsx as jsx21, jsxs as jsxs17 } from "react/jsx-runtime";
898
+ function Tabs({ items, activeTab, onTabChange, className }) {
899
+ const tabRefs = useRef3([]);
900
+ const scrollRef = useRef3(null);
901
+ const [indicatorStyle, setIndicatorStyle] = useState5({ width: 0, left: 0 });
902
+ const [canScrollLeft, setCanScrollLeft] = useState5(false);
903
+ const [canScrollRight, setCanScrollRight] = useState5(false);
904
+ const showMobileDropdown = items.length >= 2;
905
+ const activeIndex = useMemo(
906
+ () => items.findIndex((item) => item.id === activeTab),
907
+ [items, activeTab]
908
+ );
909
+ const activeLabel = items[activeIndex]?.label ?? "";
910
+ const updateScrollState = useCallback3(() => {
911
+ const el = scrollRef.current;
912
+ if (!el) return;
913
+ setCanScrollLeft(el.scrollLeft > 0);
914
+ setCanScrollRight(el.scrollLeft + el.clientWidth < el.scrollWidth - 1);
915
+ }, []);
916
+ const updateIndicator = useCallback3(() => {
917
+ const activeTabElement = tabRefs.current[activeIndex];
918
+ if (activeTabElement && activeTabElement.offsetWidth > 0) {
919
+ setIndicatorStyle({
920
+ left: activeTabElement.offsetLeft,
921
+ width: activeTabElement.offsetWidth
922
+ });
923
+ }
924
+ }, [activeIndex]);
925
+ useEffect3(() => {
926
+ updateIndicator();
927
+ const activeTabElement = tabRefs.current[activeIndex];
928
+ if (activeTabElement && scrollRef.current) {
929
+ const container = scrollRef.current;
930
+ const tabLeft = activeTabElement.offsetLeft;
931
+ const tabRight = tabLeft + activeTabElement.offsetWidth;
932
+ const containerLeft = container.scrollLeft;
933
+ const containerRight = containerLeft + container.clientWidth;
934
+ if (tabLeft < containerLeft) {
935
+ container.scrollTo({ left: tabLeft - 16, behavior: "smooth" });
936
+ } else if (tabRight > containerRight) {
937
+ container.scrollTo({
938
+ left: tabRight - container.clientWidth + 16,
939
+ behavior: "smooth"
940
+ });
941
+ }
942
+ }
943
+ }, [activeIndex, updateIndicator]);
944
+ useEffect3(() => {
945
+ updateScrollState();
946
+ updateIndicator();
947
+ const el = scrollRef.current;
948
+ if (!el) return;
949
+ el.addEventListener("scroll", updateScrollState, { passive: true });
950
+ const observer = new ResizeObserver(() => {
951
+ updateScrollState();
952
+ updateIndicator();
953
+ });
954
+ observer.observe(el);
955
+ return () => {
956
+ el.removeEventListener("scroll", updateScrollState);
957
+ observer.disconnect();
958
+ };
959
+ }, [updateScrollState, updateIndicator]);
960
+ return /* @__PURE__ */ jsxs17("div", { className: [Tabs_default.wrapper, className].filter(Boolean).join(" "), children: [
961
+ showMobileDropdown && /* @__PURE__ */ jsx21(
962
+ MobileTabDropdown,
963
+ {
964
+ items,
965
+ activeTab,
966
+ activeLabel,
967
+ onTabChange
968
+ }
969
+ ),
970
+ /* @__PURE__ */ jsxs17(
971
+ "div",
972
+ {
973
+ className: [Tabs_default.tabsContainer, showMobileDropdown && Tabs_default.hiddenMobile].filter(Boolean).join(" "),
974
+ children: [
975
+ canScrollLeft && /* @__PURE__ */ jsx21("div", { className: Tabs_default.fadeLeft }),
976
+ /* @__PURE__ */ jsxs17("div", { ref: scrollRef, className: Tabs_default.scrollable, children: [
977
+ items.map((tab, index) => /* @__PURE__ */ jsx21(
978
+ "button",
979
+ {
980
+ ref: (el) => {
981
+ tabRefs.current[index] = el;
982
+ },
983
+ type: "button",
984
+ onClick: () => onTabChange(tab.id),
985
+ className: [
986
+ Tabs_default.tab,
987
+ activeTab === tab.id ? Tabs_default.tabActive : Tabs_default.tabInactive
988
+ ].join(" "),
989
+ children: /* @__PURE__ */ jsx21("span", { className: Tabs_default.tabLabel, children: tab.label })
990
+ },
991
+ tab.id
992
+ )),
993
+ /* @__PURE__ */ jsx21(
994
+ "div",
995
+ {
996
+ className: Tabs_default.indicator,
997
+ style: {
998
+ left: `${indicatorStyle.left}px`,
999
+ width: `${indicatorStyle.width}px`
1000
+ }
1001
+ }
1002
+ )
1003
+ ] }),
1004
+ canScrollRight && /* @__PURE__ */ jsx21("div", { className: Tabs_default.fadeRight })
1005
+ ]
1006
+ }
1007
+ )
1008
+ ] });
1009
+ }
1010
+ function MobileTabDropdown({
1011
+ items,
1012
+ activeTab,
1013
+ activeLabel,
1014
+ onTabChange
1015
+ }) {
1016
+ const [isOpen, setIsOpen] = useState5(false);
1017
+ const dropdownRef = useRef3(null);
1018
+ useEffect3(() => {
1019
+ function handleClickOutside(event) {
1020
+ if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
1021
+ setIsOpen(false);
1022
+ }
1023
+ }
1024
+ document.addEventListener("mousedown", handleClickOutside);
1025
+ return () => document.removeEventListener("mousedown", handleClickOutside);
1026
+ }, []);
1027
+ return /* @__PURE__ */ jsxs17("div", { className: Tabs_default.mobileDropdown, ref: dropdownRef, children: [
1028
+ /* @__PURE__ */ jsxs17(
1029
+ "button",
1030
+ {
1031
+ type: "button",
1032
+ onClick: () => setIsOpen(!isOpen),
1033
+ className: [Tabs_default.mobileToggle, isOpen && Tabs_default.mobileToggleOpen].filter(Boolean).join(" "),
1034
+ children: [
1035
+ /* @__PURE__ */ jsx21("span", { children: activeLabel }),
1036
+ /* @__PURE__ */ jsx21(
1037
+ "svg",
1038
+ {
1039
+ className: [Tabs_default.mobileChevron, isOpen && Tabs_default.mobileChevronOpen].filter(Boolean).join(" "),
1040
+ width: "20",
1041
+ height: "20",
1042
+ fill: "none",
1043
+ viewBox: "0 0 24 24",
1044
+ stroke: "currentColor",
1045
+ children: /* @__PURE__ */ jsx21("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 9l-7 7-7-7" })
1046
+ }
1047
+ )
1048
+ ]
1049
+ }
1050
+ ),
1051
+ isOpen && /* @__PURE__ */ jsx21("div", { className: Tabs_default.mobileMenu, children: items.map((item) => /* @__PURE__ */ jsx21(
1052
+ "button",
1053
+ {
1054
+ type: "button",
1055
+ onClick: () => {
1056
+ onTabChange(item.id);
1057
+ setIsOpen(false);
1058
+ },
1059
+ className: [
1060
+ Tabs_default.mobileMenuItem,
1061
+ item.id === activeTab && Tabs_default.mobileMenuItemActive
1062
+ ].filter(Boolean).join(" "),
1063
+ children: item.label
1064
+ },
1065
+ item.id
1066
+ )) })
1067
+ ] });
1068
+ }
1069
+
1070
+ // src/components/Textarea/Textarea.module.css
1071
+ var Textarea_default = {};
1072
+
1073
+ // src/components/Textarea/Textarea.tsx
1074
+ import { jsx as jsx22, jsxs as jsxs18 } from "react/jsx-runtime";
1075
+ function Textarea({ label, error, id, name, rows = 4, className, ...props }) {
1076
+ const textareaId = id || name;
1077
+ return /* @__PURE__ */ jsxs18("div", { className: Textarea_default.wrapper, children: [
1078
+ label && /* @__PURE__ */ jsx22("label", { htmlFor: textareaId, className: Textarea_default.label, children: label }),
1079
+ /* @__PURE__ */ jsx22(
1080
+ "textarea",
1081
+ {
1082
+ id: textareaId,
1083
+ name,
1084
+ rows,
1085
+ className: [Textarea_default.textarea, error && Textarea_default.error, className].filter(Boolean).join(" "),
1086
+ "aria-invalid": error ? "true" : void 0,
1087
+ "aria-describedby": error ? `${textareaId}-error` : void 0,
1088
+ ...props
1089
+ }
1090
+ ),
1091
+ error && /* @__PURE__ */ jsx22("p", { id: `${textareaId}-error`, className: Textarea_default.errorText, children: error })
1092
+ ] });
1093
+ }
1094
+
1095
+ // src/components/Toast/Toast.tsx
1096
+ import { useCallback as useCallback4, useEffect as useEffect4, useState as useState6 } from "react";
1097
+ import { createPortal as createPortal3 } from "react-dom";
1098
+
1099
+ // src/components/Toast/Toast.module.css
1100
+ var Toast_default = {};
1101
+
1102
+ // src/components/Toast/Toast.tsx
1103
+ import { jsx as jsx23, jsxs as jsxs19 } from "react/jsx-runtime";
1104
+ var icons2 = {
1105
+ success: /* @__PURE__ */ jsx23(
1106
+ "svg",
1107
+ {
1108
+ width: "18",
1109
+ height: "18",
1110
+ fill: "none",
1111
+ viewBox: "0 0 24 24",
1112
+ stroke: "currentColor",
1113
+ strokeWidth: 2,
1114
+ children: /* @__PURE__ */ jsx23("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M5 13l4 4L19 7" })
1115
+ }
1116
+ ),
1117
+ error: /* @__PURE__ */ jsx23(
1118
+ "svg",
1119
+ {
1120
+ width: "18",
1121
+ height: "18",
1122
+ fill: "none",
1123
+ viewBox: "0 0 24 24",
1124
+ stroke: "currentColor",
1125
+ strokeWidth: 2,
1126
+ children: /* @__PURE__ */ jsx23("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 18L18 6M6 6l12 12" })
1127
+ }
1128
+ ),
1129
+ warning: /* @__PURE__ */ jsx23(
1130
+ "svg",
1131
+ {
1132
+ width: "18",
1133
+ height: "18",
1134
+ fill: "none",
1135
+ viewBox: "0 0 24 24",
1136
+ stroke: "currentColor",
1137
+ strokeWidth: 2,
1138
+ children: /* @__PURE__ */ jsx23(
1139
+ "path",
1140
+ {
1141
+ strokeLinecap: "round",
1142
+ strokeLinejoin: "round",
1143
+ d: "M12 9v2m0 4h.01M10.29 3.86l-8.58 14.57A1 1 0 002.57 20h18.86a1 1 0 00.86-1.57L13.71 3.86a1 1 0 00-1.72 0z"
1144
+ }
1145
+ )
1146
+ }
1147
+ ),
1148
+ info: /* @__PURE__ */ jsx23(
1149
+ "svg",
1150
+ {
1151
+ width: "18",
1152
+ height: "18",
1153
+ fill: "none",
1154
+ viewBox: "0 0 24 24",
1155
+ stroke: "currentColor",
1156
+ strokeWidth: 2,
1157
+ children: /* @__PURE__ */ jsx23(
1158
+ "path",
1159
+ {
1160
+ strokeLinecap: "round",
1161
+ strokeLinejoin: "round",
1162
+ d: "M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
1163
+ }
1164
+ )
1165
+ }
1166
+ )
1167
+ };
1168
+ function Toast({ type = "info", message, duration = 4e3, onClose }) {
1169
+ const [isVisible, setIsVisible] = useState6(false);
1170
+ const [isExiting, setIsExiting] = useState6(false);
1171
+ const dismiss = useCallback4(() => {
1172
+ setIsExiting(true);
1173
+ setTimeout(onClose, 200);
1174
+ }, [onClose]);
1175
+ useEffect4(() => {
1176
+ const enterTimer = setTimeout(() => setIsVisible(true), 10);
1177
+ const exitTimer = duration > 0 ? setTimeout(dismiss, duration) : void 0;
1178
+ return () => {
1179
+ clearTimeout(enterTimer);
1180
+ if (exitTimer) clearTimeout(exitTimer);
1181
+ };
1182
+ }, [duration, dismiss]);
1183
+ const content = /* @__PURE__ */ jsx23("div", { className: Toast_default.container, children: /* @__PURE__ */ jsxs19(
1184
+ "div",
1185
+ {
1186
+ className: [
1187
+ Toast_default.toast,
1188
+ Toast_default[type],
1189
+ isVisible && !isExiting ? Toast_default.enter : Toast_default.exit
1190
+ ].filter(Boolean).join(" "),
1191
+ children: [
1192
+ /* @__PURE__ */ jsx23("span", { className: Toast_default.icon, children: icons2[type] }),
1193
+ /* @__PURE__ */ jsx23("span", { className: Toast_default.message, children: message }),
1194
+ /* @__PURE__ */ jsx23("button", { type: "button", onClick: dismiss, className: Toast_default.close, "aria-label": "Schlie\xDFen", children: /* @__PURE__ */ jsx23(
1195
+ "svg",
1196
+ {
1197
+ width: "14",
1198
+ height: "14",
1199
+ fill: "none",
1200
+ viewBox: "0 0 24 24",
1201
+ stroke: "currentColor",
1202
+ strokeWidth: 2,
1203
+ children: /* @__PURE__ */ jsx23("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 18L18 6M6 6l12 12" })
1204
+ }
1205
+ ) })
1206
+ ]
1207
+ }
1208
+ ) });
1209
+ if (typeof document !== "undefined") {
1210
+ return createPortal3(content, document.body);
1211
+ }
1212
+ return content;
1213
+ }
1214
+
1215
+ // src/components/Toggle/Toggle.module.css
1216
+ var Toggle_default = {};
1217
+
1218
+ // src/components/Toggle/Toggle.tsx
1219
+ import { jsx as jsx24, jsxs as jsxs20 } from "react/jsx-runtime";
1220
+ function Toggle({ label, size = "md", id, name, className, ...props }) {
1221
+ const inputId = id || name || (label ? label.toLowerCase().replace(/\s+/g, "-") : void 0);
1222
+ return /* @__PURE__ */ jsxs20("label", { htmlFor: inputId, className: [Toggle_default.wrapper, className].filter(Boolean).join(" "), children: [
1223
+ /* @__PURE__ */ jsx24("input", { type: "checkbox", id: inputId, name, className: Toggle_default.input, ...props }),
1224
+ /* @__PURE__ */ jsx24("div", { className: [Toggle_default.track, Toggle_default[size]].join(" "), children: /* @__PURE__ */ jsx24("div", { className: Toggle_default.thumb }) }),
1225
+ label && /* @__PURE__ */ jsx24("span", { className: Toggle_default.label, children: label })
1226
+ ] });
1227
+ }
1228
+ export {
1229
+ Accordion,
1230
+ Alert,
1231
+ Avatar,
1232
+ Badge,
1233
+ BadgeCompact,
1234
+ Button,
1235
+ Card,
1236
+ Checkbox,
1237
+ ConfirmationModal,
1238
+ Divider,
1239
+ DropdownMenu,
1240
+ FilterChips,
1241
+ Input,
1242
+ Logo,
1243
+ Modal,
1244
+ Pill,
1245
+ Radio,
1246
+ SearchBar,
1247
+ Select,
1248
+ Skeleton,
1249
+ Spinner,
1250
+ StatusDot,
1251
+ Tabs,
1252
+ Textarea,
1253
+ Toast,
1254
+ Toggle
1255
+ };
1256
+ //# sourceMappingURL=index.js.map