@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.cjs ADDED
@@ -0,0 +1,1308 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ Accordion: () => Accordion,
24
+ Alert: () => Alert,
25
+ Avatar: () => Avatar,
26
+ Badge: () => Badge,
27
+ BadgeCompact: () => BadgeCompact,
28
+ Button: () => Button,
29
+ Card: () => Card,
30
+ Checkbox: () => Checkbox,
31
+ ConfirmationModal: () => ConfirmationModal,
32
+ Divider: () => Divider,
33
+ DropdownMenu: () => DropdownMenu,
34
+ FilterChips: () => FilterChips,
35
+ Input: () => Input,
36
+ Logo: () => Logo,
37
+ Modal: () => Modal,
38
+ Pill: () => Pill,
39
+ Radio: () => Radio,
40
+ SearchBar: () => SearchBar,
41
+ Select: () => Select,
42
+ Skeleton: () => Skeleton,
43
+ Spinner: () => Spinner,
44
+ StatusDot: () => StatusDot,
45
+ Tabs: () => Tabs,
46
+ Textarea: () => Textarea,
47
+ Toast: () => Toast,
48
+ Toggle: () => Toggle
49
+ });
50
+ module.exports = __toCommonJS(index_exports);
51
+
52
+ // src/components/Accordion/Accordion.tsx
53
+ var import_react = require("react");
54
+
55
+ // src/components/Accordion/Accordion.module.css
56
+ var Accordion_default = {};
57
+
58
+ // src/components/Accordion/Accordion.tsx
59
+ var import_jsx_runtime = require("react/jsx-runtime");
60
+ function Accordion({
61
+ label,
62
+ badge,
63
+ defaultOpen = false,
64
+ children,
65
+ className
66
+ }) {
67
+ const [isOpen, setIsOpen] = (0, import_react.useState)(defaultOpen);
68
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: [Accordion_default.accordion, className].filter(Boolean).join(" "), children: [
69
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", { type: "button", onClick: () => setIsOpen((prev) => !prev), className: Accordion_default.trigger, children: [
70
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: Accordion_default.label, children: [
71
+ label,
72
+ badge && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: Accordion_default.badge, children: badge })
73
+ ] }),
74
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
75
+ "svg",
76
+ {
77
+ className: [Accordion_default.chevron, isOpen && Accordion_default.chevronOpen].filter(Boolean).join(" "),
78
+ width: "16",
79
+ height: "16",
80
+ fill: "none",
81
+ viewBox: "0 0 24 24",
82
+ stroke: "currentColor",
83
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 9l-7 7-7-7" })
84
+ }
85
+ )
86
+ ] }),
87
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
88
+ "div",
89
+ {
90
+ className: [Accordion_default.content, isOpen ? Accordion_default.contentOpen : Accordion_default.contentClosed].join(" "),
91
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: Accordion_default.contentInner, children })
92
+ }
93
+ )
94
+ ] });
95
+ }
96
+
97
+ // src/components/Alert/Alert.module.css
98
+ var Alert_default = {};
99
+
100
+ // src/components/Alert/Alert.tsx
101
+ var import_jsx_runtime2 = require("react/jsx-runtime");
102
+ var icons = {
103
+ error: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { width: "20", height: "20", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
104
+ "path",
105
+ {
106
+ fillRule: "evenodd",
107
+ 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",
108
+ clipRule: "evenodd"
109
+ }
110
+ ) }),
111
+ success: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { width: "20", height: "20", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
112
+ "path",
113
+ {
114
+ fillRule: "evenodd",
115
+ 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",
116
+ clipRule: "evenodd"
117
+ }
118
+ ) }),
119
+ warning: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { width: "20", height: "20", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
120
+ "path",
121
+ {
122
+ fillRule: "evenodd",
123
+ 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",
124
+ clipRule: "evenodd"
125
+ }
126
+ ) }),
127
+ info: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { width: "20", height: "20", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
128
+ "path",
129
+ {
130
+ fillRule: "evenodd",
131
+ 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",
132
+ clipRule: "evenodd"
133
+ }
134
+ ) })
135
+ };
136
+ function Alert({ type, message, className, ...props }) {
137
+ if (!message) return null;
138
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
139
+ "div",
140
+ {
141
+ role: "alert",
142
+ className: [Alert_default.alert, Alert_default[type], className].filter(Boolean).join(" "),
143
+ ...props,
144
+ children: [
145
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: Alert_default.icon, children: icons[type] }),
146
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: message })
147
+ ]
148
+ }
149
+ );
150
+ }
151
+
152
+ // src/components/Avatar/Avatar.module.css
153
+ var Avatar_default = {};
154
+
155
+ // src/components/Avatar/Avatar.tsx
156
+ var import_jsx_runtime3 = require("react/jsx-runtime");
157
+ function getInitials(name) {
158
+ const parts = name.split(" ").filter(Boolean);
159
+ if (parts.length === 0) return "?";
160
+ if (parts.length === 1) return (parts[0]?.[0] ?? "?").toUpperCase();
161
+ return ((parts[0]?.[0] ?? "") + (parts.at(-1)?.[0] ?? "")).toUpperCase();
162
+ }
163
+ function Avatar({ name, src, size = "sm", className, ...props }) {
164
+ const initials = getInitials(name);
165
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
166
+ "div",
167
+ {
168
+ className: [Avatar_default.avatar, Avatar_default[size], className].filter(Boolean).join(" "),
169
+ title: name,
170
+ ...props,
171
+ children: src ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("img", { src, alt: name, className: Avatar_default.image }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: Avatar_default.initials, children: initials })
172
+ }
173
+ );
174
+ }
175
+
176
+ // src/components/Badge/Badge.module.css
177
+ var Badge_default = {};
178
+
179
+ // src/components/Badge/Badge.tsx
180
+ var import_jsx_runtime4 = require("react/jsx-runtime");
181
+ function Badge({
182
+ count,
183
+ label,
184
+ icon,
185
+ showLabel = true,
186
+ size = "md",
187
+ className,
188
+ ...props
189
+ }) {
190
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: [Badge_default.badge, Badge_default[size], className].filter(Boolean).join(" "), ...props, children: [
191
+ icon && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: Badge_default.icon, children: icon }),
192
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: Badge_default.count, children: count }),
193
+ showLabel && label && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: Badge_default.label, children: label })
194
+ ] });
195
+ }
196
+ function BadgeCompact({
197
+ count,
198
+ icon,
199
+ className,
200
+ ...props
201
+ }) {
202
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: [Badge_default.badge, Badge_default.sm, className].filter(Boolean).join(" "), ...props, children: [
203
+ icon && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: Badge_default.icon, children: icon }),
204
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: Badge_default.count, children: count })
205
+ ] });
206
+ }
207
+
208
+ // src/components/Button/Button.module.css
209
+ var Button_default = {};
210
+
211
+ // src/components/Button/Button.tsx
212
+ var import_jsx_runtime5 = require("react/jsx-runtime");
213
+ function Button({
214
+ variant = "primary",
215
+ size = "md",
216
+ isLoading = false,
217
+ loadingText = "Laden...",
218
+ className,
219
+ children,
220
+ disabled,
221
+ type = "submit",
222
+ ...props
223
+ }) {
224
+ const classNames = [Button_default.button, Button_default[variant], Button_default[size], className].filter(Boolean).join(" ");
225
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
226
+ "button",
227
+ {
228
+ type,
229
+ className: classNames,
230
+ disabled: disabled || isLoading,
231
+ "aria-busy": isLoading || void 0,
232
+ ...props,
233
+ children: isLoading ? loadingText : children
234
+ }
235
+ );
236
+ }
237
+
238
+ // src/components/Card/Card.module.css
239
+ var Card_default = {};
240
+
241
+ // src/components/Card/Card.tsx
242
+ var import_jsx_runtime6 = require("react/jsx-runtime");
243
+ function Card({
244
+ variant = "default",
245
+ padding = "md",
246
+ hoverable = false,
247
+ className,
248
+ children,
249
+ ...props
250
+ }) {
251
+ const classNames = [
252
+ Card_default.card,
253
+ !hoverable && Card_default[variant],
254
+ hoverable && Card_default.hoverable,
255
+ className
256
+ ].filter(Boolean).join(" ");
257
+ const contentClass = [Card_default.cardContent, padding !== "none" && Card_default[`padding-${padding}`]].filter(Boolean).join(" ");
258
+ if (hoverable) {
259
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: classNames, ...props, children: [
260
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: Card_default.gradientOverlay }),
261
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: Card_default.innerGlow }),
262
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: Card_default.ringHighlight }),
263
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: contentClass, children }),
264
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: Card_default.glowBorder })
265
+ ] });
266
+ }
267
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: classNames, ...props, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: contentClass, children }) });
268
+ }
269
+
270
+ // src/components/Checkbox/Checkbox.module.css
271
+ var Checkbox_default = {};
272
+
273
+ // src/components/Checkbox/Checkbox.tsx
274
+ var import_jsx_runtime7 = require("react/jsx-runtime");
275
+ function Checkbox({ label, id, name, className, ...props }) {
276
+ const inputId = id || name || label.toLowerCase().replace(/\s+/g, "-");
277
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { htmlFor: inputId, className: [Checkbox_default.wrapper, className].filter(Boolean).join(" "), children: [
278
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("input", { type: "checkbox", id: inputId, name, className: Checkbox_default.input, ...props }),
279
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: Checkbox_default.label, children: label })
280
+ ] });
281
+ }
282
+
283
+ // src/components/Divider/Divider.module.css
284
+ var Divider_default = {};
285
+
286
+ // src/components/Divider/Divider.tsx
287
+ var import_jsx_runtime8 = require("react/jsx-runtime");
288
+ function Divider({ spacing = "md", label, className, ...props }) {
289
+ if (label) {
290
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: [Divider_default.labeled, Divider_default[spacing], className].filter(Boolean).join(" "), children: [
291
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("hr", { className: Divider_default.line, ...props }),
292
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: Divider_default.label, children: label }),
293
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("hr", { className: Divider_default.line, ...props })
294
+ ] });
295
+ }
296
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
297
+ "hr",
298
+ {
299
+ className: [Divider_default.divider, Divider_default[spacing], className].filter(Boolean).join(" "),
300
+ ...props
301
+ }
302
+ );
303
+ }
304
+
305
+ // src/components/DropdownMenu/DropdownMenu.tsx
306
+ var import_react2 = require("react");
307
+ var import_react_dom = require("react-dom");
308
+
309
+ // src/components/DropdownMenu/DropdownMenu.module.css
310
+ var DropdownMenu_default = {};
311
+
312
+ // src/components/DropdownMenu/DropdownMenu.tsx
313
+ var import_jsx_runtime9 = require("react/jsx-runtime");
314
+ function DropdownMenu({ items, trigger, className }) {
315
+ const [isOpen, setIsOpen] = (0, import_react2.useState)(false);
316
+ const [position, setPosition] = (0, import_react2.useState)({ top: 0, right: 0 });
317
+ const buttonRef = (0, import_react2.useRef)(null);
318
+ const menuRef = (0, import_react2.useRef)(null);
319
+ const close = (0, import_react2.useCallback)(() => setIsOpen(false), []);
320
+ (0, import_react2.useEffect)(() => {
321
+ if (!isOpen) return;
322
+ function handleClickOutside(event) {
323
+ const target = event.target;
324
+ if (!buttonRef.current?.contains(target) && !menuRef.current?.contains(target)) {
325
+ close();
326
+ }
327
+ }
328
+ function handleScroll() {
329
+ close();
330
+ }
331
+ function handleEscape(e) {
332
+ if (e.key === "Escape") close();
333
+ }
334
+ document.addEventListener("mousedown", handleClickOutside);
335
+ window.addEventListener("scroll", handleScroll, true);
336
+ document.addEventListener("keydown", handleEscape);
337
+ return () => {
338
+ document.removeEventListener("mousedown", handleClickOutside);
339
+ window.removeEventListener("scroll", handleScroll, true);
340
+ document.removeEventListener("keydown", handleEscape);
341
+ };
342
+ }, [isOpen, close]);
343
+ const handleToggle = () => {
344
+ if (!isOpen && buttonRef.current) {
345
+ const rect = buttonRef.current.getBoundingClientRect();
346
+ setPosition({
347
+ top: rect.bottom + 4,
348
+ right: window.innerWidth - rect.right
349
+ });
350
+ }
351
+ setIsOpen((prev) => !prev);
352
+ };
353
+ const menu = isOpen && typeof document !== "undefined" && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
354
+ "div",
355
+ {
356
+ ref: menuRef,
357
+ className: DropdownMenu_default.menu,
358
+ style: { top: position.top, right: position.right },
359
+ role: "menu",
360
+ children: items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
361
+ "button",
362
+ {
363
+ type: "button",
364
+ role: "menuitem",
365
+ onClick: () => {
366
+ close();
367
+ item.onClick();
368
+ },
369
+ className: [DropdownMenu_default.menuItem, item.variant === "danger" && DropdownMenu_default.menuItemDanger].filter(Boolean).join(" "),
370
+ children: item.label
371
+ },
372
+ item.id
373
+ ))
374
+ }
375
+ );
376
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
377
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
378
+ "button",
379
+ {
380
+ ref: buttonRef,
381
+ type: "button",
382
+ onClick: handleToggle,
383
+ className: [DropdownMenu_default.trigger, className].filter(Boolean).join(" "),
384
+ "aria-label": "Aktionen",
385
+ "aria-expanded": isOpen,
386
+ "aria-haspopup": "menu",
387
+ children: trigger || /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("svg", { className: DropdownMenu_default.dotsIcon, fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("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" }) })
388
+ }
389
+ ),
390
+ menu && (0, import_react_dom.createPortal)(menu, document.body)
391
+ ] });
392
+ }
393
+
394
+ // src/components/FilterChips/FilterChips.module.css
395
+ var FilterChips_default = {};
396
+
397
+ // src/components/FilterChips/FilterChips.tsx
398
+ var import_jsx_runtime10 = require("react/jsx-runtime");
399
+ function FilterChips({ filters, onClearAll, className, ...props }) {
400
+ if (filters.length === 0) return null;
401
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: [FilterChips_default.wrapper, className].filter(Boolean).join(" "), ...props, children: [
402
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: FilterChips_default.chips, children: filters.map((filter) => /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: FilterChips_default.chip, children: [
403
+ filter.label,
404
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { type: "button", onClick: filter.onRemove, className: FilterChips_default.removeButton, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("svg", { width: "12", height: "12", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
405
+ "path",
406
+ {
407
+ strokeLinecap: "round",
408
+ strokeLinejoin: "round",
409
+ strokeWidth: 2,
410
+ d: "M6 18L18 6M6 6l12 12"
411
+ }
412
+ ) }) })
413
+ ] }, filter.id)) }),
414
+ onClearAll && filters.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { type: "button", onClick: onClearAll, className: FilterChips_default.clearAll, children: "Alle l\xF6schen" })
415
+ ] });
416
+ }
417
+
418
+ // src/components/Input/Input.tsx
419
+ var import_react3 = require("react");
420
+
421
+ // src/components/Input/Input.module.css
422
+ var Input_default = {};
423
+
424
+ // src/components/Input/Input.tsx
425
+ var import_jsx_runtime11 = require("react/jsx-runtime");
426
+ function Input({ label, error, id, name, type = "text", className, ...props }) {
427
+ const [showPassword, setShowPassword] = (0, import_react3.useState)(false);
428
+ const inputId = id || name;
429
+ const isPassword = type === "password";
430
+ const resolvedType = isPassword && showPassword ? "text" : type;
431
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: Input_default.wrapper, children: [
432
+ label && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("label", { htmlFor: inputId, className: Input_default.label, children: label }),
433
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: Input_default.container, children: [
434
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
435
+ "input",
436
+ {
437
+ id: inputId,
438
+ name,
439
+ type: resolvedType,
440
+ className: [
441
+ Input_default.input,
442
+ isPassword && Input_default.hasToggle,
443
+ error && Input_default.error,
444
+ className
445
+ ].filter(Boolean).join(" "),
446
+ "aria-invalid": error ? "true" : void 0,
447
+ "aria-describedby": error ? `${inputId}-error` : void 0,
448
+ ...props
449
+ }
450
+ ),
451
+ isPassword && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
452
+ "button",
453
+ {
454
+ type: "button",
455
+ onClick: () => setShowPassword((prev) => !prev),
456
+ className: Input_default.toggle,
457
+ "aria-label": showPassword ? "Passwort verbergen" : "Passwort anzeigen",
458
+ tabIndex: -1,
459
+ children: showPassword ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("svg", { width: "20", height: "20", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
460
+ "path",
461
+ {
462
+ strokeLinecap: "round",
463
+ strokeLinejoin: "round",
464
+ strokeWidth: 2,
465
+ 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"
466
+ }
467
+ ) }) : /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("svg", { width: "20", height: "20", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: [
468
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
469
+ "path",
470
+ {
471
+ strokeLinecap: "round",
472
+ strokeLinejoin: "round",
473
+ strokeWidth: 2,
474
+ d: "M15 12a3 3 0 11-6 0 3 3 0 016 0z"
475
+ }
476
+ ),
477
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
478
+ "path",
479
+ {
480
+ strokeLinecap: "round",
481
+ strokeLinejoin: "round",
482
+ strokeWidth: 2,
483
+ 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"
484
+ }
485
+ )
486
+ ] })
487
+ }
488
+ )
489
+ ] }),
490
+ error && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { id: `${inputId}-error`, className: Input_default.errorText, children: error })
491
+ ] });
492
+ }
493
+
494
+ // src/components/Logo/Logo.tsx
495
+ var import_jsx_runtime12 = require("react/jsx-runtime");
496
+ function Logo({ size = 48, ...props }) {
497
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
498
+ "svg",
499
+ {
500
+ width: size,
501
+ height: size,
502
+ viewBox: "0 0 1000 1000",
503
+ fill: "none",
504
+ "aria-label": "Ganztagshelden Logo",
505
+ ...props,
506
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("g", { transform: "matrix(1.62384,0,0,1.62384,-670.097018,-377.993255)", children: [
507
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
508
+ "path",
509
+ {
510
+ 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",
511
+ fill: "var(--color-steel-800, #1E293B)"
512
+ }
513
+ ),
514
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
515
+ "path",
516
+ {
517
+ 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",
518
+ fill: "var(--color-steel-500, #64748B)"
519
+ }
520
+ ),
521
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
522
+ "path",
523
+ {
524
+ 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",
525
+ fill: "var(--color-steel-600, #475569)"
526
+ }
527
+ ),
528
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
529
+ "path",
530
+ {
531
+ 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",
532
+ fill: "var(--color-steel-400, #94A3B8)"
533
+ }
534
+ )
535
+ ] })
536
+ }
537
+ );
538
+ }
539
+
540
+ // src/components/Modal/Modal.tsx
541
+ var import_react4 = require("react");
542
+ var import_react_dom2 = require("react-dom");
543
+
544
+ // src/components/Modal/Modal.module.css
545
+ var Modal_default = {};
546
+
547
+ // src/components/Modal/Modal.tsx
548
+ var import_jsx_runtime13 = require("react/jsx-runtime");
549
+ function Modal({ isOpen, onClose, title, children, footer }) {
550
+ const [isAnimating, setIsAnimating] = (0, import_react4.useState)(false);
551
+ const [isExiting, setIsExiting] = (0, import_react4.useState)(false);
552
+ const onCloseRef = (0, import_react4.useRef)(onClose);
553
+ onCloseRef.current = onClose;
554
+ const handleClose = (0, import_react4.useCallback)(() => {
555
+ setIsExiting(true);
556
+ setIsAnimating(false);
557
+ setTimeout(() => {
558
+ onCloseRef.current();
559
+ }, 250);
560
+ }, []);
561
+ (0, import_react4.useEffect)(() => {
562
+ if (!isOpen) {
563
+ setIsAnimating(false);
564
+ setIsExiting(false);
565
+ return;
566
+ }
567
+ const handleEscape = (e) => {
568
+ if (e.key === "Escape") handleClose();
569
+ };
570
+ document.addEventListener("keydown", handleEscape);
571
+ document.body.style.overflow = "hidden";
572
+ const timer = setTimeout(() => setIsAnimating(true), 10);
573
+ return () => {
574
+ document.removeEventListener("keydown", handleEscape);
575
+ document.body.style.overflow = "";
576
+ clearTimeout(timer);
577
+ };
578
+ }, [isOpen, handleClose]);
579
+ if (!isOpen) return null;
580
+ const entering = isAnimating && !isExiting;
581
+ const modalContent = /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: Modal_default.overlay, children: [
582
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
583
+ "button",
584
+ {
585
+ type: "button",
586
+ onClick: handleClose,
587
+ className: [Modal_default.backdrop, entering && Modal_default.backdropVisible].filter(Boolean).join(" "),
588
+ "aria-label": "Hintergrund - Klicken zum Schlie\xDFen"
589
+ }
590
+ ),
591
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
592
+ "div",
593
+ {
594
+ className: [Modal_default.dialog, entering ? Modal_default.dialogEnter : Modal_default.dialogExit].join(" "),
595
+ role: "dialog",
596
+ "aria-modal": "true",
597
+ "aria-label": title || void 0,
598
+ children: [
599
+ title ? /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: Modal_default.header, children: [
600
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("h3", { className: Modal_default.title, children: title }),
601
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(CloseButton, { onClick: handleClose })
602
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: Modal_default.closeAbsolute, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(CloseButton, { onClick: handleClose }) }),
603
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
604
+ "div",
605
+ {
606
+ className: [Modal_default.content, entering && Modal_default.contentVisible].filter(Boolean).join(" "),
607
+ children
608
+ }
609
+ ),
610
+ footer && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: Modal_default.footer, children: footer })
611
+ ]
612
+ }
613
+ )
614
+ ] });
615
+ if (typeof document !== "undefined") {
616
+ return (0, import_react_dom2.createPortal)(modalContent, document.body);
617
+ }
618
+ return modalContent;
619
+ }
620
+ function ConfirmationModal({
621
+ isOpen,
622
+ onClose,
623
+ onConfirm,
624
+ title,
625
+ children,
626
+ confirmText = "Best\xE4tigen",
627
+ cancelText = "Abbrechen",
628
+ isConfirmLoading = false,
629
+ isConfirmDisabled = false,
630
+ variant = "primary"
631
+ }) {
632
+ const confirmClass = variant === "danger" ? Modal_default.confirmDanger : Modal_default.confirmPrimary;
633
+ const footer = /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
634
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", onClick: onClose, className: Modal_default.cancelButton, children: cancelText }),
635
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
636
+ "button",
637
+ {
638
+ type: "button",
639
+ onClick: onConfirm,
640
+ disabled: isConfirmLoading || isConfirmDisabled,
641
+ className: [Modal_default.confirmButton, confirmClass].join(" "),
642
+ children: isConfirmLoading ? /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("span", { className: Modal_default.confirmLoading, children: [
643
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("svg", { className: Modal_default.confirmSpinner, fill: "none", viewBox: "0 0 24 24", children: [
644
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("circle", { opacity: 0.25, cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
645
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
646
+ "path",
647
+ {
648
+ opacity: 0.75,
649
+ fill: "currentColor",
650
+ 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"
651
+ }
652
+ )
653
+ ] }),
654
+ "Wird geladen..."
655
+ ] }) : confirmText
656
+ }
657
+ )
658
+ ] });
659
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Modal, { isOpen, onClose, title, footer, children });
660
+ }
661
+ function CloseButton({ onClick }) {
662
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
663
+ "button",
664
+ {
665
+ type: "button",
666
+ onClick,
667
+ className: Modal_default.closeButton,
668
+ "aria-label": "Modal schlie\xDFen",
669
+ children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
670
+ "svg",
671
+ {
672
+ className: Modal_default.closeIcon,
673
+ width: "20",
674
+ height: "20",
675
+ fill: "none",
676
+ viewBox: "0 0 24 24",
677
+ stroke: "currentColor",
678
+ strokeWidth: 2,
679
+ children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 18L18 6M6 6l12 12" })
680
+ }
681
+ )
682
+ }
683
+ );
684
+ }
685
+
686
+ // src/components/Pill/Pill.module.css
687
+ var Pill_default = {};
688
+
689
+ // src/components/Pill/Pill.tsx
690
+ var import_jsx_runtime14 = require("react/jsx-runtime");
691
+ function Pill({
692
+ label,
693
+ color = "gray",
694
+ variant = "solid",
695
+ size = "md",
696
+ dot = true,
697
+ className,
698
+ ...props
699
+ }) {
700
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
701
+ "span",
702
+ {
703
+ className: [Pill_default.pill, Pill_default[`${variant}-${color}`], Pill_default[size], className].filter(Boolean).join(" "),
704
+ ...props,
705
+ children: [
706
+ dot && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: [Pill_default.dot, Pill_default[`dot-${size}`]].join(" ") }),
707
+ label
708
+ ]
709
+ }
710
+ );
711
+ }
712
+
713
+ // src/components/Radio/Radio.module.css
714
+ var Radio_default = {};
715
+
716
+ // src/components/Radio/Radio.tsx
717
+ var import_jsx_runtime15 = require("react/jsx-runtime");
718
+ function Radio({ label, id, name, className, ...props }) {
719
+ const inputId = id || `${name}-${label.toLowerCase().replace(/\s+/g, "-")}`;
720
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("label", { htmlFor: inputId, className: [Radio_default.wrapper, className].filter(Boolean).join(" "), children: [
721
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("input", { type: "radio", id: inputId, name, className: Radio_default.input, ...props }),
722
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: Radio_default.label, children: label })
723
+ ] });
724
+ }
725
+
726
+ // src/components/SearchBar/SearchBar.module.css
727
+ var SearchBar_default = {};
728
+
729
+ // src/components/SearchBar/SearchBar.tsx
730
+ var import_jsx_runtime16 = require("react/jsx-runtime");
731
+ function SearchBar({
732
+ value,
733
+ onChange,
734
+ onClear,
735
+ placeholder = "Name suchen...",
736
+ size = "md",
737
+ className,
738
+ ...props
739
+ }) {
740
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: [SearchBar_default.wrapper, className].filter(Boolean).join(" "), children: [
741
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
742
+ "svg",
743
+ {
744
+ className: [SearchBar_default.searchIcon, SearchBar_default[`icon-${size}`]].join(" "),
745
+ fill: "none",
746
+ viewBox: "0 0 24 24",
747
+ stroke: "currentColor",
748
+ children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
749
+ "path",
750
+ {
751
+ strokeLinecap: "round",
752
+ strokeLinejoin: "round",
753
+ strokeWidth: 2,
754
+ d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
755
+ }
756
+ )
757
+ }
758
+ ),
759
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
760
+ "input",
761
+ {
762
+ type: "text",
763
+ placeholder,
764
+ value,
765
+ onChange: (e) => onChange(e.target.value),
766
+ className: [SearchBar_default.input, SearchBar_default[size]].join(" "),
767
+ ...props
768
+ }
769
+ ),
770
+ value && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
771
+ "button",
772
+ {
773
+ type: "button",
774
+ onClick: () => {
775
+ onChange("");
776
+ onClear?.();
777
+ },
778
+ className: SearchBar_default.clearButton,
779
+ children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
780
+ "svg",
781
+ {
782
+ className: [SearchBar_default.clearIcon, SearchBar_default[`icon-${size}`]].join(" "),
783
+ fill: "none",
784
+ viewBox: "0 0 24 24",
785
+ stroke: "currentColor",
786
+ children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
787
+ "path",
788
+ {
789
+ strokeLinecap: "round",
790
+ strokeLinejoin: "round",
791
+ strokeWidth: 2,
792
+ d: "M6 18L18 6M6 6l12 12"
793
+ }
794
+ )
795
+ }
796
+ )
797
+ }
798
+ )
799
+ ] });
800
+ }
801
+
802
+ // src/components/Select/Select.module.css
803
+ var Select_default = {};
804
+
805
+ // src/components/Select/Select.tsx
806
+ var import_jsx_runtime17 = require("react/jsx-runtime");
807
+ function Select({ label, placeholder, options, id, className, ...props }) {
808
+ const selectId = id || (label ? label.toLowerCase().replace(/\s+/g, "-") : void 0);
809
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: Select_default.wrapper, children: [
810
+ label && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("label", { htmlFor: selectId, className: Select_default.label, children: label }),
811
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: Select_default.container, children: [
812
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
813
+ "select",
814
+ {
815
+ id: selectId,
816
+ className: [Select_default.select, className].filter(Boolean).join(" "),
817
+ ...props,
818
+ children: [
819
+ placeholder && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("option", { value: "", disabled: props.required, children: placeholder }),
820
+ options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("option", { value: option.value, disabled: option.disabled, children: option.label }, option.value))
821
+ ]
822
+ }
823
+ ),
824
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: Select_default.chevron, "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 9l-7 7-7-7" }) }) })
825
+ ] })
826
+ ] });
827
+ }
828
+
829
+ // src/components/Skeleton/Skeleton.module.css
830
+ var Skeleton_default = {};
831
+
832
+ // src/components/Skeleton/Skeleton.tsx
833
+ var import_jsx_runtime18 = require("react/jsx-runtime");
834
+ function Skeleton({
835
+ width,
836
+ height = 16,
837
+ circle = false,
838
+ borderRadius,
839
+ count = 1,
840
+ gap = 8,
841
+ className,
842
+ style,
843
+ ...props
844
+ }) {
845
+ const resolvedRadius = circle ? "9999px" : borderRadius != null ? typeof borderRadius === "number" ? `${borderRadius}px` : borderRadius : "var(--radius-md)";
846
+ const itemStyle = {
847
+ width: circle ? height : width,
848
+ height,
849
+ borderRadius: resolvedRadius,
850
+ ...style
851
+ };
852
+ if (count === 1) {
853
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
854
+ "div",
855
+ {
856
+ className: [Skeleton_default.skeleton, className].filter(Boolean).join(" "),
857
+ style: itemStyle,
858
+ "aria-hidden": "true",
859
+ ...props
860
+ }
861
+ );
862
+ }
863
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: Skeleton_default.group, style: { gap }, "aria-hidden": "true", ...props, children: Array.from({ length: count }, (_, i) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
864
+ "div",
865
+ {
866
+ className: [Skeleton_default.skeleton, className].filter(Boolean).join(" "),
867
+ style: itemStyle
868
+ },
869
+ `skeleton-${i}`
870
+ )) });
871
+ }
872
+
873
+ // src/components/Spinner/Spinner.module.css
874
+ var Spinner_default = {};
875
+
876
+ // src/components/Spinner/Spinner.tsx
877
+ var import_jsx_runtime19 = require("react/jsx-runtime");
878
+ var sizes = { sm: 20, md: 32, lg: 48 };
879
+ var strokes = { sm: 2.5, md: 3, lg: 3.5 };
880
+ function Spinner({ size = "md", label, className, ...props }) {
881
+ const s = sizes[size];
882
+ const stroke = strokes[size];
883
+ const r = (s - stroke) / 2;
884
+ const circumference = 2 * Math.PI * r;
885
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: [Spinner_default.wrapper, className].filter(Boolean).join(" "), role: "status", ...props, children: [
886
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("svg", { width: s, height: s, viewBox: `0 0 ${s} ${s}`, className: Spinner_default.svg, children: [
887
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
888
+ "circle",
889
+ {
890
+ cx: s / 2,
891
+ cy: s / 2,
892
+ r,
893
+ fill: "none",
894
+ stroke: "var(--semantic-color-border-default)",
895
+ strokeWidth: stroke
896
+ }
897
+ ),
898
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
899
+ "circle",
900
+ {
901
+ cx: s / 2,
902
+ cy: s / 2,
903
+ r,
904
+ fill: "none",
905
+ stroke: "var(--semantic-color-brand-primary)",
906
+ strokeWidth: stroke,
907
+ strokeLinecap: "round",
908
+ strokeDasharray: `${circumference * 0.3} ${circumference * 0.7}`
909
+ }
910
+ )
911
+ ] }),
912
+ label && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { className: Spinner_default.label, children: label }),
913
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: Spinner_default.srOnly, children: "Laden..." })
914
+ ] });
915
+ }
916
+
917
+ // src/components/StatusDot/StatusDot.module.css
918
+ var StatusDot_default = {};
919
+
920
+ // src/components/StatusDot/StatusDot.tsx
921
+ var import_jsx_runtime20 = require("react/jsx-runtime");
922
+ function StatusDot({
923
+ color,
924
+ tooltip,
925
+ size = "sm",
926
+ pulse,
927
+ className,
928
+ ...props
929
+ }) {
930
+ const shouldPulse = pulse ?? color === "green";
931
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
932
+ "div",
933
+ {
934
+ className: [StatusDot_default.dot, StatusDot_default[color], StatusDot_default[size], shouldPulse && StatusDot_default.pulse, className].filter(Boolean).join(" "),
935
+ title: tooltip,
936
+ ...props
937
+ }
938
+ );
939
+ }
940
+
941
+ // src/components/Tabs/Tabs.tsx
942
+ var import_react5 = require("react");
943
+
944
+ // src/components/Tabs/Tabs.module.css
945
+ var Tabs_default = {};
946
+
947
+ // src/components/Tabs/Tabs.tsx
948
+ var import_jsx_runtime21 = require("react/jsx-runtime");
949
+ function Tabs({ items, activeTab, onTabChange, className }) {
950
+ const tabRefs = (0, import_react5.useRef)([]);
951
+ const scrollRef = (0, import_react5.useRef)(null);
952
+ const [indicatorStyle, setIndicatorStyle] = (0, import_react5.useState)({ width: 0, left: 0 });
953
+ const [canScrollLeft, setCanScrollLeft] = (0, import_react5.useState)(false);
954
+ const [canScrollRight, setCanScrollRight] = (0, import_react5.useState)(false);
955
+ const showMobileDropdown = items.length >= 2;
956
+ const activeIndex = (0, import_react5.useMemo)(
957
+ () => items.findIndex((item) => item.id === activeTab),
958
+ [items, activeTab]
959
+ );
960
+ const activeLabel = items[activeIndex]?.label ?? "";
961
+ const updateScrollState = (0, import_react5.useCallback)(() => {
962
+ const el = scrollRef.current;
963
+ if (!el) return;
964
+ setCanScrollLeft(el.scrollLeft > 0);
965
+ setCanScrollRight(el.scrollLeft + el.clientWidth < el.scrollWidth - 1);
966
+ }, []);
967
+ const updateIndicator = (0, import_react5.useCallback)(() => {
968
+ const activeTabElement = tabRefs.current[activeIndex];
969
+ if (activeTabElement && activeTabElement.offsetWidth > 0) {
970
+ setIndicatorStyle({
971
+ left: activeTabElement.offsetLeft,
972
+ width: activeTabElement.offsetWidth
973
+ });
974
+ }
975
+ }, [activeIndex]);
976
+ (0, import_react5.useEffect)(() => {
977
+ updateIndicator();
978
+ const activeTabElement = tabRefs.current[activeIndex];
979
+ if (activeTabElement && scrollRef.current) {
980
+ const container = scrollRef.current;
981
+ const tabLeft = activeTabElement.offsetLeft;
982
+ const tabRight = tabLeft + activeTabElement.offsetWidth;
983
+ const containerLeft = container.scrollLeft;
984
+ const containerRight = containerLeft + container.clientWidth;
985
+ if (tabLeft < containerLeft) {
986
+ container.scrollTo({ left: tabLeft - 16, behavior: "smooth" });
987
+ } else if (tabRight > containerRight) {
988
+ container.scrollTo({
989
+ left: tabRight - container.clientWidth + 16,
990
+ behavior: "smooth"
991
+ });
992
+ }
993
+ }
994
+ }, [activeIndex, updateIndicator]);
995
+ (0, import_react5.useEffect)(() => {
996
+ updateScrollState();
997
+ updateIndicator();
998
+ const el = scrollRef.current;
999
+ if (!el) return;
1000
+ el.addEventListener("scroll", updateScrollState, { passive: true });
1001
+ const observer = new ResizeObserver(() => {
1002
+ updateScrollState();
1003
+ updateIndicator();
1004
+ });
1005
+ observer.observe(el);
1006
+ return () => {
1007
+ el.removeEventListener("scroll", updateScrollState);
1008
+ observer.disconnect();
1009
+ };
1010
+ }, [updateScrollState, updateIndicator]);
1011
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: [Tabs_default.wrapper, className].filter(Boolean).join(" "), children: [
1012
+ showMobileDropdown && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
1013
+ MobileTabDropdown,
1014
+ {
1015
+ items,
1016
+ activeTab,
1017
+ activeLabel,
1018
+ onTabChange
1019
+ }
1020
+ ),
1021
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
1022
+ "div",
1023
+ {
1024
+ className: [Tabs_default.tabsContainer, showMobileDropdown && Tabs_default.hiddenMobile].filter(Boolean).join(" "),
1025
+ children: [
1026
+ canScrollLeft && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: Tabs_default.fadeLeft }),
1027
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { ref: scrollRef, className: Tabs_default.scrollable, children: [
1028
+ items.map((tab, index) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
1029
+ "button",
1030
+ {
1031
+ ref: (el) => {
1032
+ tabRefs.current[index] = el;
1033
+ },
1034
+ type: "button",
1035
+ onClick: () => onTabChange(tab.id),
1036
+ className: [
1037
+ Tabs_default.tab,
1038
+ activeTab === tab.id ? Tabs_default.tabActive : Tabs_default.tabInactive
1039
+ ].join(" "),
1040
+ children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: Tabs_default.tabLabel, children: tab.label })
1041
+ },
1042
+ tab.id
1043
+ )),
1044
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
1045
+ "div",
1046
+ {
1047
+ className: Tabs_default.indicator,
1048
+ style: {
1049
+ left: `${indicatorStyle.left}px`,
1050
+ width: `${indicatorStyle.width}px`
1051
+ }
1052
+ }
1053
+ )
1054
+ ] }),
1055
+ canScrollRight && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: Tabs_default.fadeRight })
1056
+ ]
1057
+ }
1058
+ )
1059
+ ] });
1060
+ }
1061
+ function MobileTabDropdown({
1062
+ items,
1063
+ activeTab,
1064
+ activeLabel,
1065
+ onTabChange
1066
+ }) {
1067
+ const [isOpen, setIsOpen] = (0, import_react5.useState)(false);
1068
+ const dropdownRef = (0, import_react5.useRef)(null);
1069
+ (0, import_react5.useEffect)(() => {
1070
+ function handleClickOutside(event) {
1071
+ if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
1072
+ setIsOpen(false);
1073
+ }
1074
+ }
1075
+ document.addEventListener("mousedown", handleClickOutside);
1076
+ return () => document.removeEventListener("mousedown", handleClickOutside);
1077
+ }, []);
1078
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: Tabs_default.mobileDropdown, ref: dropdownRef, children: [
1079
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
1080
+ "button",
1081
+ {
1082
+ type: "button",
1083
+ onClick: () => setIsOpen(!isOpen),
1084
+ className: [Tabs_default.mobileToggle, isOpen && Tabs_default.mobileToggleOpen].filter(Boolean).join(" "),
1085
+ children: [
1086
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { children: activeLabel }),
1087
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
1088
+ "svg",
1089
+ {
1090
+ className: [Tabs_default.mobileChevron, isOpen && Tabs_default.mobileChevronOpen].filter(Boolean).join(" "),
1091
+ width: "20",
1092
+ height: "20",
1093
+ fill: "none",
1094
+ viewBox: "0 0 24 24",
1095
+ stroke: "currentColor",
1096
+ children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 9l-7 7-7-7" })
1097
+ }
1098
+ )
1099
+ ]
1100
+ }
1101
+ ),
1102
+ isOpen && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: Tabs_default.mobileMenu, children: items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
1103
+ "button",
1104
+ {
1105
+ type: "button",
1106
+ onClick: () => {
1107
+ onTabChange(item.id);
1108
+ setIsOpen(false);
1109
+ },
1110
+ className: [
1111
+ Tabs_default.mobileMenuItem,
1112
+ item.id === activeTab && Tabs_default.mobileMenuItemActive
1113
+ ].filter(Boolean).join(" "),
1114
+ children: item.label
1115
+ },
1116
+ item.id
1117
+ )) })
1118
+ ] });
1119
+ }
1120
+
1121
+ // src/components/Textarea/Textarea.module.css
1122
+ var Textarea_default = {};
1123
+
1124
+ // src/components/Textarea/Textarea.tsx
1125
+ var import_jsx_runtime22 = require("react/jsx-runtime");
1126
+ function Textarea({ label, error, id, name, rows = 4, className, ...props }) {
1127
+ const textareaId = id || name;
1128
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: Textarea_default.wrapper, children: [
1129
+ label && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("label", { htmlFor: textareaId, className: Textarea_default.label, children: label }),
1130
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
1131
+ "textarea",
1132
+ {
1133
+ id: textareaId,
1134
+ name,
1135
+ rows,
1136
+ className: [Textarea_default.textarea, error && Textarea_default.error, className].filter(Boolean).join(" "),
1137
+ "aria-invalid": error ? "true" : void 0,
1138
+ "aria-describedby": error ? `${textareaId}-error` : void 0,
1139
+ ...props
1140
+ }
1141
+ ),
1142
+ error && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("p", { id: `${textareaId}-error`, className: Textarea_default.errorText, children: error })
1143
+ ] });
1144
+ }
1145
+
1146
+ // src/components/Toast/Toast.tsx
1147
+ var import_react6 = require("react");
1148
+ var import_react_dom3 = require("react-dom");
1149
+
1150
+ // src/components/Toast/Toast.module.css
1151
+ var Toast_default = {};
1152
+
1153
+ // src/components/Toast/Toast.tsx
1154
+ var import_jsx_runtime23 = require("react/jsx-runtime");
1155
+ var icons2 = {
1156
+ success: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
1157
+ "svg",
1158
+ {
1159
+ width: "18",
1160
+ height: "18",
1161
+ fill: "none",
1162
+ viewBox: "0 0 24 24",
1163
+ stroke: "currentColor",
1164
+ strokeWidth: 2,
1165
+ children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M5 13l4 4L19 7" })
1166
+ }
1167
+ ),
1168
+ error: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
1169
+ "svg",
1170
+ {
1171
+ width: "18",
1172
+ height: "18",
1173
+ fill: "none",
1174
+ viewBox: "0 0 24 24",
1175
+ stroke: "currentColor",
1176
+ strokeWidth: 2,
1177
+ children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 18L18 6M6 6l12 12" })
1178
+ }
1179
+ ),
1180
+ warning: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
1181
+ "svg",
1182
+ {
1183
+ width: "18",
1184
+ height: "18",
1185
+ fill: "none",
1186
+ viewBox: "0 0 24 24",
1187
+ stroke: "currentColor",
1188
+ strokeWidth: 2,
1189
+ children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
1190
+ "path",
1191
+ {
1192
+ strokeLinecap: "round",
1193
+ strokeLinejoin: "round",
1194
+ 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"
1195
+ }
1196
+ )
1197
+ }
1198
+ ),
1199
+ info: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
1200
+ "svg",
1201
+ {
1202
+ width: "18",
1203
+ height: "18",
1204
+ fill: "none",
1205
+ viewBox: "0 0 24 24",
1206
+ stroke: "currentColor",
1207
+ strokeWidth: 2,
1208
+ children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
1209
+ "path",
1210
+ {
1211
+ strokeLinecap: "round",
1212
+ strokeLinejoin: "round",
1213
+ d: "M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
1214
+ }
1215
+ )
1216
+ }
1217
+ )
1218
+ };
1219
+ function Toast({ type = "info", message, duration = 4e3, onClose }) {
1220
+ const [isVisible, setIsVisible] = (0, import_react6.useState)(false);
1221
+ const [isExiting, setIsExiting] = (0, import_react6.useState)(false);
1222
+ const dismiss = (0, import_react6.useCallback)(() => {
1223
+ setIsExiting(true);
1224
+ setTimeout(onClose, 200);
1225
+ }, [onClose]);
1226
+ (0, import_react6.useEffect)(() => {
1227
+ const enterTimer = setTimeout(() => setIsVisible(true), 10);
1228
+ const exitTimer = duration > 0 ? setTimeout(dismiss, duration) : void 0;
1229
+ return () => {
1230
+ clearTimeout(enterTimer);
1231
+ if (exitTimer) clearTimeout(exitTimer);
1232
+ };
1233
+ }, [duration, dismiss]);
1234
+ const content = /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: Toast_default.container, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
1235
+ "div",
1236
+ {
1237
+ className: [
1238
+ Toast_default.toast,
1239
+ Toast_default[type],
1240
+ isVisible && !isExiting ? Toast_default.enter : Toast_default.exit
1241
+ ].filter(Boolean).join(" "),
1242
+ children: [
1243
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: Toast_default.icon, children: icons2[type] }),
1244
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: Toast_default.message, children: message }),
1245
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { type: "button", onClick: dismiss, className: Toast_default.close, "aria-label": "Schlie\xDFen", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
1246
+ "svg",
1247
+ {
1248
+ width: "14",
1249
+ height: "14",
1250
+ fill: "none",
1251
+ viewBox: "0 0 24 24",
1252
+ stroke: "currentColor",
1253
+ strokeWidth: 2,
1254
+ children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 18L18 6M6 6l12 12" })
1255
+ }
1256
+ ) })
1257
+ ]
1258
+ }
1259
+ ) });
1260
+ if (typeof document !== "undefined") {
1261
+ return (0, import_react_dom3.createPortal)(content, document.body);
1262
+ }
1263
+ return content;
1264
+ }
1265
+
1266
+ // src/components/Toggle/Toggle.module.css
1267
+ var Toggle_default = {};
1268
+
1269
+ // src/components/Toggle/Toggle.tsx
1270
+ var import_jsx_runtime24 = require("react/jsx-runtime");
1271
+ function Toggle({ label, size = "md", id, name, className, ...props }) {
1272
+ const inputId = id || name || (label ? label.toLowerCase().replace(/\s+/g, "-") : void 0);
1273
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("label", { htmlFor: inputId, className: [Toggle_default.wrapper, className].filter(Boolean).join(" "), children: [
1274
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("input", { type: "checkbox", id: inputId, name, className: Toggle_default.input, ...props }),
1275
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: [Toggle_default.track, Toggle_default[size]].join(" "), children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: Toggle_default.thumb }) }),
1276
+ label && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: Toggle_default.label, children: label })
1277
+ ] });
1278
+ }
1279
+ // Annotate the CommonJS export names for ESM import in node:
1280
+ 0 && (module.exports = {
1281
+ Accordion,
1282
+ Alert,
1283
+ Avatar,
1284
+ Badge,
1285
+ BadgeCompact,
1286
+ Button,
1287
+ Card,
1288
+ Checkbox,
1289
+ ConfirmationModal,
1290
+ Divider,
1291
+ DropdownMenu,
1292
+ FilterChips,
1293
+ Input,
1294
+ Logo,
1295
+ Modal,
1296
+ Pill,
1297
+ Radio,
1298
+ SearchBar,
1299
+ Select,
1300
+ Skeleton,
1301
+ Spinner,
1302
+ StatusDot,
1303
+ Tabs,
1304
+ Textarea,
1305
+ Toast,
1306
+ Toggle
1307
+ });
1308
+ //# sourceMappingURL=index.cjs.map