@boostdev/design-system-components 0.1.1 → 0.1.3

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/client.js ADDED
@@ -0,0 +1,2223 @@
1
+ 'use client';
2
+
3
+ // src/components/ui/Accordion/Accordion.tsx
4
+ import { useId, useState } from "react";
5
+
6
+ // src/components/ui/Accordion/Accordion.module.css
7
+ var Accordion_default = {};
8
+
9
+ // src/components/ui/Accordion/Accordion.tsx
10
+ import { cn } from "@boostdev/design-system-foundation";
11
+ import { jsx, jsxs } from "react/jsx-runtime";
12
+ function Accordion({
13
+ items,
14
+ allowMultiple = false,
15
+ defaultOpen = [],
16
+ className
17
+ }) {
18
+ const baseId = useId();
19
+ const [openIds, setOpenIds] = useState(defaultOpen);
20
+ const toggle = (id) => {
21
+ setOpenIds((prev) => {
22
+ const isOpen = prev.includes(id);
23
+ if (isOpen) return prev.filter((i) => i !== id);
24
+ return allowMultiple ? [...prev, id] : [id];
25
+ });
26
+ };
27
+ return /* @__PURE__ */ jsx("div", { className: cn(Accordion_default.accordion, className), children: items.map((item) => {
28
+ const isOpen = openIds.includes(item.id);
29
+ const triggerId = `${baseId}-trigger-${item.id}`;
30
+ const panelId = `${baseId}-panel-${item.id}`;
31
+ return /* @__PURE__ */ jsxs("div", { className: cn(Accordion_default.item, isOpen ? Accordion_default["--open"] : void 0), children: [
32
+ /* @__PURE__ */ jsx("h3", { className: Accordion_default.heading, children: /* @__PURE__ */ jsxs(
33
+ "button",
34
+ {
35
+ type: "button",
36
+ id: triggerId,
37
+ "aria-expanded": isOpen,
38
+ "aria-controls": panelId,
39
+ disabled: item.disabled,
40
+ className: Accordion_default.trigger,
41
+ onClick: () => toggle(item.id),
42
+ children: [
43
+ /* @__PURE__ */ jsx("span", { className: Accordion_default.triggerLabel, children: item.title }),
44
+ /* @__PURE__ */ jsx(
45
+ "svg",
46
+ {
47
+ "aria-hidden": "true",
48
+ className: Accordion_default.chevron,
49
+ viewBox: "0 0 24 24",
50
+ fill: "none",
51
+ stroke: "currentColor",
52
+ strokeWidth: "2",
53
+ children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 9l6 6 6-6" })
54
+ }
55
+ )
56
+ ]
57
+ }
58
+ ) }),
59
+ /* @__PURE__ */ jsx(
60
+ "div",
61
+ {
62
+ id: panelId,
63
+ role: "region",
64
+ "aria-labelledby": triggerId,
65
+ hidden: !isOpen,
66
+ className: Accordion_default.panel,
67
+ children: /* @__PURE__ */ jsx("div", { className: Accordion_default.panelContent, children: item.content })
68
+ }
69
+ )
70
+ ] }, item.id);
71
+ }) });
72
+ }
73
+
74
+ // src/components/ui/Alert/Alert.module.css
75
+ var Alert_default = {};
76
+
77
+ // src/components/ui/Alert/Alert.tsx
78
+ import { cn as cn2 } from "@boostdev/design-system-foundation";
79
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
80
+ function Alert({
81
+ variant = "info",
82
+ icon,
83
+ title,
84
+ children,
85
+ onDismiss,
86
+ className
87
+ }) {
88
+ const isUrgent = variant === "error" || variant === "warning";
89
+ return /* @__PURE__ */ jsxs2(
90
+ "div",
91
+ {
92
+ role: isUrgent ? "alert" : "status",
93
+ "aria-live": isUrgent ? "assertive" : "polite",
94
+ "aria-atomic": "true",
95
+ className: cn2(Alert_default.alert, Alert_default[`--variant_${variant}`], className),
96
+ children: [
97
+ icon && /* @__PURE__ */ jsx2("span", { className: Alert_default.icon, "aria-hidden": "true", children: icon }),
98
+ /* @__PURE__ */ jsxs2("div", { className: Alert_default.content, children: [
99
+ title && /* @__PURE__ */ jsx2("strong", { className: Alert_default.title, children: title }),
100
+ /* @__PURE__ */ jsx2("div", { className: Alert_default.body, children })
101
+ ] }),
102
+ onDismiss && /* @__PURE__ */ jsx2(
103
+ "button",
104
+ {
105
+ type: "button",
106
+ className: Alert_default.dismiss,
107
+ onClick: onDismiss,
108
+ "aria-label": "Dismiss alert",
109
+ children: /* @__PURE__ */ jsx2("svg", { "aria-hidden": "true", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx2("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M18 6L6 18M6 6l12 12" }) })
110
+ }
111
+ )
112
+ ]
113
+ }
114
+ );
115
+ }
116
+
117
+ // src/components/ui/Avatar/Avatar.module.css
118
+ var Avatar_default = {};
119
+
120
+ // src/components/ui/Avatar/Avatar.tsx
121
+ import { cn as cn3 } from "@boostdev/design-system-foundation";
122
+ import { jsx as jsx3 } from "react/jsx-runtime";
123
+ function getInitials(name) {
124
+ return name.split(" ").filter(Boolean).slice(0, 2).map((word) => word[0].toUpperCase()).join("");
125
+ }
126
+ function Avatar({ src, alt, name, size = "medium", className }) {
127
+ const sizeClass = Avatar_default[`--size_${size}`];
128
+ if (src) {
129
+ return /* @__PURE__ */ jsx3("span", { className: cn3(Avatar_default.avatar, sizeClass, className), children: /* @__PURE__ */ jsx3("img", { src, alt: alt ?? name ?? "", className: Avatar_default.image }) });
130
+ }
131
+ const initials = name ? getInitials(name) : "";
132
+ return /* @__PURE__ */ jsx3(
133
+ "span",
134
+ {
135
+ role: "img",
136
+ "aria-label": name ?? "User avatar",
137
+ className: cn3(Avatar_default.avatar, Avatar_default["--fallback"], sizeClass, className),
138
+ children: /* @__PURE__ */ jsx3("span", { className: Avatar_default.initials, "aria-hidden": "true", children: initials })
139
+ }
140
+ );
141
+ }
142
+
143
+ // src/components/ui/Badge/Badge.module.css
144
+ var Badge_default = {};
145
+
146
+ // src/components/ui/Badge/Badge.tsx
147
+ import { cn as cn4 } from "@boostdev/design-system-foundation";
148
+ import { jsx as jsx4 } from "react/jsx-runtime";
149
+ function Badge({ children, variant = "primary", className }) {
150
+ return /* @__PURE__ */ jsx4("span", { className: cn4(Badge_default.badge, Badge_default[`--variant_${variant}`], className), children });
151
+ }
152
+
153
+ // src/components/ui/Breadcrumb/Breadcrumb.module.css
154
+ var Breadcrumb_default = {};
155
+
156
+ // src/components/ui/Breadcrumb/Breadcrumb.tsx
157
+ import { cn as cn5 } from "@boostdev/design-system-foundation";
158
+ import { Fragment, jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
159
+ function Breadcrumb({ items, className }) {
160
+ return /* @__PURE__ */ jsx5("nav", { "aria-label": "Breadcrumb", className: cn5(Breadcrumb_default.breadcrumb, className), children: /* @__PURE__ */ jsx5("ol", { className: Breadcrumb_default.list, children: items.map((item, index) => {
161
+ const isLast = index === items.length - 1;
162
+ return /* @__PURE__ */ jsx5("li", { className: Breadcrumb_default.item, children: isLast ? /* @__PURE__ */ jsx5("span", { "aria-current": "page", className: Breadcrumb_default.current, children: item.label }) : /* @__PURE__ */ jsxs3(Fragment, { children: [
163
+ /* @__PURE__ */ jsx5("a", { href: item.href, className: Breadcrumb_default.link, children: item.label }),
164
+ /* @__PURE__ */ jsx5("span", { className: Breadcrumb_default.separator, "aria-hidden": "true", children: "\u203A" })
165
+ ] }) }, item.label);
166
+ }) }) });
167
+ }
168
+
169
+ // src/components/ui/Calendar/Calendar.tsx
170
+ import { useState as useState2, useId as useId2 } from "react";
171
+
172
+ // src/components/ui/Calendar/Calendar.module.css
173
+ var Calendar_default = {};
174
+
175
+ // src/components/ui/Calendar/Calendar.tsx
176
+ import { cn as cn6 } from "@boostdev/design-system-foundation";
177
+ import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
178
+ var DAYS = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
179
+ var MONTHS = [
180
+ "January",
181
+ "February",
182
+ "March",
183
+ "April",
184
+ "May",
185
+ "June",
186
+ "July",
187
+ "August",
188
+ "September",
189
+ "October",
190
+ "November",
191
+ "December"
192
+ ];
193
+ function isSameDay(a, b) {
194
+ return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
195
+ }
196
+ function isOutOfRange(date, min, max) {
197
+ if (min && date < min) return true;
198
+ if (max && date > max) return true;
199
+ return false;
200
+ }
201
+ function getDaysInMonth(year, month) {
202
+ return new Date(year, month + 1, 0).getDate();
203
+ }
204
+ function getFirstDayOfMonth(year, month) {
205
+ return new Date(year, month, 1).getDay();
206
+ }
207
+ function Calendar({ value, defaultValue, min, max, onChange, className }) {
208
+ const today = /* @__PURE__ */ new Date();
209
+ const controlled = value !== void 0;
210
+ const [internal, setInternal] = useState2(defaultValue);
211
+ const selected = controlled ? value : internal;
212
+ const [viewYear, setViewYear] = useState2(selected?.getFullYear() ?? today.getFullYear());
213
+ const [viewMonth, setViewMonth] = useState2(selected?.getMonth() ?? today.getMonth());
214
+ const [focusedDay, setFocusedDay] = useState2();
215
+ const titleId = useId2();
216
+ const daysInMonth = getDaysInMonth(viewYear, viewMonth);
217
+ const firstDay = getFirstDayOfMonth(viewYear, viewMonth);
218
+ const navigate = (delta) => {
219
+ const d = new Date(viewYear, viewMonth + delta, 1);
220
+ setViewYear(d.getFullYear());
221
+ setViewMonth(d.getMonth());
222
+ setFocusedDay(void 0);
223
+ };
224
+ const selectDay = (day) => {
225
+ const date = new Date(viewYear, viewMonth, day);
226
+ if (isOutOfRange(date, min, max)) return;
227
+ if (!controlled) setInternal(date);
228
+ onChange?.(date);
229
+ };
230
+ const handleKeyDown = (e, day) => {
231
+ const map = {
232
+ ArrowRight: 1,
233
+ ArrowLeft: -1,
234
+ ArrowDown: 7,
235
+ ArrowUp: -7
236
+ };
237
+ if (e.key in map) {
238
+ e.preventDefault();
239
+ const current = new Date(viewYear, viewMonth, day);
240
+ const next = new Date(current);
241
+ next.setDate(next.getDate() + map[e.key]);
242
+ setViewYear(next.getFullYear());
243
+ setViewMonth(next.getMonth());
244
+ setFocusedDay(next.getDate());
245
+ } else if (e.key === "Home") {
246
+ e.preventDefault();
247
+ setFocusedDay(1);
248
+ } else if (e.key === "End") {
249
+ e.preventDefault();
250
+ setFocusedDay(daysInMonth);
251
+ } else if (e.key === "Enter" || e.key === " ") {
252
+ e.preventDefault();
253
+ selectDay(day);
254
+ }
255
+ };
256
+ const cells = [
257
+ ...Array.from({ length: firstDay }, () => null),
258
+ ...Array.from({ length: daysInMonth }, (_, i) => ({ day: i + 1 }))
259
+ ];
260
+ while (cells.length % 7 !== 0) cells.push(null);
261
+ return /* @__PURE__ */ jsxs4("div", { className: cn6(Calendar_default.calendar, className), role: "group", "aria-labelledby": titleId, children: [
262
+ /* @__PURE__ */ jsxs4("div", { className: Calendar_default.header, children: [
263
+ /* @__PURE__ */ jsx6(
264
+ "button",
265
+ {
266
+ type: "button",
267
+ className: Calendar_default.navBtn,
268
+ "aria-label": "Previous month",
269
+ onClick: () => navigate(-1),
270
+ children: /* @__PURE__ */ jsx6("svg", { "aria-hidden": "true", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", children: /* @__PURE__ */ jsx6("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M15 19l-7-7 7-7" }) })
271
+ }
272
+ ),
273
+ /* @__PURE__ */ jsxs4("span", { id: titleId, className: Calendar_default.monthYear, "aria-live": "polite", children: [
274
+ MONTHS[viewMonth],
275
+ " ",
276
+ viewYear
277
+ ] }),
278
+ /* @__PURE__ */ jsx6(
279
+ "button",
280
+ {
281
+ type: "button",
282
+ className: Calendar_default.navBtn,
283
+ "aria-label": "Next month",
284
+ onClick: () => navigate(1),
285
+ children: /* @__PURE__ */ jsx6("svg", { "aria-hidden": "true", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", children: /* @__PURE__ */ jsx6("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M9 5l7 7-7 7" }) })
286
+ }
287
+ )
288
+ ] }),
289
+ /* @__PURE__ */ jsxs4(
290
+ "table",
291
+ {
292
+ className: Calendar_default.grid,
293
+ role: "grid",
294
+ "aria-labelledby": titleId,
295
+ children: [
296
+ /* @__PURE__ */ jsx6("thead", { children: /* @__PURE__ */ jsx6("tr", { children: DAYS.map((d) => /* @__PURE__ */ jsx6("th", { scope: "col", abbr: d, className: Calendar_default.weekday, children: d }, d)) }) }),
297
+ /* @__PURE__ */ jsx6("tbody", { children: Array.from({ length: cells.length / 7 }, (_, row) => /* @__PURE__ */ jsx6("tr", { children: cells.slice(row * 7, row * 7 + 7).map((cell, col) => {
298
+ if (!cell) return /* @__PURE__ */ jsx6("td", { className: Calendar_default.empty, "aria-hidden": "true" }, col);
299
+ const date = new Date(viewYear, viewMonth, cell.day);
300
+ const isSelected = selected ? isSameDay(date, selected) : false;
301
+ const isToday = isSameDay(date, today);
302
+ const disabled = isOutOfRange(date, min, max);
303
+ const isFocused = focusedDay === cell.day;
304
+ return /* @__PURE__ */ jsx6("td", { role: "gridcell", children: /* @__PURE__ */ jsx6(
305
+ "button",
306
+ {
307
+ type: "button",
308
+ className: cn6(
309
+ Calendar_default.day,
310
+ isSelected && Calendar_default.selected,
311
+ isToday && !isSelected && Calendar_default.today,
312
+ disabled && Calendar_default.disabled
313
+ ),
314
+ "aria-label": date.toLocaleDateString("en", { month: "long", day: "numeric", year: "numeric" }),
315
+ "aria-pressed": isSelected,
316
+ "aria-current": isToday ? "date" : void 0,
317
+ "aria-disabled": disabled,
318
+ disabled,
319
+ tabIndex: isFocused || !focusedDay && isSelected || !focusedDay && !selected && isToday ? 0 : -1,
320
+ onClick: () => selectDay(cell.day),
321
+ onKeyDown: (e) => handleKeyDown(e, cell.day),
322
+ children: cell.day
323
+ }
324
+ ) }, col);
325
+ }) }, row)) })
326
+ ]
327
+ }
328
+ )
329
+ ] });
330
+ }
331
+
332
+ // src/components/ui/Carousel/Carousel.tsx
333
+ import { useRef, useId as useId3 } from "react";
334
+
335
+ // src/components/ui/Carousel/Carousel.module.css
336
+ var Carousel_default = {};
337
+
338
+ // src/components/ui/Carousel/Carousel.tsx
339
+ import { cn as cn7 } from "@boostdev/design-system-foundation";
340
+ import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
341
+ function Carousel({ items, label, className }) {
342
+ const trackRef = useRef(null);
343
+ const listId = useId3();
344
+ const scroll = (direction) => {
345
+ if (!trackRef.current) return;
346
+ const { scrollLeft, clientWidth } = trackRef.current;
347
+ trackRef.current.scrollTo({
348
+ left: scrollLeft + (direction === "next" ? clientWidth : -clientWidth),
349
+ behavior: "smooth"
350
+ });
351
+ };
352
+ return /* @__PURE__ */ jsxs5("section", { "aria-label": label, className: cn7(Carousel_default.carousel, className), children: [
353
+ /* @__PURE__ */ jsx7(
354
+ "button",
355
+ {
356
+ type: "button",
357
+ className: cn7(Carousel_default.navBtn, Carousel_default["--prev"]),
358
+ "aria-label": "Previous",
359
+ "aria-controls": listId,
360
+ onClick: () => scroll("prev"),
361
+ children: /* @__PURE__ */ jsx7("svg", { "aria-hidden": "true", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", children: /* @__PURE__ */ jsx7("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M15 19l-7-7 7-7" }) })
362
+ }
363
+ ),
364
+ /* @__PURE__ */ jsx7(
365
+ "div",
366
+ {
367
+ ref: trackRef,
368
+ id: listId,
369
+ role: "list",
370
+ className: Carousel_default.track,
371
+ children: items.map((item, i) => /* @__PURE__ */ jsx7("div", { role: "listitem", className: Carousel_default.slide, children: item }, i))
372
+ }
373
+ ),
374
+ /* @__PURE__ */ jsx7(
375
+ "button",
376
+ {
377
+ type: "button",
378
+ className: cn7(Carousel_default.navBtn, Carousel_default["--next"]),
379
+ "aria-label": "Next",
380
+ "aria-controls": listId,
381
+ onClick: () => scroll("next"),
382
+ children: /* @__PURE__ */ jsx7("svg", { "aria-hidden": "true", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", children: /* @__PURE__ */ jsx7("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M9 5l7 7-7 7" }) })
383
+ }
384
+ )
385
+ ] });
386
+ }
387
+
388
+ // src/components/ui/DescriptionList/DescriptionList.module.css
389
+ var DescriptionList_default = {};
390
+
391
+ // src/components/ui/DescriptionList/DescriptionList.tsx
392
+ import { cn as cn8 } from "@boostdev/design-system-foundation";
393
+ import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
394
+ function DescriptionList({ items, layout = "stacked", className }) {
395
+ return /* @__PURE__ */ jsx8("dl", { className: cn8(DescriptionList_default.list, DescriptionList_default[`--layout_${layout}`], className), children: items.map((item, i) => /* @__PURE__ */ jsxs6("div", { className: DescriptionList_default.group, children: [
396
+ /* @__PURE__ */ jsx8("dt", { className: DescriptionList_default.term, children: item.term }),
397
+ Array.isArray(item.details) ? item.details.map((d, j) => /* @__PURE__ */ jsx8("dd", { className: DescriptionList_default.details, children: d }, j)) : /* @__PURE__ */ jsx8("dd", { className: DescriptionList_default.details, children: item.details })
398
+ ] }, i)) });
399
+ }
400
+
401
+ // src/components/ui/Link/Link.module.css
402
+ var Link_default = {};
403
+
404
+ // src/components/ui/Link/Link.tsx
405
+ import { cn as cn9 } from "@boostdev/design-system-foundation";
406
+ import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
407
+ function Link({
408
+ as,
409
+ children,
410
+ variant = "default",
411
+ external = false,
412
+ className,
413
+ ...props
414
+ }) {
415
+ const Component = as ?? "a";
416
+ const externalProps = external ? { target: "_blank", rel: "noreferrer noopener" } : {};
417
+ return /* @__PURE__ */ jsxs7(
418
+ Component,
419
+ {
420
+ className: cn9(Link_default.link, Link_default[`--variant_${variant}`], className),
421
+ ...externalProps,
422
+ ...props,
423
+ children: [
424
+ children,
425
+ external && /* @__PURE__ */ jsx9("span", { className: Link_default.externalLabel, children: " (opens in new tab)" })
426
+ ]
427
+ }
428
+ );
429
+ }
430
+
431
+ // src/components/ui/Loading/Loading.module.css
432
+ var Loading_default = {};
433
+
434
+ // src/components/ui/Loading/Loading.tsx
435
+ import { cn as cn10 } from "@boostdev/design-system-foundation";
436
+ import { jsx as jsx10 } from "react/jsx-runtime";
437
+ function Loading({ size = "medium", className }) {
438
+ return /* @__PURE__ */ jsx10("div", { className: cn10(Loading_default.loading, Loading_default[`--size_${size}`], className), children: /* @__PURE__ */ jsx10("div", { className: Loading_default.spinner, role: "status", "aria-label": "Loading" }) });
439
+ }
440
+
441
+ // src/components/ui/NotificationBanner/NotificationBanner.module.css
442
+ var NotificationBanner_default = {};
443
+
444
+ // src/components/ui/NotificationBanner/NotificationBanner.tsx
445
+ import { cn as cn11 } from "@boostdev/design-system-foundation";
446
+ import { jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
447
+ function NotificationBanner({
448
+ variant = "info",
449
+ children,
450
+ action,
451
+ onDismiss,
452
+ className
453
+ }) {
454
+ const isUrgent = variant === "error" || variant === "warning";
455
+ return /* @__PURE__ */ jsxs8(
456
+ "div",
457
+ {
458
+ role: isUrgent ? "alert" : "status",
459
+ "aria-live": isUrgent ? "assertive" : "polite",
460
+ "aria-atomic": "true",
461
+ className: cn11(NotificationBanner_default.banner, NotificationBanner_default[`--variant_${variant}`], className),
462
+ children: [
463
+ /* @__PURE__ */ jsx11("div", { className: NotificationBanner_default.content, children }),
464
+ action && /* @__PURE__ */ jsx11("div", { className: NotificationBanner_default.action, children: action }),
465
+ onDismiss && /* @__PURE__ */ jsx11(
466
+ "button",
467
+ {
468
+ type: "button",
469
+ className: NotificationBanner_default.dismiss,
470
+ onClick: onDismiss,
471
+ "aria-label": "Dismiss notification",
472
+ children: /* @__PURE__ */ jsx11("svg", { "aria-hidden": "true", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx11("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M18 6L6 18M6 6l12 12" }) })
473
+ }
474
+ )
475
+ ]
476
+ }
477
+ );
478
+ }
479
+
480
+ // src/components/ui/Pagination/Pagination.module.css
481
+ var Pagination_default = {};
482
+
483
+ // src/components/ui/Pagination/Pagination.tsx
484
+ import { cn as cn12 } from "@boostdev/design-system-foundation";
485
+ import { jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
486
+ function getPageRange(current, total) {
487
+ const delta = 1;
488
+ const range = [];
489
+ for (let i = 1; i <= total; i++) {
490
+ if (i === 1 || i === total || i >= current - delta && i <= current + delta) {
491
+ range.push(i);
492
+ } else if (range[range.length - 1] !== "...") {
493
+ range.push("...");
494
+ }
495
+ }
496
+ return range;
497
+ }
498
+ function Pagination({
499
+ currentPage,
500
+ totalPages,
501
+ onPageChange,
502
+ className
503
+ }) {
504
+ const pages = getPageRange(currentPage, totalPages);
505
+ return /* @__PURE__ */ jsx12("nav", { "aria-label": "Pagination", className: cn12(Pagination_default.pagination, className), children: /* @__PURE__ */ jsxs9("ul", { className: Pagination_default.list, children: [
506
+ /* @__PURE__ */ jsx12("li", { children: /* @__PURE__ */ jsx12(
507
+ "button",
508
+ {
509
+ type: "button",
510
+ className: cn12(Pagination_default.button, Pagination_default["--nav"]),
511
+ onClick: () => onPageChange(currentPage - 1),
512
+ disabled: currentPage <= 1,
513
+ "aria-label": "Previous page",
514
+ children: /* @__PURE__ */ jsx12("svg", { "aria-hidden": "true", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx12("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M15 19l-7-7 7-7" }) })
515
+ }
516
+ ) }),
517
+ pages.map(
518
+ (page, index) => page === "..." ? /* @__PURE__ */ jsx12("li", { children: /* @__PURE__ */ jsx12("span", { className: Pagination_default.ellipsis, "aria-hidden": "true", children: "\u2026" }) }, `ellipsis-${index}`) : /* @__PURE__ */ jsx12("li", { children: /* @__PURE__ */ jsx12(
519
+ "button",
520
+ {
521
+ type: "button",
522
+ className: cn12(Pagination_default.button, currentPage === page ? Pagination_default["--active"] : void 0),
523
+ onClick: () => onPageChange(page),
524
+ "aria-label": `Page ${page}`,
525
+ "aria-current": currentPage === page ? "page" : void 0,
526
+ children: page
527
+ }
528
+ ) }, page)
529
+ ),
530
+ /* @__PURE__ */ jsx12("li", { children: /* @__PURE__ */ jsx12(
531
+ "button",
532
+ {
533
+ type: "button",
534
+ className: cn12(Pagination_default.button, Pagination_default["--nav"]),
535
+ onClick: () => onPageChange(currentPage + 1),
536
+ disabled: currentPage >= totalPages,
537
+ "aria-label": "Next page",
538
+ children: /* @__PURE__ */ jsx12("svg", { "aria-hidden": "true", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx12("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M9 5l7 7-7 7" }) })
539
+ }
540
+ ) })
541
+ ] }) });
542
+ }
543
+
544
+ // src/components/ui/Progress/Progress.module.css
545
+ var Progress_default = {};
546
+
547
+ // src/components/ui/Progress/Progress.tsx
548
+ import { cn as cn13 } from "@boostdev/design-system-foundation";
549
+ import { jsx as jsx13, jsxs as jsxs10 } from "react/jsx-runtime";
550
+ function Progress({
551
+ value,
552
+ max = 100,
553
+ label,
554
+ showLabel = false,
555
+ size = "medium",
556
+ className
557
+ }) {
558
+ const percentage = Math.min(100, Math.max(0, value / max * 100));
559
+ return /* @__PURE__ */ jsxs10("div", { className: cn13(Progress_default.container, className), children: [
560
+ showLabel && /* @__PURE__ */ jsxs10("div", { className: Progress_default.labelRow, children: [
561
+ /* @__PURE__ */ jsx13("span", { className: Progress_default.label, children: label }),
562
+ /* @__PURE__ */ jsxs10("span", { className: Progress_default.value, children: [
563
+ Math.round(percentage),
564
+ "%"
565
+ ] })
566
+ ] }),
567
+ /* @__PURE__ */ jsx13(
568
+ "div",
569
+ {
570
+ role: "progressbar",
571
+ "aria-label": label,
572
+ "aria-valuenow": value,
573
+ "aria-valuemin": 0,
574
+ "aria-valuemax": max,
575
+ className: cn13(Progress_default.track, Progress_default[`--size_${size}`]),
576
+ children: /* @__PURE__ */ jsx13("div", { className: Progress_default.fill, style: { width: `${percentage}%` } })
577
+ }
578
+ )
579
+ ] });
580
+ }
581
+
582
+ // src/components/ui/ProgressCircle/ProgressCircle.module.css
583
+ var ProgressCircle_default = {};
584
+
585
+ // src/components/ui/ProgressCircle/ProgressCircle.tsx
586
+ import { cn as cn14 } from "@boostdev/design-system-foundation";
587
+ import { jsx as jsx14, jsxs as jsxs11 } from "react/jsx-runtime";
588
+ var SIZE_PX = { small: 40, medium: 64, large: 96 };
589
+ var STROKE_WIDTH = 4;
590
+ function ProgressCircle({
591
+ value,
592
+ max = 100,
593
+ label,
594
+ showValue = false,
595
+ size = "medium",
596
+ className
597
+ }) {
598
+ const percentage = Math.min(100, Math.max(0, value / max * 100));
599
+ const px = SIZE_PX[size];
600
+ const radius = (px - STROKE_WIDTH * 2) / 2;
601
+ const circumference = 2 * Math.PI * radius;
602
+ const offset = circumference - percentage / 100 * circumference;
603
+ const cx = px / 2;
604
+ return /* @__PURE__ */ jsxs11(
605
+ "div",
606
+ {
607
+ role: "progressbar",
608
+ "aria-label": label,
609
+ "aria-valuenow": value,
610
+ "aria-valuemin": 0,
611
+ "aria-valuemax": max,
612
+ className: cn14(ProgressCircle_default.wrapper, ProgressCircle_default[`--size_${size}`], className),
613
+ children: [
614
+ /* @__PURE__ */ jsxs11(
615
+ "svg",
616
+ {
617
+ width: px,
618
+ height: px,
619
+ viewBox: `0 0 ${px} ${px}`,
620
+ "aria-hidden": "true",
621
+ className: ProgressCircle_default.svg,
622
+ children: [
623
+ /* @__PURE__ */ jsx14(
624
+ "circle",
625
+ {
626
+ className: ProgressCircle_default.track,
627
+ cx,
628
+ cy: cx,
629
+ r: radius,
630
+ strokeWidth: STROKE_WIDTH,
631
+ fill: "none"
632
+ }
633
+ ),
634
+ /* @__PURE__ */ jsx14(
635
+ "circle",
636
+ {
637
+ className: ProgressCircle_default.fill,
638
+ cx,
639
+ cy: cx,
640
+ r: radius,
641
+ strokeWidth: STROKE_WIDTH,
642
+ fill: "none",
643
+ strokeDasharray: circumference,
644
+ strokeDashoffset: offset,
645
+ strokeLinecap: "round",
646
+ transform: `rotate(-90 ${cx} ${cx})`
647
+ }
648
+ )
649
+ ]
650
+ }
651
+ ),
652
+ showValue && /* @__PURE__ */ jsxs11("span", { className: ProgressCircle_default.value, "aria-hidden": "true", children: [
653
+ Math.round(percentage),
654
+ "%"
655
+ ] })
656
+ ]
657
+ }
658
+ );
659
+ }
660
+
661
+ // src/components/ui/Separator/Separator.module.css
662
+ var Separator_default = {};
663
+
664
+ // src/components/ui/Separator/Separator.tsx
665
+ import { cn as cn15 } from "@boostdev/design-system-foundation";
666
+ import { jsx as jsx15 } from "react/jsx-runtime";
667
+ function Separator({ orientation = "horizontal", className }) {
668
+ if (orientation === "vertical") {
669
+ return /* @__PURE__ */ jsx15(
670
+ "div",
671
+ {
672
+ role: "separator",
673
+ "aria-orientation": "vertical",
674
+ className: cn15(Separator_default.separator, Separator_default["--vertical"], className)
675
+ }
676
+ );
677
+ }
678
+ return /* @__PURE__ */ jsx15("hr", { className: cn15(Separator_default.separator, Separator_default["--horizontal"], className) });
679
+ }
680
+
681
+ // src/components/ui/Skeleton/Skeleton.tsx
682
+ import { cn as cn16 } from "@boostdev/design-system-foundation";
683
+
684
+ // src/components/ui/Skeleton/Skeleton.module.css
685
+ var Skeleton_default = {};
686
+
687
+ // src/components/ui/Skeleton/Skeleton.tsx
688
+ import { jsx as jsx16 } from "react/jsx-runtime";
689
+ function Skeleton({ className }) {
690
+ return /* @__PURE__ */ jsx16("div", { "aria-hidden": "true", className: cn16(Skeleton_default.skeleton, className) });
691
+ }
692
+
693
+ // src/components/ui/SkipLink/SkipLink.module.css
694
+ var SkipLink_default = {};
695
+
696
+ // src/components/ui/SkipLink/SkipLink.tsx
697
+ import { jsx as jsx17 } from "react/jsx-runtime";
698
+ function SkipLink({ href = "#main", children = "Skip to main content" }) {
699
+ return /* @__PURE__ */ jsx17("a", { href, className: SkipLink_default.skipLink, children });
700
+ }
701
+
702
+ // src/components/ui/Table/Table.module.css
703
+ var Table_default = {};
704
+
705
+ // src/components/ui/Table/Table.tsx
706
+ import { cn as cn17 } from "@boostdev/design-system-foundation";
707
+ import { jsx as jsx18, jsxs as jsxs12 } from "react/jsx-runtime";
708
+ function Table({
709
+ columns,
710
+ rows,
711
+ caption,
712
+ sortKey,
713
+ sortDirection,
714
+ onSort,
715
+ className
716
+ }) {
717
+ const handleSort = (key) => {
718
+ if (!onSort) return;
719
+ const nextDirection = sortKey === key && sortDirection === "asc" ? "desc" : "asc";
720
+ onSort(key, nextDirection);
721
+ };
722
+ const getAriaSort = (key) => {
723
+ if (sortKey !== key) return "none";
724
+ return sortDirection === "asc" ? "ascending" : "descending";
725
+ };
726
+ return /* @__PURE__ */ jsx18("div", { className: cn17(Table_default.wrapper, className), children: /* @__PURE__ */ jsxs12("table", { className: Table_default.table, children: [
727
+ caption && /* @__PURE__ */ jsx18("caption", { className: Table_default.caption, children: caption }),
728
+ /* @__PURE__ */ jsx18("thead", { className: Table_default.thead, children: /* @__PURE__ */ jsx18("tr", { children: columns.map((col) => /* @__PURE__ */ jsx18(
729
+ "th",
730
+ {
731
+ scope: "col",
732
+ "aria-sort": col.sortable ? getAriaSort(col.key) : void 0,
733
+ className: cn17(Table_default.th, col.sortable ? Table_default["--sortable"] : void 0),
734
+ children: col.sortable ? /* @__PURE__ */ jsxs12(
735
+ "button",
736
+ {
737
+ type: "button",
738
+ className: Table_default.sortButton,
739
+ onClick: () => handleSort(col.key),
740
+ children: [
741
+ col.header,
742
+ /* @__PURE__ */ jsx18(
743
+ "svg",
744
+ {
745
+ "aria-hidden": "true",
746
+ className: cn17(
747
+ Table_default.sortIcon,
748
+ sortKey === col.key ? Table_default["--sort-active"] : void 0,
749
+ sortKey === col.key && sortDirection === "desc" ? Table_default["--sort-desc"] : void 0
750
+ ),
751
+ viewBox: "0 0 24 24",
752
+ fill: "none",
753
+ stroke: "currentColor",
754
+ strokeWidth: "2",
755
+ children: /* @__PURE__ */ jsx18("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 9l6 6 6-6" })
756
+ }
757
+ )
758
+ ]
759
+ }
760
+ ) : col.header
761
+ },
762
+ col.key
763
+ )) }) }),
764
+ /* @__PURE__ */ jsx18("tbody", { className: Table_default.tbody, children: rows.map((row, rowIndex) => /* @__PURE__ */ jsx18("tr", { className: Table_default.tr, children: columns.map((col) => /* @__PURE__ */ jsx18("td", { className: Table_default.td, children: col.render ? col.render(row) : String(row[col.key] ?? "") }, col.key)) }, rowIndex)) })
765
+ ] }) });
766
+ }
767
+
768
+ // src/components/ui/Tabs/Tabs.tsx
769
+ import { useId as useId4, useRef as useRef2, useState as useState3 } from "react";
770
+
771
+ // src/components/ui/Tabs/Tabs.module.css
772
+ var Tabs_default = {};
773
+
774
+ // src/components/ui/Tabs/Tabs.tsx
775
+ import { cn as cn18 } from "@boostdev/design-system-foundation";
776
+ import { jsx as jsx19, jsxs as jsxs13 } from "react/jsx-runtime";
777
+ function Tabs({ tabs, defaultTab, className }) {
778
+ const baseId = useId4();
779
+ const [activeTab, setActiveTab] = useState3(defaultTab ?? tabs[0]?.id);
780
+ const tabRefs = useRef2([]);
781
+ const enabledIndexes = tabs.map((tab, i) => ({ tab, i })).filter(({ tab }) => !tab.disabled).map(({ i }) => i);
782
+ const handleKeyDown = (e, index) => {
783
+ const pos = enabledIndexes.indexOf(index);
784
+ const focusAt = (i) => {
785
+ tabRefs.current[i]?.focus();
786
+ setActiveTab(tabs[i].id);
787
+ };
788
+ if (e.key === "ArrowRight") {
789
+ e.preventDefault();
790
+ focusAt(enabledIndexes[(pos + 1) % enabledIndexes.length]);
791
+ } else if (e.key === "ArrowLeft") {
792
+ e.preventDefault();
793
+ focusAt(enabledIndexes[(pos - 1 + enabledIndexes.length) % enabledIndexes.length]);
794
+ } else if (e.key === "Home") {
795
+ e.preventDefault();
796
+ focusAt(enabledIndexes[0]);
797
+ } else if (e.key === "End") {
798
+ e.preventDefault();
799
+ focusAt(enabledIndexes[enabledIndexes.length - 1]);
800
+ }
801
+ };
802
+ return /* @__PURE__ */ jsxs13("div", { className: cn18(Tabs_default.tabs, className), children: [
803
+ /* @__PURE__ */ jsx19("div", { role: "tablist", className: Tabs_default.tabList, children: tabs.map((tab, i) => {
804
+ const tabId = `${baseId}-tab-${tab.id}`;
805
+ const panelId = `${baseId}-panel-${tab.id}`;
806
+ const isActive = activeTab === tab.id;
807
+ return /* @__PURE__ */ jsx19(
808
+ "button",
809
+ {
810
+ ref: (el) => {
811
+ tabRefs.current[i] = el;
812
+ },
813
+ id: tabId,
814
+ type: "button",
815
+ role: "tab",
816
+ "aria-selected": isActive,
817
+ "aria-controls": panelId,
818
+ tabIndex: isActive ? 0 : -1,
819
+ disabled: tab.disabled,
820
+ className: cn18(Tabs_default.tab, isActive ? Tabs_default["--active"] : void 0),
821
+ onClick: () => setActiveTab(tab.id),
822
+ onKeyDown: (e) => handleKeyDown(e, i),
823
+ children: tab.label
824
+ },
825
+ tab.id
826
+ );
827
+ }) }),
828
+ tabs.map((tab) => {
829
+ const tabId = `${baseId}-tab-${tab.id}`;
830
+ const panelId = `${baseId}-panel-${tab.id}`;
831
+ const isActive = activeTab === tab.id;
832
+ return /* @__PURE__ */ jsx19(
833
+ "div",
834
+ {
835
+ id: panelId,
836
+ role: "tabpanel",
837
+ "aria-labelledby": tabId,
838
+ tabIndex: 0,
839
+ hidden: !isActive,
840
+ className: Tabs_default.panel,
841
+ children: tab.content
842
+ },
843
+ tab.id
844
+ );
845
+ })
846
+ ] });
847
+ }
848
+
849
+ // src/components/ui/Tooltip/Tooltip.tsx
850
+ import { cloneElement, isValidElement, useId as useId5 } from "react";
851
+
852
+ // src/components/ui/Tooltip/Tooltip.module.css
853
+ var Tooltip_default = {};
854
+
855
+ // src/components/ui/Tooltip/Tooltip.tsx
856
+ import { cn as cn19 } from "@boostdev/design-system-foundation";
857
+ import { jsx as jsx20, jsxs as jsxs14 } from "react/jsx-runtime";
858
+ function Tooltip({
859
+ content,
860
+ placement = "top",
861
+ children,
862
+ className
863
+ }) {
864
+ const tooltipId = useId5();
865
+ const trigger = isValidElement(children) ? cloneElement(children, {
866
+ "aria-describedby": tooltipId
867
+ }) : children;
868
+ return /* @__PURE__ */ jsxs14("span", { className: cn19(Tooltip_default.wrapper, className), children: [
869
+ trigger,
870
+ /* @__PURE__ */ jsx20(
871
+ "span",
872
+ {
873
+ id: tooltipId,
874
+ role: "tooltip",
875
+ className: cn19(Tooltip_default.tooltip, Tooltip_default[`--placement_${placement}`]),
876
+ children: content
877
+ }
878
+ )
879
+ ] });
880
+ }
881
+
882
+ // src/components/ui/Typography/Typography.module.css
883
+ var Typography_default = {};
884
+
885
+ // src/components/ui/Typography/Typography.tsx
886
+ import { cn as cn20 } from "@boostdev/design-system-foundation";
887
+ import { jsx as jsx21 } from "react/jsx-runtime";
888
+ var variantToElement = {
889
+ h1: "h1",
890
+ h2: "h2",
891
+ h3: "h3",
892
+ body: "p",
893
+ body_s: "p"
894
+ };
895
+ function Typography({ variant = "body", component, children, className }) {
896
+ const Component = component || variantToElement[variant];
897
+ return /* @__PURE__ */ jsx21(Component, { className: cn20(Typography_default.typography, Typography_default[`--${variant}`], className), children });
898
+ }
899
+
900
+ // src/components/interaction/Button/Button.module.css
901
+ var Button_default = {};
902
+
903
+ // src/components/interaction/Button/Button.tsx
904
+ import { cn as cn21 } from "@boostdev/design-system-foundation";
905
+ import { Fragment as Fragment2, jsx as jsx22, jsxs as jsxs15 } from "react/jsx-runtime";
906
+ function Button({
907
+ children,
908
+ className = "",
909
+ variant = "primary",
910
+ type = "button",
911
+ iconStart,
912
+ iconEnd,
913
+ size = "medium",
914
+ hasPulse = false,
915
+ href,
916
+ target,
917
+ rel,
918
+ disabled,
919
+ onClick,
920
+ ...rest
921
+ }) {
922
+ const classNames = cn21(
923
+ Button_default.button,
924
+ Button_default[`--${variant}`],
925
+ Button_default[`--size_${size}`],
926
+ hasPulse && Button_default["--hasPulse"],
927
+ className
928
+ );
929
+ const allChildren = /* @__PURE__ */ jsxs15(Fragment2, { children: [
930
+ !!iconStart && /* @__PURE__ */ jsx22("span", { className: Button_default.prefix, children: iconStart }),
931
+ children,
932
+ !!iconEnd && /* @__PURE__ */ jsx22("span", { className: Button_default.suffix, children: iconEnd })
933
+ ] });
934
+ if (href) {
935
+ return /* @__PURE__ */ jsx22("a", { className: classNames, href, target, rel, onClick, ...rest, children: allChildren });
936
+ }
937
+ return /* @__PURE__ */ jsx22("button", { type, className: classNames, disabled, onClick, ...rest, children: allChildren });
938
+ }
939
+
940
+ // src/components/interaction/Command/Command.tsx
941
+ import { useState as useState4, useEffect, useRef as useRef3, useId as useId6, useMemo } from "react";
942
+
943
+ // src/components/interaction/Command/Command.module.css
944
+ var Command_default = {};
945
+
946
+ // src/components/interaction/Command/Command.tsx
947
+ import { cn as cn22 } from "@boostdev/design-system-foundation";
948
+ import { jsx as jsx23, jsxs as jsxs16 } from "react/jsx-runtime";
949
+ function Command({
950
+ isOpen,
951
+ onClose,
952
+ items,
953
+ placeholder = "Search commands\u2026",
954
+ className
955
+ }) {
956
+ const [query, setQuery] = useState4("");
957
+ const [activeIndex, setActiveIndex] = useState4(0);
958
+ const dialogRef = useRef3(null);
959
+ const inputRef = useRef3(null);
960
+ const listboxId = useId6();
961
+ const filtered = useMemo(() => {
962
+ const q = query.toLowerCase().trim();
963
+ return q ? items.filter(
964
+ (item) => item.label.toLowerCase().includes(q) || item.description?.toLowerCase().includes(q)
965
+ ) : items;
966
+ }, [query, items]);
967
+ const groups = useMemo(() => {
968
+ const map = /* @__PURE__ */ new Map();
969
+ filtered.forEach((item) => {
970
+ const g = item.group ?? "";
971
+ const list = map.get(g) ?? [];
972
+ list.push(item);
973
+ map.set(g, list);
974
+ });
975
+ return map;
976
+ }, [filtered]);
977
+ useEffect(() => {
978
+ const dialog = dialogRef.current;
979
+ if (!dialog) return;
980
+ if (isOpen) {
981
+ dialog.showModal();
982
+ setQuery("");
983
+ setActiveIndex(0);
984
+ setTimeout(() => inputRef.current?.focus(), 0);
985
+ } else if (dialog.open) {
986
+ dialog.close();
987
+ }
988
+ }, [isOpen]);
989
+ useEffect(() => {
990
+ setActiveIndex(0);
991
+ }, [query]);
992
+ const handleCancel = (e) => {
993
+ e.preventDefault();
994
+ onClose();
995
+ };
996
+ const handleKeyDown = (e) => {
997
+ if (e.key === "ArrowDown") {
998
+ e.preventDefault();
999
+ setActiveIndex((i) => Math.min(i + 1, filtered.length - 1));
1000
+ } else if (e.key === "ArrowUp") {
1001
+ e.preventDefault();
1002
+ setActiveIndex((i) => Math.max(i - 1, 0));
1003
+ } else if (e.key === "Enter") {
1004
+ e.preventDefault();
1005
+ filtered[activeIndex]?.onSelect();
1006
+ onClose();
1007
+ } else if (e.key === "Escape") {
1008
+ onClose();
1009
+ }
1010
+ };
1011
+ const selectItem = (item) => {
1012
+ item.onSelect();
1013
+ onClose();
1014
+ };
1015
+ return /* @__PURE__ */ jsx23(
1016
+ "dialog",
1017
+ {
1018
+ ref: dialogRef,
1019
+ className: cn22(Command_default.dialog, className),
1020
+ "aria-label": "Command palette",
1021
+ onCancel: handleCancel,
1022
+ children: /* @__PURE__ */ jsxs16("div", { className: Command_default.palette, onKeyDown: handleKeyDown, children: [
1023
+ /* @__PURE__ */ jsxs16("div", { className: Command_default.searchRow, children: [
1024
+ /* @__PURE__ */ jsxs16("svg", { "aria-hidden": "true", className: Command_default.searchIcon, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
1025
+ /* @__PURE__ */ jsx23("circle", { cx: "11", cy: "11", r: "8" }),
1026
+ /* @__PURE__ */ jsx23("path", { strokeLinecap: "round", d: "M21 21l-4.35-4.35" })
1027
+ ] }),
1028
+ /* @__PURE__ */ jsx23(
1029
+ "input",
1030
+ {
1031
+ ref: inputRef,
1032
+ type: "search",
1033
+ role: "combobox",
1034
+ "aria-expanded": filtered.length > 0,
1035
+ "aria-controls": listboxId,
1036
+ "aria-autocomplete": "list",
1037
+ "aria-activedescendant": filtered[activeIndex] ? `cmd-${filtered[activeIndex].id}` : void 0,
1038
+ className: Command_default.search,
1039
+ placeholder,
1040
+ value: query,
1041
+ onChange: (e) => setQuery(e.target.value)
1042
+ }
1043
+ ),
1044
+ /* @__PURE__ */ jsx23("kbd", { className: Command_default.escHint, children: "Esc" })
1045
+ ] }),
1046
+ filtered.length > 0 ? /* @__PURE__ */ jsx23("ul", { id: listboxId, role: "listbox", className: Command_default.list, "aria-label": "Commands", children: Array.from(groups.entries()).map(([group, groupItems]) => /* @__PURE__ */ jsxs16("li", { role: "presentation", children: [
1047
+ group && /* @__PURE__ */ jsx23("div", { className: Command_default.group, role: "presentation", children: group }),
1048
+ /* @__PURE__ */ jsx23("ul", { role: "group", "aria-label": group || void 0, className: Command_default.groupList, children: groupItems.map((item) => {
1049
+ const flatIndex = filtered.indexOf(item);
1050
+ const isActive = flatIndex === activeIndex;
1051
+ return /* @__PURE__ */ jsxs16(
1052
+ "li",
1053
+ {
1054
+ id: `cmd-${item.id}`,
1055
+ role: "option",
1056
+ "aria-selected": isActive,
1057
+ className: cn22(Command_default.item, isActive && Command_default.itemActive),
1058
+ onPointerDown: (e) => e.preventDefault(),
1059
+ onClick: () => selectItem(item),
1060
+ children: [
1061
+ /* @__PURE__ */ jsx23("span", { className: Command_default.itemLabel, children: item.label }),
1062
+ item.description && /* @__PURE__ */ jsx23("span", { className: Command_default.itemDesc, children: item.description }),
1063
+ item.shortcut && /* @__PURE__ */ jsx23("kbd", { className: Command_default.shortcut, children: item.shortcut })
1064
+ ]
1065
+ },
1066
+ item.id
1067
+ );
1068
+ }) })
1069
+ ] }, group)) }) : /* @__PURE__ */ jsxs16("div", { className: Command_default.empty, "aria-live": "polite", children: [
1070
+ "No results for \u201C",
1071
+ query,
1072
+ "\u201D"
1073
+ ] })
1074
+ ] })
1075
+ }
1076
+ );
1077
+ }
1078
+
1079
+ // src/components/interaction/Dialog/Dialog.tsx
1080
+ import { useEffect as useEffect2, useRef as useRef4 } from "react";
1081
+
1082
+ // src/components/interaction/Dialog/Dialog.module.css
1083
+ var Dialog_default = {};
1084
+
1085
+ // src/components/interaction/Dialog/Dialog.tsx
1086
+ import { cn as cn23 } from "@boostdev/design-system-foundation";
1087
+ import { jsx as jsx24, jsxs as jsxs17 } from "react/jsx-runtime";
1088
+ function Dialog({ children, isVisible = false, className, handleClose }) {
1089
+ const dialogRef = useRef4(null);
1090
+ useEffect2(() => {
1091
+ const dialog = dialogRef.current;
1092
+ if (!dialog) return;
1093
+ if (isVisible) {
1094
+ dialog.showModal();
1095
+ } else if (dialog.open) {
1096
+ dialog.close();
1097
+ }
1098
+ }, [isVisible]);
1099
+ return /* @__PURE__ */ jsxs17("dialog", { ref: dialogRef, className: cn23(className, Dialog_default.dialog), children: [
1100
+ /* @__PURE__ */ jsx24("form", { method: "dialog", className: Dialog_default.closeForm, children: /* @__PURE__ */ jsx24(
1101
+ "button",
1102
+ {
1103
+ type: "submit",
1104
+ className: Dialog_default.closeButton,
1105
+ onClick: handleClose,
1106
+ "aria-label": "Close dialog",
1107
+ children: /* @__PURE__ */ jsx24("svg", { "aria-hidden": "true", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx24("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M18 6L6 18M6 6l12 12" }) })
1108
+ }
1109
+ ) }),
1110
+ children
1111
+ ] });
1112
+ }
1113
+
1114
+ // src/components/interaction/Drawer/Drawer.tsx
1115
+ import { useEffect as useEffect3, useRef as useRef5 } from "react";
1116
+
1117
+ // src/components/interaction/Drawer/Drawer.module.css
1118
+ var Drawer_default = {};
1119
+
1120
+ // src/components/interaction/Drawer/Drawer.tsx
1121
+ import { cn as cn24 } from "@boostdev/design-system-foundation";
1122
+ import { jsx as jsx25, jsxs as jsxs18 } from "react/jsx-runtime";
1123
+ function Drawer({
1124
+ isOpen,
1125
+ onClose,
1126
+ title,
1127
+ children,
1128
+ side = "right",
1129
+ className
1130
+ }) {
1131
+ const dialogRef = useRef5(null);
1132
+ useEffect3(() => {
1133
+ const dialog = dialogRef.current;
1134
+ if (!dialog) return;
1135
+ if (isOpen) {
1136
+ dialog.showModal();
1137
+ } else if (dialog.open) {
1138
+ dialog.close();
1139
+ }
1140
+ }, [isOpen]);
1141
+ const handleClick = (e) => {
1142
+ if (e.target === dialogRef.current) onClose();
1143
+ };
1144
+ const handleCancel = (e) => {
1145
+ e.preventDefault();
1146
+ onClose();
1147
+ };
1148
+ return /* @__PURE__ */ jsx25(
1149
+ "dialog",
1150
+ {
1151
+ ref: dialogRef,
1152
+ className: cn24(Drawer_default.drawer, Drawer_default[`--side_${side}`], className),
1153
+ "aria-label": title,
1154
+ onClick: handleClick,
1155
+ onCancel: handleCancel,
1156
+ children: /* @__PURE__ */ jsxs18("div", { className: Drawer_default.panel, children: [
1157
+ /* @__PURE__ */ jsxs18("div", { className: Drawer_default.header, children: [
1158
+ /* @__PURE__ */ jsx25("h2", { className: Drawer_default.title, children: title }),
1159
+ /* @__PURE__ */ jsx25(
1160
+ "button",
1161
+ {
1162
+ type: "button",
1163
+ className: Drawer_default.closeButton,
1164
+ onClick: onClose,
1165
+ "aria-label": "Close drawer",
1166
+ children: /* @__PURE__ */ jsx25("svg", { "aria-hidden": "true", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx25("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M18 6L6 18M6 6l12 12" }) })
1167
+ }
1168
+ )
1169
+ ] }),
1170
+ /* @__PURE__ */ jsx25("div", { className: Drawer_default.body, children })
1171
+ ] })
1172
+ }
1173
+ );
1174
+ }
1175
+
1176
+ // src/components/interaction/DropdownMenu/DropdownMenu.tsx
1177
+ import {
1178
+ cloneElement as cloneElement2,
1179
+ isValidElement as isValidElement2,
1180
+ useEffect as useEffect4,
1181
+ useId as useId7,
1182
+ useRef as useRef6,
1183
+ useState as useState5
1184
+ } from "react";
1185
+
1186
+ // src/components/interaction/DropdownMenu/DropdownMenu.module.css
1187
+ var DropdownMenu_default = {};
1188
+
1189
+ // src/components/interaction/DropdownMenu/DropdownMenu.tsx
1190
+ import { cn as cn25 } from "@boostdev/design-system-foundation";
1191
+ import { jsx as jsx26, jsxs as jsxs19 } from "react/jsx-runtime";
1192
+ function DropdownMenu({
1193
+ trigger,
1194
+ items,
1195
+ placement = "bottom-start",
1196
+ className
1197
+ }) {
1198
+ const [isOpen, setIsOpen] = useState5(false);
1199
+ const containerRef = useRef6(null);
1200
+ const menuId = useId7();
1201
+ const itemRefs = useRef6([]);
1202
+ const open = () => {
1203
+ setIsOpen(true);
1204
+ };
1205
+ const close = () => setIsOpen(false);
1206
+ useEffect4(() => {
1207
+ if (isOpen) {
1208
+ itemRefs.current[0]?.focus();
1209
+ }
1210
+ }, [isOpen]);
1211
+ useEffect4(() => {
1212
+ if (!isOpen) return;
1213
+ const handlePointerDown = (e) => {
1214
+ if (!containerRef.current?.contains(e.target)) close();
1215
+ };
1216
+ const handleKeyDown = (e) => {
1217
+ if (e.key === "Escape") close();
1218
+ };
1219
+ document.addEventListener("pointerdown", handlePointerDown);
1220
+ document.addEventListener("keydown", handleKeyDown);
1221
+ return () => {
1222
+ document.removeEventListener("pointerdown", handlePointerDown);
1223
+ document.removeEventListener("keydown", handleKeyDown);
1224
+ };
1225
+ }, [isOpen]);
1226
+ const handleItemKeyDown = (e, index) => {
1227
+ const enabledIndexes = items.map((item, i) => ({ item, i })).filter(({ item }) => !item.disabled).map(({ i }) => i);
1228
+ const pos = enabledIndexes.indexOf(index);
1229
+ if (e.key === "ArrowDown") {
1230
+ e.preventDefault();
1231
+ itemRefs.current[enabledIndexes[(pos + 1) % enabledIndexes.length]]?.focus();
1232
+ } else if (e.key === "ArrowUp") {
1233
+ e.preventDefault();
1234
+ itemRefs.current[enabledIndexes[(pos - 1 + enabledIndexes.length) % enabledIndexes.length]]?.focus();
1235
+ } else if (e.key === "Home") {
1236
+ e.preventDefault();
1237
+ itemRefs.current[enabledIndexes[0]]?.focus();
1238
+ } else if (e.key === "End") {
1239
+ e.preventDefault();
1240
+ itemRefs.current[enabledIndexes[enabledIndexes.length - 1]]?.focus();
1241
+ } else if (e.key === "Tab") {
1242
+ close();
1243
+ }
1244
+ };
1245
+ const triggerEl = isValidElement2(trigger) ? cloneElement2(trigger, {
1246
+ "aria-haspopup": "menu",
1247
+ "aria-expanded": isOpen,
1248
+ "aria-controls": menuId,
1249
+ onClick: (e) => {
1250
+ if (isOpen) {
1251
+ close();
1252
+ } else {
1253
+ open();
1254
+ }
1255
+ const existingOnClick = trigger.props.onClick;
1256
+ if (typeof existingOnClick === "function") existingOnClick(e);
1257
+ }
1258
+ }) : trigger;
1259
+ return /* @__PURE__ */ jsxs19("div", { ref: containerRef, className: cn25(DropdownMenu_default.wrapper, className), children: [
1260
+ triggerEl,
1261
+ isOpen && /* @__PURE__ */ jsx26(
1262
+ "ul",
1263
+ {
1264
+ id: menuId,
1265
+ role: "menu",
1266
+ className: cn25(DropdownMenu_default.menu, DropdownMenu_default[`--placement_${placement}`]),
1267
+ children: items.map((item, index) => /* @__PURE__ */ jsxs19("li", { role: "presentation", children: [
1268
+ item.separator && /* @__PURE__ */ jsx26("hr", { className: DropdownMenu_default.separator, role: "separator" }),
1269
+ /* @__PURE__ */ jsxs19(
1270
+ "button",
1271
+ {
1272
+ ref: (el) => {
1273
+ itemRefs.current[index] = el;
1274
+ },
1275
+ type: "button",
1276
+ role: "menuitem",
1277
+ disabled: item.disabled,
1278
+ className: DropdownMenu_default.item,
1279
+ onClick: () => {
1280
+ item.onClick?.();
1281
+ close();
1282
+ },
1283
+ onKeyDown: (e) => handleItemKeyDown(e, index),
1284
+ children: [
1285
+ item.icon && /* @__PURE__ */ jsx26("span", { className: DropdownMenu_default.icon, "aria-hidden": "true", children: item.icon }),
1286
+ item.label
1287
+ ]
1288
+ }
1289
+ )
1290
+ ] }, item.id))
1291
+ }
1292
+ )
1293
+ ] });
1294
+ }
1295
+
1296
+ // src/components/interaction/Popover/Popover.tsx
1297
+ import {
1298
+ cloneElement as cloneElement3,
1299
+ isValidElement as isValidElement3,
1300
+ useEffect as useEffect5,
1301
+ useId as useId8,
1302
+ useRef as useRef7,
1303
+ useState as useState6
1304
+ } from "react";
1305
+
1306
+ // src/components/interaction/Popover/Popover.module.css
1307
+ var Popover_default = {};
1308
+
1309
+ // src/components/interaction/Popover/Popover.tsx
1310
+ import { cn as cn26 } from "@boostdev/design-system-foundation";
1311
+ import { jsx as jsx27, jsxs as jsxs20 } from "react/jsx-runtime";
1312
+ function Popover({
1313
+ children,
1314
+ content,
1315
+ placement = "bottom",
1316
+ className
1317
+ }) {
1318
+ const [isOpen, setIsOpen] = useState6(false);
1319
+ const containerRef = useRef7(null);
1320
+ const panelId = useId8();
1321
+ useEffect5(() => {
1322
+ if (!isOpen) return;
1323
+ const handlePointerDown = (e) => {
1324
+ if (!containerRef.current?.contains(e.target)) {
1325
+ setIsOpen(false);
1326
+ }
1327
+ };
1328
+ const handleKeyDown = (e) => {
1329
+ if (e.key === "Escape") setIsOpen(false);
1330
+ };
1331
+ document.addEventListener("pointerdown", handlePointerDown);
1332
+ document.addEventListener("keydown", handleKeyDown);
1333
+ return () => {
1334
+ document.removeEventListener("pointerdown", handlePointerDown);
1335
+ document.removeEventListener("keydown", handleKeyDown);
1336
+ };
1337
+ }, [isOpen]);
1338
+ const trigger = isValidElement3(children) ? cloneElement3(children, {
1339
+ "aria-expanded": isOpen,
1340
+ "aria-controls": panelId,
1341
+ onClick: (e) => {
1342
+ setIsOpen((prev) => !prev);
1343
+ const existingOnClick = children.props.onClick;
1344
+ if (typeof existingOnClick === "function") existingOnClick(e);
1345
+ }
1346
+ }) : children;
1347
+ return /* @__PURE__ */ jsxs20("span", { ref: containerRef, className: cn26(Popover_default.wrapper, className), children: [
1348
+ trigger,
1349
+ isOpen && /* @__PURE__ */ jsx27(
1350
+ "div",
1351
+ {
1352
+ id: panelId,
1353
+ role: "dialog",
1354
+ "aria-modal": "false",
1355
+ className: cn26(Popover_default.panel, Popover_default[`--placement_${placement}`]),
1356
+ children: content
1357
+ }
1358
+ )
1359
+ ] });
1360
+ }
1361
+
1362
+ // src/components/interaction/Rating/Rating.module.css
1363
+ var Rating_default = {};
1364
+
1365
+ // src/components/interaction/Rating/Rating.tsx
1366
+ import { cn as cn27 } from "@boostdev/design-system-foundation";
1367
+ import { jsx as jsx28 } from "react/jsx-runtime";
1368
+ function Rating({ value, max = 5, className }) {
1369
+ return /* @__PURE__ */ jsx28(
1370
+ "div",
1371
+ {
1372
+ className: cn27(Rating_default.rating, className),
1373
+ role: "img",
1374
+ "aria-label": `${value} out of ${max} stars`,
1375
+ children: Array.from({ length: max }).map((_, i) => /* @__PURE__ */ jsx28(
1376
+ "svg",
1377
+ {
1378
+ "aria-hidden": "true",
1379
+ className: cn27(Rating_default.star, i < value && Rating_default["--filled"]),
1380
+ fill: "currentColor",
1381
+ viewBox: "0 0 24 24",
1382
+ children: /* @__PURE__ */ jsx28("path", { d: "M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z" })
1383
+ },
1384
+ i
1385
+ ))
1386
+ }
1387
+ );
1388
+ }
1389
+
1390
+ // src/components/interaction/Toast/Toast.tsx
1391
+ import { useState as useState7, useEffect as useEffect6, createContext, useContext, useCallback, useMemo as useMemo2 } from "react";
1392
+
1393
+ // src/components/interaction/Toast/Toast.module.css
1394
+ var Toast_default = {};
1395
+
1396
+ // src/components/interaction/Toast/Toast.tsx
1397
+ import { cn as cn28 } from "@boostdev/design-system-foundation";
1398
+ import { jsx as jsx29, jsxs as jsxs21 } from "react/jsx-runtime";
1399
+ var ToastContext = createContext(void 0);
1400
+ function ToastProvider({ children }) {
1401
+ const [toasts, setToasts] = useState7([]);
1402
+ const showToast = useCallback((message, variant) => {
1403
+ const id = Math.random().toString(36).substring(2, 9);
1404
+ setToasts((prev) => [...prev, { id, message, variant }]);
1405
+ }, []);
1406
+ const removeToast = useCallback((id) => {
1407
+ setToasts((prev) => prev.filter((toast) => toast.id !== id));
1408
+ }, []);
1409
+ const value = useMemo2(() => ({ showToast }), [showToast]);
1410
+ return /* @__PURE__ */ jsxs21(ToastContext.Provider, { value, children: [
1411
+ children,
1412
+ /* @__PURE__ */ jsx29("div", { className: Toast_default.toastContainer, children: toasts.map((toast) => /* @__PURE__ */ jsx29(
1413
+ ToastItem,
1414
+ {
1415
+ toast,
1416
+ onRemove: () => removeToast(toast.id)
1417
+ },
1418
+ toast.id
1419
+ )) })
1420
+ ] });
1421
+ }
1422
+ function ToastItem({ toast, onRemove }) {
1423
+ useEffect6(() => {
1424
+ const timer = setTimeout(onRemove, 5e3);
1425
+ return () => clearTimeout(timer);
1426
+ }, [onRemove]);
1427
+ return /* @__PURE__ */ jsx29("div", { className: cn28(Toast_default.toast, Toast_default[`--variant_${toast.variant}`]), children: toast.message });
1428
+ }
1429
+ function useToast() {
1430
+ const context = useContext(ToastContext);
1431
+ if (!context) {
1432
+ throw new Error("useToast must be used within a ToastProvider");
1433
+ }
1434
+ return context;
1435
+ }
1436
+
1437
+ // src/components/interaction/form/Checkbox/Checkbox.tsx
1438
+ import { useId as useId9 } from "react";
1439
+
1440
+ // src/components/interaction/form/Checkbox/Checkbox.module.css
1441
+ var Checkbox_default = {};
1442
+
1443
+ // src/components/interaction/form/atoms/Message.module.css
1444
+ var Message_default = {};
1445
+
1446
+ // src/components/interaction/form/atoms/Message.tsx
1447
+ import { jsx as jsx30 } from "react/jsx-runtime";
1448
+ var Message = ({ message, type, inputId }) => {
1449
+ if (!message) return null;
1450
+ return /* @__PURE__ */ jsx30("label", { id: inputId + type, htmlFor: inputId, className: Message_default[type], children: message });
1451
+ };
1452
+
1453
+ // src/components/interaction/form/atoms/Label.module.css
1454
+ var Label_default = {};
1455
+
1456
+ // src/components/interaction/form/atoms/Label.tsx
1457
+ import { jsx as jsx31 } from "react/jsx-runtime";
1458
+ var Label = ({ label, id }) => {
1459
+ return /* @__PURE__ */ jsx31("label", { htmlFor: id, className: Label_default.label, children: label });
1460
+ };
1461
+
1462
+ // src/components/interaction/form/Checkbox/Checkbox.tsx
1463
+ import { cn as cn30 } from "@boostdev/design-system-foundation";
1464
+
1465
+ // src/components/interaction/form/atoms/InputContainer.module.css
1466
+ var InputContainer_default = {};
1467
+
1468
+ // src/components/interaction/form/atoms/InputContainer.tsx
1469
+ import { cn as cn29 } from "@boostdev/design-system-foundation";
1470
+ import { jsx as jsx32 } from "react/jsx-runtime";
1471
+ var InputContainer = ({ children, className }) => {
1472
+ return /* @__PURE__ */ jsx32("div", { className: cn29(InputContainer_default.container, className), children });
1473
+ };
1474
+
1475
+ // src/components/interaction/form/Checkbox/Checkbox.tsx
1476
+ import { jsx as jsx33, jsxs as jsxs22 } from "react/jsx-runtime";
1477
+ function Checkbox({ label, name, error, hint, className, ...props }) {
1478
+ const id = name + useId9();
1479
+ const hintId = id + "hint";
1480
+ const errorId = id + "error";
1481
+ const describedBy = !!error ? errorId : hintId;
1482
+ return /* @__PURE__ */ jsxs22(InputContainer, { className: cn30(Checkbox_default.checkboxGroup, className), children: [
1483
+ /* @__PURE__ */ jsxs22("div", { className: Checkbox_default.inputWrapper, children: [
1484
+ /* @__PURE__ */ jsx33(
1485
+ "input",
1486
+ {
1487
+ "aria-describedby": describedBy,
1488
+ type: "checkbox",
1489
+ id,
1490
+ name,
1491
+ className: `${Checkbox_default.checkbox} ${error ? Checkbox_default.checkboxError : ""}`,
1492
+ ...props
1493
+ }
1494
+ ),
1495
+ /* @__PURE__ */ jsx33(Label, { id, label })
1496
+ ] }),
1497
+ /* @__PURE__ */ jsx33(Message, { inputId: id, type: "error", message: error }),
1498
+ /* @__PURE__ */ jsx33(Message, { inputId: id, type: "hint", message: hint })
1499
+ ] });
1500
+ }
1501
+
1502
+ // src/components/interaction/form/Combobox/Combobox.tsx
1503
+ import {
1504
+ useEffect as useEffect7,
1505
+ useId as useId10,
1506
+ useRef as useRef8,
1507
+ useState as useState8
1508
+ } from "react";
1509
+
1510
+ // src/components/interaction/form/Combobox/Combobox.module.css
1511
+ var Combobox_default = {};
1512
+
1513
+ // src/components/interaction/form/Combobox/Combobox.tsx
1514
+ import { cn as cn31 } from "@boostdev/design-system-foundation";
1515
+ import { jsx as jsx34, jsxs as jsxs23 } from "react/jsx-runtime";
1516
+ function Combobox({
1517
+ label,
1518
+ name,
1519
+ options,
1520
+ placeholder,
1521
+ value,
1522
+ onChange,
1523
+ error,
1524
+ hint,
1525
+ className
1526
+ }) {
1527
+ const id = name + useId10();
1528
+ const listboxId = id + "listbox";
1529
+ const hintId = id + "hint";
1530
+ const errorId = id + "error";
1531
+ const describedBy = error ? errorId : hintId;
1532
+ const selectedOption = options.find((o) => o.value === value);
1533
+ const [inputValue, setInputValue] = useState8(selectedOption?.label ?? "");
1534
+ const [isOpen, setIsOpen] = useState8(false);
1535
+ const [highlightedIndex, setHighlightedIndex] = useState8(-1);
1536
+ const containerRef = useRef8(null);
1537
+ const inputRef = useRef8(null);
1538
+ const filtered = options.filter(
1539
+ (o) => o.label.toLowerCase().includes(inputValue.toLowerCase())
1540
+ );
1541
+ const getOptionId = (index) => `${id}-option-${index}`;
1542
+ useEffect7(() => {
1543
+ if (!isOpen) return;
1544
+ const handlePointerDown = (e) => {
1545
+ if (!containerRef.current?.contains(e.target)) setIsOpen(false);
1546
+ };
1547
+ document.addEventListener("pointerdown", handlePointerDown);
1548
+ return () => document.removeEventListener("pointerdown", handlePointerDown);
1549
+ }, [isOpen]);
1550
+ const selectOption = (option) => {
1551
+ setInputValue(option.label);
1552
+ setIsOpen(false);
1553
+ setHighlightedIndex(-1);
1554
+ onChange?.(option.value);
1555
+ };
1556
+ const handleInputChange = (e) => {
1557
+ setInputValue(e.target.value);
1558
+ setIsOpen(true);
1559
+ setHighlightedIndex(-1);
1560
+ };
1561
+ const handleKeyDown = (e) => {
1562
+ const enabledIndexes = filtered.map((opt, i) => ({ opt, i })).filter(({ opt }) => !opt.disabled).map(({ i }) => i);
1563
+ if (e.key === "ArrowDown") {
1564
+ e.preventDefault();
1565
+ if (!isOpen) {
1566
+ setIsOpen(true);
1567
+ return;
1568
+ }
1569
+ const pos = enabledIndexes.indexOf(highlightedIndex);
1570
+ setHighlightedIndex(enabledIndexes[(pos + 1) % enabledIndexes.length] ?? 0);
1571
+ } else if (e.key === "ArrowUp") {
1572
+ e.preventDefault();
1573
+ const pos = enabledIndexes.indexOf(highlightedIndex);
1574
+ setHighlightedIndex(
1575
+ enabledIndexes[(pos - 1 + enabledIndexes.length) % enabledIndexes.length] ?? 0
1576
+ );
1577
+ } else if (e.key === "Enter") {
1578
+ e.preventDefault();
1579
+ if (highlightedIndex >= 0 && filtered[highlightedIndex]) {
1580
+ selectOption(filtered[highlightedIndex]);
1581
+ }
1582
+ } else if (e.key === "Escape") {
1583
+ setIsOpen(false);
1584
+ setHighlightedIndex(-1);
1585
+ } else if (e.key === "Tab") {
1586
+ setIsOpen(false);
1587
+ }
1588
+ };
1589
+ return /* @__PURE__ */ jsxs23(InputContainer, { className: cn31(Combobox_default.formGroup, className), children: [
1590
+ /* @__PURE__ */ jsx34(Label, { id, label }),
1591
+ /* @__PURE__ */ jsxs23("div", { ref: containerRef, className: Combobox_default.inputWrapper, children: [
1592
+ /* @__PURE__ */ jsx34(
1593
+ "input",
1594
+ {
1595
+ ref: inputRef,
1596
+ id,
1597
+ name,
1598
+ type: "text",
1599
+ role: "combobox",
1600
+ "aria-expanded": isOpen,
1601
+ "aria-haspopup": "listbox",
1602
+ "aria-autocomplete": "list",
1603
+ "aria-controls": listboxId,
1604
+ "aria-activedescendant": highlightedIndex >= 0 ? getOptionId(highlightedIndex) : void 0,
1605
+ "aria-invalid": !!error,
1606
+ "aria-describedby": describedBy,
1607
+ autoComplete: "off",
1608
+ placeholder,
1609
+ value: inputValue,
1610
+ className: cn31(Combobox_default.input, error ? Combobox_default.inputError : void 0),
1611
+ onChange: handleInputChange,
1612
+ onKeyDown: handleKeyDown,
1613
+ onFocus: () => setIsOpen(true)
1614
+ }
1615
+ ),
1616
+ /* @__PURE__ */ jsx34("span", { className: Combobox_default.chevron, "aria-hidden": "true", children: /* @__PURE__ */ jsx34("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx34("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 9l6 6 6-6" }) }) }),
1617
+ isOpen && filtered.length > 0 && /* @__PURE__ */ jsx34(
1618
+ "ul",
1619
+ {
1620
+ id: listboxId,
1621
+ role: "listbox",
1622
+ "aria-label": String(label),
1623
+ className: Combobox_default.listbox,
1624
+ children: filtered.map((option, index) => /* @__PURE__ */ jsx34(
1625
+ "li",
1626
+ {
1627
+ id: getOptionId(index),
1628
+ role: "option",
1629
+ "aria-selected": option.value === value,
1630
+ "aria-disabled": option.disabled,
1631
+ className: cn31(
1632
+ Combobox_default.option,
1633
+ index === highlightedIndex ? Combobox_default["--highlighted"] : void 0,
1634
+ option.value === value ? Combobox_default["--selected"] : void 0,
1635
+ option.disabled ? Combobox_default["--disabled"] : void 0
1636
+ ),
1637
+ onPointerDown: (e) => {
1638
+ e.preventDefault();
1639
+ if (!option.disabled) selectOption(option);
1640
+ },
1641
+ children: option.label
1642
+ },
1643
+ option.value
1644
+ ))
1645
+ }
1646
+ )
1647
+ ] }),
1648
+ /* @__PURE__ */ jsx34(Message, { inputId: id, type: "error", message: error }),
1649
+ /* @__PURE__ */ jsx34(Message, { inputId: id, type: "hint", message: hint })
1650
+ ] });
1651
+ }
1652
+
1653
+ // src/components/interaction/form/FileInput/FileInput.tsx
1654
+ import { useId as useId11, useRef as useRef9, useState as useState9 } from "react";
1655
+
1656
+ // src/components/interaction/form/FileInput/FileInput.module.css
1657
+ var FileInput_default = {};
1658
+
1659
+ // src/components/interaction/form/FileInput/FileInput.tsx
1660
+ import { cn as cn32 } from "@boostdev/design-system-foundation";
1661
+ import { Fragment as Fragment3, jsx as jsx35, jsxs as jsxs24 } from "react/jsx-runtime";
1662
+ function FileInput({
1663
+ label,
1664
+ name,
1665
+ accept,
1666
+ multiple = false,
1667
+ disabled = false,
1668
+ error,
1669
+ hint,
1670
+ onChange,
1671
+ className
1672
+ }) {
1673
+ const uid = name + useId11();
1674
+ const hintId = uid + "hint";
1675
+ const errorId = uid + "error";
1676
+ const describedBy = error ? errorId : hintId;
1677
+ const inputRef = useRef9(null);
1678
+ const [isDragging, setIsDragging] = useState9(false);
1679
+ const [fileNames, setFileNames] = useState9([]);
1680
+ const handleFiles = (files) => {
1681
+ if (!files) return;
1682
+ setFileNames(Array.from(files).map((f) => f.name));
1683
+ onChange?.(files);
1684
+ };
1685
+ const handleChange = (e) => handleFiles(e.target.files);
1686
+ const handleDrop = (e) => {
1687
+ e.preventDefault();
1688
+ setIsDragging(false);
1689
+ if (disabled) return;
1690
+ handleFiles(e.dataTransfer.files);
1691
+ };
1692
+ const handleDragOver = (e) => {
1693
+ e.preventDefault();
1694
+ if (!disabled) setIsDragging(true);
1695
+ };
1696
+ const handleDragLeave = () => setIsDragging(false);
1697
+ return /* @__PURE__ */ jsxs24(InputContainer, { className: cn32(FileInput_default.formGroup, className), children: [
1698
+ /* @__PURE__ */ jsx35(Label, { id: uid, label }),
1699
+ /* @__PURE__ */ jsxs24(
1700
+ "label",
1701
+ {
1702
+ htmlFor: uid,
1703
+ className: cn32(FileInput_default.dropZone, isDragging && FileInput_default.isDragging, error && FileInput_default.hasError, disabled && FileInput_default.isDisabled),
1704
+ onDrop: handleDrop,
1705
+ onDragOver: handleDragOver,
1706
+ onDragLeave: handleDragLeave,
1707
+ children: [
1708
+ /* @__PURE__ */ jsx35("svg", { "aria-hidden": "true", className: FileInput_default.icon, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", children: /* @__PURE__ */ jsx35("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M3 16.5v2.25A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021 18.75V16.5m-13.5-9L12 3m0 0l4.5 4.5M12 3v13.5" }) }),
1709
+ /* @__PURE__ */ jsx35("span", { className: FileInput_default.prompt, children: fileNames.length > 0 ? fileNames.join(", ") : /* @__PURE__ */ jsxs24(Fragment3, { children: [
1710
+ /* @__PURE__ */ jsx35("strong", { children: "Click to upload" }),
1711
+ " or drag and drop"
1712
+ ] }) }),
1713
+ accept && /* @__PURE__ */ jsx35("span", { className: FileInput_default.acceptHint, children: accept }),
1714
+ /* @__PURE__ */ jsx35(
1715
+ "input",
1716
+ {
1717
+ ref: inputRef,
1718
+ id: uid,
1719
+ type: "file",
1720
+ name,
1721
+ accept,
1722
+ multiple,
1723
+ disabled,
1724
+ "aria-invalid": !!error,
1725
+ "aria-describedby": describedBy,
1726
+ className: FileInput_default.hiddenInput,
1727
+ onChange: handleChange
1728
+ }
1729
+ )
1730
+ ]
1731
+ }
1732
+ ),
1733
+ /* @__PURE__ */ jsx35(Message, { inputId: uid, type: "error", message: error }),
1734
+ /* @__PURE__ */ jsx35(Message, { inputId: uid, type: "hint", message: hint })
1735
+ ] });
1736
+ }
1737
+
1738
+ // src/components/interaction/form/FormInput/FormInput.tsx
1739
+ import { useId as useId12 } from "react";
1740
+
1741
+ // src/components/interaction/form/FormInput/FormInput.module.css
1742
+ var FormInput_default = {};
1743
+
1744
+ // src/components/interaction/form/FormInput/FormInput.tsx
1745
+ import { cn as cn33 } from "@boostdev/design-system-foundation";
1746
+ import { jsx as jsx36, jsxs as jsxs25 } from "react/jsx-runtime";
1747
+ function FormInput({
1748
+ label,
1749
+ name,
1750
+ ariaLabel,
1751
+ error,
1752
+ hint,
1753
+ className,
1754
+ ...props
1755
+ }) {
1756
+ const id = name + useId12();
1757
+ const hintId = id + "hint";
1758
+ const errorId = id + "error";
1759
+ const describedBy = !!error ? errorId : hintId;
1760
+ return /* @__PURE__ */ jsxs25(InputContainer, { className: cn33(FormInput_default.formGroup, className), children: [
1761
+ /* @__PURE__ */ jsx36(Label, { id, label }),
1762
+ /* @__PURE__ */ jsx36(
1763
+ "input",
1764
+ {
1765
+ "aria-invalid": !!error,
1766
+ "aria-describedby": describedBy,
1767
+ "aria-label": ariaLabel,
1768
+ id,
1769
+ name,
1770
+ className: `${FormInput_default.input} ${error ? FormInput_default.inputError : ""}`,
1771
+ ...props
1772
+ }
1773
+ ),
1774
+ /* @__PURE__ */ jsx36(Message, { inputId: id, type: "error", message: error }),
1775
+ /* @__PURE__ */ jsx36(Message, { inputId: id, type: "hint", message: hint })
1776
+ ] });
1777
+ }
1778
+
1779
+ // src/components/interaction/form/NumberInput/NumberInput.tsx
1780
+ import { useId as useId13, useRef as useRef10 } from "react";
1781
+
1782
+ // src/components/interaction/form/NumberInput/NumberInput.module.css
1783
+ var NumberInput_default = {};
1784
+
1785
+ // src/components/interaction/form/NumberInput/NumberInput.tsx
1786
+ import { cn as cn34 } from "@boostdev/design-system-foundation";
1787
+ import { jsx as jsx37, jsxs as jsxs26 } from "react/jsx-runtime";
1788
+ function NumberInput({
1789
+ label,
1790
+ name,
1791
+ value,
1792
+ defaultValue,
1793
+ min,
1794
+ max,
1795
+ step = 1,
1796
+ disabled = false,
1797
+ error,
1798
+ hint,
1799
+ onChange,
1800
+ className
1801
+ }) {
1802
+ const uid = name + useId13();
1803
+ const hintId = uid + "hint";
1804
+ const errorId = uid + "error";
1805
+ const describedBy = error ? errorId : hintId;
1806
+ const inputRef = useRef10(null);
1807
+ const clamp = (v) => {
1808
+ const withMin = min !== void 0 ? Math.max(min, v) : v;
1809
+ const withMax = max !== void 0 ? Math.min(max, withMin) : withMin;
1810
+ return withMax;
1811
+ };
1812
+ const adjust = (delta) => {
1813
+ if (!inputRef.current) return;
1814
+ const current = parseFloat(inputRef.current.value) || 0;
1815
+ const next = clamp(current + delta);
1816
+ inputRef.current.value = String(next);
1817
+ onChange?.(next);
1818
+ };
1819
+ return /* @__PURE__ */ jsxs26(InputContainer, { className: cn34(NumberInput_default.formGroup, className), children: [
1820
+ /* @__PURE__ */ jsx37(Label, { id: uid, label }),
1821
+ /* @__PURE__ */ jsxs26("div", { className: NumberInput_default.inputRow, children: [
1822
+ /* @__PURE__ */ jsx37(
1823
+ "button",
1824
+ {
1825
+ type: "button",
1826
+ className: NumberInput_default.stepper,
1827
+ "aria-label": "Decrease",
1828
+ disabled: disabled || min !== void 0 && (value ?? defaultValue ?? 0) <= min,
1829
+ onClick: () => adjust(-step),
1830
+ tabIndex: -1,
1831
+ children: /* @__PURE__ */ jsx37("svg", { "aria-hidden": "true", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", children: /* @__PURE__ */ jsx37("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M5 12h14" }) })
1832
+ }
1833
+ ),
1834
+ /* @__PURE__ */ jsx37(
1835
+ "input",
1836
+ {
1837
+ ref: inputRef,
1838
+ id: uid,
1839
+ type: "number",
1840
+ name,
1841
+ defaultValue,
1842
+ value,
1843
+ min,
1844
+ max,
1845
+ step,
1846
+ disabled,
1847
+ "aria-invalid": !!error,
1848
+ "aria-describedby": describedBy,
1849
+ className: cn34(NumberInput_default.input, error ? NumberInput_default.inputError : void 0),
1850
+ onChange: (e) => onChange?.(parseFloat(e.target.value))
1851
+ }
1852
+ ),
1853
+ /* @__PURE__ */ jsx37(
1854
+ "button",
1855
+ {
1856
+ type: "button",
1857
+ className: NumberInput_default.stepper,
1858
+ "aria-label": "Increase",
1859
+ disabled: disabled || max !== void 0 && (value ?? defaultValue ?? 0) >= max,
1860
+ onClick: () => adjust(step),
1861
+ tabIndex: -1,
1862
+ children: /* @__PURE__ */ jsx37("svg", { "aria-hidden": "true", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", children: /* @__PURE__ */ jsx37("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M12 5v14M5 12h14" }) })
1863
+ }
1864
+ )
1865
+ ] }),
1866
+ /* @__PURE__ */ jsx37(Message, { inputId: uid, type: "error", message: error }),
1867
+ /* @__PURE__ */ jsx37(Message, { inputId: uid, type: "hint", message: hint })
1868
+ ] });
1869
+ }
1870
+
1871
+ // src/components/interaction/form/Radio/Radio.tsx
1872
+ import { useId as useId14 } from "react";
1873
+
1874
+ // src/components/interaction/form/Radio/Radio.module.css
1875
+ var Radio_default = {};
1876
+
1877
+ // src/components/interaction/form/Radio/Radio.tsx
1878
+ import { cn as cn35 } from "@boostdev/design-system-foundation";
1879
+ import { jsx as jsx38, jsxs as jsxs27 } from "react/jsx-runtime";
1880
+ function Radio({ label, name, error, hint, className, ...props }) {
1881
+ const id = name + useId14();
1882
+ const hintId = id + "hint";
1883
+ const errorId = id + "error";
1884
+ const describedBy = !!error ? errorId : hintId;
1885
+ return /* @__PURE__ */ jsxs27(InputContainer, { className: cn35(Radio_default.radioGroup, className), children: [
1886
+ /* @__PURE__ */ jsxs27("div", { className: Radio_default.inputWrapper, children: [
1887
+ /* @__PURE__ */ jsx38(
1888
+ "input",
1889
+ {
1890
+ "aria-describedby": describedBy,
1891
+ type: "radio",
1892
+ id,
1893
+ name,
1894
+ className: `${Radio_default.radio} ${error ? Radio_default.radioError : ""}`,
1895
+ ...props
1896
+ }
1897
+ ),
1898
+ /* @__PURE__ */ jsx38(Label, { id, label })
1899
+ ] }),
1900
+ /* @__PURE__ */ jsx38(Message, { inputId: id, type: "error", message: error }),
1901
+ /* @__PURE__ */ jsx38(Message, { inputId: id, type: "hint", message: hint })
1902
+ ] });
1903
+ }
1904
+
1905
+ // src/components/interaction/form/Select/Select.tsx
1906
+ import { useId as useId15 } from "react";
1907
+
1908
+ // src/components/interaction/form/Select/Select.module.css
1909
+ var Select_default = {};
1910
+
1911
+ // src/components/interaction/form/Select/Select.tsx
1912
+ import { cn as cn36 } from "@boostdev/design-system-foundation";
1913
+ import { jsx as jsx39, jsxs as jsxs28 } from "react/jsx-runtime";
1914
+ function Select({
1915
+ label,
1916
+ name,
1917
+ options,
1918
+ placeholder,
1919
+ error,
1920
+ hint,
1921
+ className,
1922
+ ...props
1923
+ }) {
1924
+ const id = name + useId15();
1925
+ const hintId = id + "hint";
1926
+ const errorId = id + "error";
1927
+ const describedBy = error ? errorId : hintId;
1928
+ return /* @__PURE__ */ jsxs28(InputContainer, { className: cn36(Select_default.formGroup, className), children: [
1929
+ /* @__PURE__ */ jsx39(Label, { id, label }),
1930
+ /* @__PURE__ */ jsxs28("div", { className: Select_default.selectWrapper, children: [
1931
+ /* @__PURE__ */ jsxs28(
1932
+ "select",
1933
+ {
1934
+ id,
1935
+ name,
1936
+ "aria-invalid": !!error,
1937
+ "aria-describedby": describedBy,
1938
+ className: cn36(Select_default.select, error ? Select_default.selectError : void 0),
1939
+ ...props,
1940
+ children: [
1941
+ placeholder && /* @__PURE__ */ jsx39("option", { value: "", disabled: true, children: placeholder }),
1942
+ options.map(({ value, label: optLabel, disabled }) => /* @__PURE__ */ jsx39("option", { value, disabled, children: optLabel }, value))
1943
+ ]
1944
+ }
1945
+ ),
1946
+ /* @__PURE__ */ jsx39("span", { className: Select_default.chevron, "aria-hidden": "true", children: /* @__PURE__ */ jsx39("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx39("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 9l6 6 6-6" }) }) })
1947
+ ] }),
1948
+ /* @__PURE__ */ jsx39(Message, { inputId: id, type: "error", message: error }),
1949
+ /* @__PURE__ */ jsx39(Message, { inputId: id, type: "hint", message: hint })
1950
+ ] });
1951
+ }
1952
+
1953
+ // src/components/interaction/form/Slider/Slider.tsx
1954
+ import { useId as useId16, useState as useState10 } from "react";
1955
+
1956
+ // src/components/interaction/form/Slider/Slider.module.css
1957
+ var Slider_default = {};
1958
+
1959
+ // src/components/interaction/form/Slider/Slider.tsx
1960
+ import { cn as cn37 } from "@boostdev/design-system-foundation";
1961
+ import { jsx as jsx40, jsxs as jsxs29 } from "react/jsx-runtime";
1962
+ function Slider({
1963
+ label,
1964
+ name,
1965
+ min = 0,
1966
+ max = 100,
1967
+ showValue = false,
1968
+ error,
1969
+ hint,
1970
+ className,
1971
+ onChange,
1972
+ ...props
1973
+ }) {
1974
+ const id = name + useId16();
1975
+ const hintId = id + "hint";
1976
+ const errorId = id + "error";
1977
+ const describedBy = error ? errorId : hintId;
1978
+ const initialValue = Number(props.value ?? props.defaultValue ?? min);
1979
+ const [currentValue, setCurrentValue] = useState10(initialValue);
1980
+ const fillPct = (currentValue - min) / (max - min) * 100;
1981
+ const handleChange = (e) => {
1982
+ setCurrentValue(Number(e.target.value));
1983
+ onChange?.(e);
1984
+ };
1985
+ return /* @__PURE__ */ jsxs29(InputContainer, { className: cn37(Slider_default.formGroup, className), children: [
1986
+ /* @__PURE__ */ jsxs29("div", { className: Slider_default.labelRow, children: [
1987
+ /* @__PURE__ */ jsx40(Label, { id, label }),
1988
+ showValue && /* @__PURE__ */ jsx40("span", { className: Slider_default.value, children: currentValue })
1989
+ ] }),
1990
+ /* @__PURE__ */ jsx40(
1991
+ "input",
1992
+ {
1993
+ type: "range",
1994
+ id,
1995
+ name,
1996
+ min,
1997
+ max,
1998
+ "aria-describedby": describedBy,
1999
+ "aria-valuemin": min,
2000
+ "aria-valuemax": max,
2001
+ "aria-valuenow": currentValue,
2002
+ className: cn37(Slider_default.slider, error ? Slider_default.sliderError : void 0),
2003
+ style: { "--slider_fill": `${fillPct}%` },
2004
+ onChange: handleChange,
2005
+ ...props
2006
+ }
2007
+ ),
2008
+ /* @__PURE__ */ jsx40(Message, { inputId: id, type: "error", message: error }),
2009
+ /* @__PURE__ */ jsx40(Message, { inputId: id, type: "hint", message: hint })
2010
+ ] });
2011
+ }
2012
+
2013
+ // src/components/interaction/form/Switch/Switch.tsx
2014
+ import { useId as useId17 } from "react";
2015
+
2016
+ // src/components/interaction/form/Switch/Switch.module.css
2017
+ var Switch_default = {};
2018
+
2019
+ // src/components/interaction/form/Switch/Switch.tsx
2020
+ import { cn as cn38 } from "@boostdev/design-system-foundation";
2021
+ import { jsx as jsx41, jsxs as jsxs30 } from "react/jsx-runtime";
2022
+ function Switch({
2023
+ label,
2024
+ name,
2025
+ size = "medium",
2026
+ error,
2027
+ hint,
2028
+ className,
2029
+ ...props
2030
+ }) {
2031
+ const id = name + useId17();
2032
+ const hintId = id + "hint";
2033
+ const errorId = id + "error";
2034
+ const describedBy = error ? errorId : hintId;
2035
+ return /* @__PURE__ */ jsxs30(InputContainer, { className: cn38(Switch_default.switchGroup, Switch_default[`--size_${size}`], className), children: [
2036
+ /* @__PURE__ */ jsxs30("div", { className: Switch_default.inputWrapper, children: [
2037
+ /* @__PURE__ */ jsxs30("div", { className: Switch_default.trackWrapper, children: [
2038
+ /* @__PURE__ */ jsx41(
2039
+ "input",
2040
+ {
2041
+ type: "checkbox",
2042
+ role: "switch",
2043
+ id,
2044
+ name,
2045
+ "aria-describedby": describedBy,
2046
+ className: cn38(Switch_default.switch, error ? Switch_default.switchError : void 0),
2047
+ ...props
2048
+ }
2049
+ ),
2050
+ /* @__PURE__ */ jsx41("span", { className: Switch_default.track, "aria-hidden": "true", children: /* @__PURE__ */ jsx41("span", { className: Switch_default.thumb }) })
2051
+ ] }),
2052
+ /* @__PURE__ */ jsx41(Label, { id, label })
2053
+ ] }),
2054
+ /* @__PURE__ */ jsx41(Message, { inputId: id, type: "error", message: error }),
2055
+ /* @__PURE__ */ jsx41(Message, { inputId: id, type: "hint", message: hint })
2056
+ ] });
2057
+ }
2058
+
2059
+ // src/components/interaction/form/Textarea/Textarea.tsx
2060
+ import { useId as useId18 } from "react";
2061
+
2062
+ // src/components/interaction/form/Textarea/Textarea.module.css
2063
+ var Textarea_default = {};
2064
+
2065
+ // src/components/interaction/form/Textarea/Textarea.tsx
2066
+ import { cn as cn39 } from "@boostdev/design-system-foundation";
2067
+ import { jsx as jsx42, jsxs as jsxs31 } from "react/jsx-runtime";
2068
+ function Textarea({
2069
+ label,
2070
+ name,
2071
+ error,
2072
+ hint,
2073
+ className,
2074
+ ...props
2075
+ }) {
2076
+ const id = name + useId18();
2077
+ const hintId = id + "hint";
2078
+ const errorId = id + "error";
2079
+ const describedBy = error ? errorId : hintId;
2080
+ return /* @__PURE__ */ jsxs31(InputContainer, { className: cn39(Textarea_default.formGroup, className), children: [
2081
+ /* @__PURE__ */ jsx42(Label, { id, label }),
2082
+ /* @__PURE__ */ jsx42(
2083
+ "textarea",
2084
+ {
2085
+ id,
2086
+ name,
2087
+ "aria-invalid": !!error,
2088
+ "aria-describedby": describedBy,
2089
+ className: cn39(Textarea_default.textarea, error ? Textarea_default.textareaError : void 0),
2090
+ ...props
2091
+ }
2092
+ ),
2093
+ /* @__PURE__ */ jsx42(Message, { inputId: id, type: "error", message: error }),
2094
+ /* @__PURE__ */ jsx42(Message, { inputId: id, type: "hint", message: hint })
2095
+ ] });
2096
+ }
2097
+
2098
+ // src/components/layout/ButtonGroup/ButtonGroup.module.css
2099
+ var ButtonGroup_default = {};
2100
+
2101
+ // src/components/layout/ButtonGroup/ButtonGroup.tsx
2102
+ import { cn as cn40 } from "@boostdev/design-system-foundation";
2103
+ import { jsx as jsx43 } from "react/jsx-runtime";
2104
+ function ButtonGroup({ children, className, variant }) {
2105
+ return /* @__PURE__ */ jsx43("div", { className: cn40(ButtonGroup_default.buttonGroup, className, variant && ButtonGroup_default[`--variant__${variant}`]), children: /* @__PURE__ */ jsx43("div", { className: ButtonGroup_default.container, children }) });
2106
+ }
2107
+
2108
+ // src/components/layout/Card/Card.module.css
2109
+ var Card_default = {};
2110
+
2111
+ // src/components/layout/Card/Card.tsx
2112
+ import { cn as cn41 } from "@boostdev/design-system-foundation";
2113
+ import { jsx as jsx44 } from "react/jsx-runtime";
2114
+ function Card({
2115
+ children,
2116
+ className,
2117
+ variant = "default",
2118
+ padding = "medium",
2119
+ textAlign = "start",
2120
+ style,
2121
+ onClick
2122
+ }) {
2123
+ const classNames = cn41(
2124
+ Card_default.card,
2125
+ Card_default[`--${variant}`],
2126
+ Card_default[`--padding-${padding}`],
2127
+ Card_default[`--text-${textAlign}`],
2128
+ onClick && Card_default["--clickable"],
2129
+ className
2130
+ );
2131
+ const Component = onClick ? "button" : "div";
2132
+ return /* @__PURE__ */ jsx44(
2133
+ Component,
2134
+ {
2135
+ className: classNames,
2136
+ onClick,
2137
+ style,
2138
+ ...onClick && { type: "button" },
2139
+ children
2140
+ }
2141
+ );
2142
+ }
2143
+
2144
+ // src/components/layout/SectionHeader/SectionHeader.module.css
2145
+ var SectionHeader_default = {};
2146
+
2147
+ // src/components/layout/SectionHeader/SectionHeader.tsx
2148
+ import { cn as cn42 } from "@boostdev/design-system-foundation";
2149
+ import { jsx as jsx45, jsxs as jsxs32 } from "react/jsx-runtime";
2150
+ function SectionHeader({
2151
+ title,
2152
+ subtitle,
2153
+ className,
2154
+ alignment = "start",
2155
+ size = "medium",
2156
+ titleAs = "h2"
2157
+ }) {
2158
+ const Title = titleAs;
2159
+ return /* @__PURE__ */ jsxs32("header", { className: cn42(SectionHeader_default.sectionHeader, SectionHeader_default[`--${alignment}`], SectionHeader_default[`--${size}`], className), children: [
2160
+ /* @__PURE__ */ jsx45(Title, { className: SectionHeader_default.title, children: title }),
2161
+ subtitle && /* @__PURE__ */ jsx45("p", { className: SectionHeader_default.subtitle, children: subtitle })
2162
+ ] });
2163
+ }
2164
+
2165
+ // src/components/layout/IconWrapper/IconWrapper.module.css
2166
+ var IconWrapper_default = {};
2167
+
2168
+ // src/components/layout/IconWrapper/IconWrapper.tsx
2169
+ import { cn as cn43 } from "@boostdev/design-system-foundation";
2170
+ import { jsx as jsx46 } from "react/jsx-runtime";
2171
+ function IconWrapper({ children, className }) {
2172
+ return /* @__PURE__ */ jsx46("div", { className: cn43(className, IconWrapper_default.wrapper), children });
2173
+ }
2174
+
2175
+ // src/index.ts
2176
+ import { cn as cn44 } from "@boostdev/design-system-foundation";
2177
+ export {
2178
+ Accordion,
2179
+ Alert,
2180
+ Avatar,
2181
+ Badge,
2182
+ Breadcrumb,
2183
+ Button,
2184
+ ButtonGroup,
2185
+ Calendar,
2186
+ Card,
2187
+ Carousel,
2188
+ Checkbox,
2189
+ Combobox,
2190
+ Command,
2191
+ DescriptionList,
2192
+ Dialog,
2193
+ Drawer,
2194
+ DropdownMenu,
2195
+ FileInput,
2196
+ FormInput,
2197
+ IconWrapper,
2198
+ Link,
2199
+ Loading,
2200
+ NotificationBanner,
2201
+ NumberInput,
2202
+ Pagination,
2203
+ Popover,
2204
+ Progress,
2205
+ ProgressCircle,
2206
+ Radio,
2207
+ Rating,
2208
+ SectionHeader,
2209
+ Select,
2210
+ Separator,
2211
+ Skeleton,
2212
+ SkipLink,
2213
+ Slider,
2214
+ Switch,
2215
+ Table,
2216
+ Tabs,
2217
+ Textarea,
2218
+ ToastProvider,
2219
+ Tooltip,
2220
+ Typography,
2221
+ cn44 as cn,
2222
+ useToast
2223
+ };