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