@jiwambe/components 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (179) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +367 -0
  3. package/dist/client.d.ts +40 -0
  4. package/dist/client.d.ts.map +1 -0
  5. package/dist/client.js +46 -0
  6. package/dist/client.js.map +1 -0
  7. package/dist/components/Accordion/Accordion.d.ts +74 -0
  8. package/dist/components/Accordion/Accordion.d.ts.map +1 -0
  9. package/dist/components/Accordion/Accordion.js +297 -0
  10. package/dist/components/Accordion/Accordion.js.map +1 -0
  11. package/dist/components/Box/Box.d.ts +56 -0
  12. package/dist/components/Box/Box.d.ts.map +1 -0
  13. package/dist/components/Box/Box.js +51 -0
  14. package/dist/components/Box/Box.js.map +1 -0
  15. package/dist/components/Breadcrumb/Breadcrumb.d.ts +66 -0
  16. package/dist/components/Breadcrumb/Breadcrumb.d.ts.map +1 -0
  17. package/dist/components/Button/Button.d.ts +54 -0
  18. package/dist/components/Button/Button.d.ts.map +1 -0
  19. package/dist/components/Button/Button.js +92 -0
  20. package/dist/components/Button/Button.js.map +1 -0
  21. package/dist/components/Card/Card.d.ts +54 -0
  22. package/dist/components/Card/Card.d.ts.map +1 -0
  23. package/dist/components/Card/Card.js +98 -0
  24. package/dist/components/Card/Card.js.map +1 -0
  25. package/dist/components/CheckboxGroup/CheckboxGroup.d.ts +61 -0
  26. package/dist/components/CheckboxGroup/CheckboxGroup.d.ts.map +1 -0
  27. package/dist/components/CheckboxGroup/CheckboxGroup.js +205 -0
  28. package/dist/components/CheckboxGroup/CheckboxGroup.js.map +1 -0
  29. package/dist/components/Container/Container.d.ts +72 -0
  30. package/dist/components/Container/Container.d.ts.map +1 -0
  31. package/dist/components/Container/Container.js +69 -0
  32. package/dist/components/Container/Container.js.map +1 -0
  33. package/dist/components/DateInput/DateInput.d.ts +61 -0
  34. package/dist/components/DateInput/DateInput.d.ts.map +1 -0
  35. package/dist/components/DateInput/DateInput.js +234 -0
  36. package/dist/components/DateInput/DateInput.js.map +1 -0
  37. package/dist/components/Divider/Divider.d.ts +44 -0
  38. package/dist/components/Divider/Divider.d.ts.map +1 -0
  39. package/dist/components/Divider/Divider.js +35 -0
  40. package/dist/components/Divider/Divider.js.map +1 -0
  41. package/dist/components/Drawer/Drawer.d.ts +35 -0
  42. package/dist/components/Drawer/Drawer.d.ts.map +1 -0
  43. package/dist/components/Drawer/Drawer.js +37 -0
  44. package/dist/components/Drawer/Drawer.js.map +1 -0
  45. package/dist/components/FAQ/FAQ.d.ts +40 -0
  46. package/dist/components/FAQ/FAQ.d.ts.map +1 -0
  47. package/dist/components/FAQ/FAQ.js +161 -0
  48. package/dist/components/FAQ/FAQ.js.map +1 -0
  49. package/dist/components/Grid/Grid.d.ts +61 -0
  50. package/dist/components/Grid/Grid.d.ts.map +1 -0
  51. package/dist/components/Grid/Grid.js +95 -0
  52. package/dist/components/Grid/Grid.js.map +1 -0
  53. package/dist/components/Icon/Icon.d.ts +21 -0
  54. package/dist/components/Icon/Icon.d.ts.map +1 -0
  55. package/dist/components/Icon/Icon.js +167 -0
  56. package/dist/components/Icon/Icon.js.map +1 -0
  57. package/dist/components/Link/Link.d.ts +49 -0
  58. package/dist/components/Link/Link.d.ts.map +1 -0
  59. package/dist/components/Link/Link.js +70 -0
  60. package/dist/components/Link/Link.js.map +1 -0
  61. package/dist/components/List/List.d.ts +36 -0
  62. package/dist/components/List/List.d.ts.map +1 -0
  63. package/dist/components/List/List.js +42 -0
  64. package/dist/components/List/List.js.map +1 -0
  65. package/dist/components/List/index.d.ts +3 -0
  66. package/dist/components/List/index.d.ts.map +1 -0
  67. package/dist/components/Overlay/Overlay.d.ts +35 -0
  68. package/dist/components/Overlay/Overlay.d.ts.map +1 -0
  69. package/dist/components/Overlay/Overlay.js +51 -0
  70. package/dist/components/Overlay/Overlay.js.map +1 -0
  71. package/dist/components/PhoneInput/PhoneInput.d.ts +55 -0
  72. package/dist/components/PhoneInput/PhoneInput.d.ts.map +1 -0
  73. package/dist/components/PhoneInput/PhoneInput.js +255 -0
  74. package/dist/components/PhoneInput/PhoneInput.js.map +1 -0
  75. package/dist/components/Popover/Popover.d.ts +46 -0
  76. package/dist/components/Popover/Popover.d.ts.map +1 -0
  77. package/dist/components/Popover/Popover.js +57 -0
  78. package/dist/components/Popover/Popover.js.map +1 -0
  79. package/dist/components/ProductImage/ProductImage.d.ts +78 -0
  80. package/dist/components/ProductImage/ProductImage.d.ts.map +1 -0
  81. package/dist/components/ProductImage/ProductImage.js +220 -0
  82. package/dist/components/ProductImage/ProductImage.js.map +1 -0
  83. package/dist/components/RadioGroup/RadioGroup.d.ts +63 -0
  84. package/dist/components/RadioGroup/RadioGroup.d.ts.map +1 -0
  85. package/dist/components/RadioGroup/RadioGroup.js +233 -0
  86. package/dist/components/RadioGroup/RadioGroup.js.map +1 -0
  87. package/dist/components/Section/Section.d.ts +44 -0
  88. package/dist/components/Section/Section.d.ts.map +1 -0
  89. package/dist/components/Section/Section.js +48 -0
  90. package/dist/components/Section/Section.js.map +1 -0
  91. package/dist/components/Select/Select.d.ts +47 -0
  92. package/dist/components/Select/Select.d.ts.map +1 -0
  93. package/dist/components/Select/Select.js +153 -0
  94. package/dist/components/Select/Select.js.map +1 -0
  95. package/dist/components/SelectTab/SelectTab.d.ts +62 -0
  96. package/dist/components/SelectTab/SelectTab.d.ts.map +1 -0
  97. package/dist/components/SelectTab/SelectTab.js +192 -0
  98. package/dist/components/SelectTab/SelectTab.js.map +1 -0
  99. package/dist/components/Skeleton/Skeleton.d.ts +87 -0
  100. package/dist/components/Skeleton/Skeleton.d.ts.map +1 -0
  101. package/dist/components/Skeleton/Skeleton.js +97 -0
  102. package/dist/components/Skeleton/Skeleton.js.map +1 -0
  103. package/dist/components/Skeleton/index.d.ts +3 -0
  104. package/dist/components/Skeleton/index.d.ts.map +1 -0
  105. package/dist/components/Slider/Slider.d.ts +47 -0
  106. package/dist/components/Slider/Slider.d.ts.map +1 -0
  107. package/dist/components/Slider/Slider.js +147 -0
  108. package/dist/components/Slider/Slider.js.map +1 -0
  109. package/dist/components/Stack/Stack.d.ts +145 -0
  110. package/dist/components/Stack/Stack.d.ts.map +1 -0
  111. package/dist/components/Stack/Stack.js +80 -0
  112. package/dist/components/Stack/Stack.js.map +1 -0
  113. package/dist/components/Tab/Tab.d.ts +38 -0
  114. package/dist/components/Tab/Tab.d.ts.map +1 -0
  115. package/dist/components/Tab/Tab.js +146 -0
  116. package/dist/components/Tab/Tab.js.map +1 -0
  117. package/dist/components/TextArea/TextArea.d.ts +32 -0
  118. package/dist/components/TextArea/TextArea.d.ts.map +1 -0
  119. package/dist/components/TextArea/TextArea.js +118 -0
  120. package/dist/components/TextArea/TextArea.js.map +1 -0
  121. package/dist/components/TextInput/TextInput.d.ts +35 -0
  122. package/dist/components/TextInput/TextInput.d.ts.map +1 -0
  123. package/dist/components/TextInput/TextInput.js +128 -0
  124. package/dist/components/TextInput/TextInput.js.map +1 -0
  125. package/dist/components/Toggle/Toggle.d.ts +83 -0
  126. package/dist/components/Toggle/Toggle.d.ts.map +1 -0
  127. package/dist/components/Toggle/Toggle.js +121 -0
  128. package/dist/components/Toggle/Toggle.js.map +1 -0
  129. package/dist/components/Typography/Typography.d.ts +321 -0
  130. package/dist/components/Typography/Typography.d.ts.map +1 -0
  131. package/dist/components/Typography/Typography.js +21 -0
  132. package/dist/components/Typography/Typography.js.map +1 -0
  133. package/dist/components/UploadInput/UploadInput.d.ts +39 -0
  134. package/dist/components/UploadInput/UploadInput.d.ts.map +1 -0
  135. package/dist/components/UploadInput/UploadInput.js +297 -0
  136. package/dist/components/UploadInput/UploadInput.js.map +1 -0
  137. package/dist/components/index.d.ts +65 -0
  138. package/dist/components/index.d.ts.map +1 -0
  139. package/dist/index.d.ts +7 -0
  140. package/dist/index.d.ts.map +1 -0
  141. package/dist/index.js +69 -0
  142. package/dist/index.js.map +1 -0
  143. package/dist/plugin/jiwambe-plugin.d.ts +37 -0
  144. package/dist/plugin/jiwambe-plugin.d.ts.map +1 -0
  145. package/dist/plugin/jiwambe-plugin.js +640 -0
  146. package/dist/plugin/jiwambe-plugin.js.map +1 -0
  147. package/dist/server.d.ts +22 -0
  148. package/dist/server.d.ts.map +1 -0
  149. package/dist/server.js +23 -0
  150. package/dist/server.js.map +1 -0
  151. package/dist/types/index.d.ts +103 -0
  152. package/dist/types/index.d.ts.map +1 -0
  153. package/dist/types/layout.d.ts +138 -0
  154. package/dist/types/layout.d.ts.map +1 -0
  155. package/dist/types/list.d.ts +69 -0
  156. package/dist/types/list.d.ts.map +1 -0
  157. package/dist/types/list.js +9 -0
  158. package/dist/types/list.js.map +1 -0
  159. package/dist/types/skeleton.d.ts +38 -0
  160. package/dist/types/skeleton.d.ts.map +1 -0
  161. package/dist/types/skeleton.js +13 -0
  162. package/dist/types/skeleton.js.map +1 -0
  163. package/dist/types/spacing.d.ts +105 -0
  164. package/dist/types/spacing.d.ts.map +1 -0
  165. package/dist/utils/layoutClasses.d.ts +44 -0
  166. package/dist/utils/layoutClasses.d.ts.map +1 -0
  167. package/dist/utils/layoutClasses.js +88 -0
  168. package/dist/utils/layoutClasses.js.map +1 -0
  169. package/dist/utils/responsive-props.d.ts +60 -0
  170. package/dist/utils/responsive-props.d.ts.map +1 -0
  171. package/dist/utils/responsive-props.js +184 -0
  172. package/dist/utils/responsive-props.js.map +1 -0
  173. package/dist/utils/spacing.d.ts +52 -0
  174. package/dist/utils/spacing.d.ts.map +1 -0
  175. package/dist/utils/spacing.js +625 -0
  176. package/dist/utils/spacing.js.map +1 -0
  177. package/package.json +96 -0
  178. package/tailwind.preset.d.ts +3 -0
  179. package/tailwind.preset.ts +21 -0
@@ -0,0 +1,297 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { useId, useState, useEffect, useRef, useCallback } from "react";
4
+ function ChevronIcon({ className }) {
5
+ return /* @__PURE__ */ jsx(
6
+ "svg",
7
+ {
8
+ className,
9
+ width: "24",
10
+ height: "24",
11
+ viewBox: "0 0 24 24",
12
+ fill: "none",
13
+ stroke: "currentColor",
14
+ strokeWidth: "1.5",
15
+ strokeLinecap: "round",
16
+ strokeLinejoin: "round",
17
+ "aria-hidden": "true",
18
+ children: /* @__PURE__ */ jsx("path", { d: "M6 9l6 6 6-6" })
19
+ }
20
+ );
21
+ }
22
+ function triggerStyles(variant, disabled) {
23
+ const base = "flex w-full items-center justify-between py-space-4 px-space-4 text-form-text font-medium text-left transition-colors outline-none";
24
+ if (disabled) {
25
+ switch (variant) {
26
+ case "secondary":
27
+ return `${base} bg-fill-action-primary-disabled text-text-inverse-disabled cursor-not-allowed`;
28
+ case "inverse":
29
+ return `${base} text-text-disabled cursor-not-allowed`;
30
+ default:
31
+ return `${base} text-text-disabled cursor-not-allowed`;
32
+ }
33
+ }
34
+ switch (variant) {
35
+ case "secondary":
36
+ return `${base} bg-fill-action-primary text-text-primary-inverse hover:bg-fill-action-primary-hover active:bg-fill-action-primary-active focus-visible:outline-none cursor-pointer`;
37
+ case "inverse":
38
+ return `${base} text-text-primary hover:bg-fill-bg-secondary active:bg-fill-bg-secondary focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-border-focus cursor-pointer`;
39
+ default:
40
+ return `${base} text-text-primary hover:bg-fill-bg-secondary active:bg-fill-bg-secondary focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-border-focus cursor-pointer`;
41
+ }
42
+ }
43
+ function panelStyles(variant, disabled) {
44
+ if (disabled) {
45
+ switch (variant) {
46
+ case "secondary":
47
+ return "px-space-4 pb-space-4 text-text-sm text-text-inverse-disabled bg-fill-action-primary-disabled";
48
+ default:
49
+ return "px-space-4 pb-space-4 text-text-sm text-text-disabled";
50
+ }
51
+ }
52
+ switch (variant) {
53
+ case "secondary":
54
+ return "px-space-4 pb-space-4 text-text-sm text-text-primary-inverse bg-fill-action-primary";
55
+ default:
56
+ return "px-space-4 pb-space-4 text-text-sm text-text-secondary";
57
+ }
58
+ }
59
+ function wrapperBorder(variant) {
60
+ switch (variant) {
61
+ case "secondary":
62
+ return "";
63
+ default:
64
+ return "divide-y divide-neutral-200 border-b border-neutral-200";
65
+ }
66
+ }
67
+ function itemBorder(variant) {
68
+ switch (variant) {
69
+ case "secondary":
70
+ return "rounded-rad-md overflow-hidden focus-within:outline-[1.5px] focus-within:outline-border-focus focus-within:outline-offset-[3px] focus-within:rounded-rad-lg";
71
+ default:
72
+ return "";
73
+ }
74
+ }
75
+ function Accordion({ items, variant = "primary", defaultOpenIndex, value, onChange, className = "", style, ref, ...rest }) {
76
+ const baseId = useId();
77
+ const isControlled = value !== void 0;
78
+ const [internalOpen, setInternalOpen] = useState(defaultOpenIndex ?? -1);
79
+ const openIndex = isControlled ? value : internalOpen;
80
+ useEffect(() => {
81
+ if (!isControlled && defaultOpenIndex !== void 0) {
82
+ setInternalOpen(defaultOpenIndex);
83
+ }
84
+ }, [defaultOpenIndex, isControlled]);
85
+ const triggerRefs = useRef([]);
86
+ const toggle = useCallback(
87
+ (index) => {
88
+ const next = openIndex === index ? -1 : index;
89
+ if (isControlled) {
90
+ onChange == null ? void 0 : onChange(next);
91
+ } else {
92
+ setInternalOpen(next);
93
+ }
94
+ },
95
+ [openIndex, isControlled, onChange]
96
+ );
97
+ const focusTrigger = (index) => {
98
+ var _a;
99
+ (_a = triggerRefs.current[index]) == null ? void 0 : _a.focus();
100
+ };
101
+ const handleKeyDown = (e, index) => {
102
+ const enabledIndices = items.map((item, i) => item.disabled ? -1 : i).filter((i) => i !== -1);
103
+ const currentPos = enabledIndices.indexOf(index);
104
+ switch (e.key) {
105
+ case "ArrowDown": {
106
+ e.preventDefault();
107
+ focusTrigger(enabledIndices[(currentPos + 1) % enabledIndices.length]);
108
+ break;
109
+ }
110
+ case "ArrowUp": {
111
+ e.preventDefault();
112
+ focusTrigger(enabledIndices[(currentPos - 1 + enabledIndices.length) % enabledIndices.length]);
113
+ break;
114
+ }
115
+ case "Home": {
116
+ e.preventDefault();
117
+ focusTrigger(enabledIndices[0]);
118
+ break;
119
+ }
120
+ case "End": {
121
+ e.preventDefault();
122
+ focusTrigger(enabledIndices[enabledIndices.length - 1]);
123
+ break;
124
+ }
125
+ }
126
+ };
127
+ return /* @__PURE__ */ jsx(
128
+ "div",
129
+ {
130
+ ref,
131
+ className: `w-full ${wrapperBorder(variant)} ${variant === "secondary" ? "flex flex-col gap-space-2" : ""} ${className}`,
132
+ style,
133
+ ...rest,
134
+ children: items.map((item, index) => {
135
+ const isOpen = openIndex === index;
136
+ const triggerId = `${baseId}-trigger-${index}`;
137
+ const panelId = `${baseId}-panel-${index}`;
138
+ const disabled = !!item.disabled;
139
+ return /* @__PURE__ */ jsxs("div", { className: itemBorder(variant), children: [
140
+ /* @__PURE__ */ jsx("h3", { children: /* @__PURE__ */ jsxs(
141
+ "button",
142
+ {
143
+ ref: (el) => {
144
+ triggerRefs.current[index] = el;
145
+ },
146
+ id: triggerId,
147
+ type: "button",
148
+ className: triggerStyles(variant, disabled),
149
+ "aria-expanded": isOpen,
150
+ "aria-controls": panelId,
151
+ "aria-disabled": disabled || void 0,
152
+ disabled,
153
+ onClick: () => toggle(index),
154
+ onKeyDown: (e) => handleKeyDown(e, index),
155
+ children: [
156
+ /* @__PURE__ */ jsx("span", { children: item.title }),
157
+ /* @__PURE__ */ jsx(
158
+ ChevronIcon,
159
+ {
160
+ className: `h-6 w-6 shrink-0 transition-transform duration-200 ${isOpen ? "rotate-180" : ""}`
161
+ }
162
+ )
163
+ ]
164
+ }
165
+ ) }),
166
+ /* @__PURE__ */ jsx(
167
+ "div",
168
+ {
169
+ id: panelId,
170
+ role: "region",
171
+ "aria-labelledby": triggerId,
172
+ className: `overflow-hidden transition-all duration-200 ease-in-out ${isOpen ? "max-h-[2000px] opacity-100" : "max-h-0 opacity-0"}`,
173
+ children: /* @__PURE__ */ jsx("div", { className: panelStyles(variant, disabled), children: item.content })
174
+ }
175
+ )
176
+ ] }, index);
177
+ })
178
+ }
179
+ );
180
+ }
181
+ function AccordionSpecs({ items, layout = "vertical", defaultOpenIndex, value, onChange, className = "", style, ref, ...rest }) {
182
+ const baseId = useId();
183
+ const isControlled = value !== void 0;
184
+ const [internalOpen, setInternalOpen] = useState(defaultOpenIndex ?? -1);
185
+ const openIndex = isControlled ? value : internalOpen;
186
+ useEffect(() => {
187
+ if (!isControlled && defaultOpenIndex !== void 0) {
188
+ setInternalOpen(defaultOpenIndex);
189
+ }
190
+ }, [defaultOpenIndex, isControlled]);
191
+ const triggerRefs = useRef([]);
192
+ const toggle = useCallback(
193
+ (index) => {
194
+ const next = openIndex === index ? -1 : index;
195
+ if (isControlled) {
196
+ onChange == null ? void 0 : onChange(next);
197
+ } else {
198
+ setInternalOpen(next);
199
+ }
200
+ },
201
+ [openIndex, isControlled, onChange]
202
+ );
203
+ const focusTrigger = (index) => {
204
+ var _a;
205
+ (_a = triggerRefs.current[index]) == null ? void 0 : _a.focus();
206
+ };
207
+ const handleKeyDown = (e, index) => {
208
+ const enabledIndices = items.map((item, i) => item.disabled ? -1 : i).filter((i) => i !== -1);
209
+ const currentPos = enabledIndices.indexOf(index);
210
+ switch (e.key) {
211
+ case "ArrowDown": {
212
+ e.preventDefault();
213
+ focusTrigger(enabledIndices[(currentPos + 1) % enabledIndices.length]);
214
+ break;
215
+ }
216
+ case "ArrowUp": {
217
+ e.preventDefault();
218
+ focusTrigger(enabledIndices[(currentPos - 1 + enabledIndices.length) % enabledIndices.length]);
219
+ break;
220
+ }
221
+ case "Home": {
222
+ e.preventDefault();
223
+ focusTrigger(enabledIndices[0]);
224
+ break;
225
+ }
226
+ case "End": {
227
+ e.preventDefault();
228
+ focusTrigger(enabledIndices[enabledIndices.length - 1]);
229
+ break;
230
+ }
231
+ }
232
+ };
233
+ return /* @__PURE__ */ jsx(
234
+ "div",
235
+ {
236
+ ref,
237
+ className: `w-full divide-y divide-neutral-200 border-b border-neutral-200 ${className}`,
238
+ style,
239
+ ...rest,
240
+ children: items.map((item, index) => {
241
+ const isOpen = openIndex === index;
242
+ const triggerId = `${baseId}-spec-trigger-${index}`;
243
+ const panelId = `${baseId}-spec-panel-${index}`;
244
+ const disabled = !!item.disabled;
245
+ return /* @__PURE__ */ jsxs("div", { children: [
246
+ /* @__PURE__ */ jsx("h3", { children: /* @__PURE__ */ jsxs(
247
+ "button",
248
+ {
249
+ ref: (el) => {
250
+ triggerRefs.current[index] = el;
251
+ },
252
+ id: triggerId,
253
+ type: "button",
254
+ className: `flex w-full items-center justify-between py-space-4 px-space-4 text-form-text font-medium text-left transition-colors outline-none ${disabled ? "text-text-disabled cursor-not-allowed" : "text-text-primary hover:bg-fill-bg-secondary active:bg-fill-bg-secondary focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-border-focus cursor-pointer"}`,
255
+ "aria-expanded": isOpen,
256
+ "aria-controls": panelId,
257
+ "aria-disabled": disabled || void 0,
258
+ disabled,
259
+ onClick: () => toggle(index),
260
+ onKeyDown: (e) => handleKeyDown(e, index),
261
+ children: [
262
+ /* @__PURE__ */ jsx("span", { children: item.title }),
263
+ /* @__PURE__ */ jsx(
264
+ ChevronIcon,
265
+ {
266
+ className: `h-6 w-6 shrink-0 transition-transform duration-200 ${isOpen ? "rotate-180" : ""}`
267
+ }
268
+ )
269
+ ]
270
+ }
271
+ ) }),
272
+ /* @__PURE__ */ jsx(
273
+ "div",
274
+ {
275
+ id: panelId,
276
+ role: "region",
277
+ "aria-labelledby": triggerId,
278
+ className: `overflow-hidden transition-all duration-200 ease-in-out ${isOpen ? "max-h-[4000px] opacity-100" : "max-h-0 opacity-0"}`,
279
+ children: /* @__PURE__ */ jsx("div", { className: `px-space-4 pb-space-4 ${disabled ? "opacity-50" : ""}`, children: layout === "horizontal" ? /* @__PURE__ */ jsx("div", { className: "grid grid-cols-4 gap-space-2", children: item.specs.map((spec, si) => /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-space-1", children: [
280
+ /* @__PURE__ */ jsx("span", { className: "text-text-xs text-text-secondary", children: spec.label }),
281
+ /* @__PURE__ */ jsx("span", { className: "text-text-sm text-text-primary", children: spec.value })
282
+ ] }, si)) }) : /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-space-3", children: item.specs.map((spec, si) => /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-space-1", children: [
283
+ /* @__PURE__ */ jsx("span", { className: "text-text-xs text-text-secondary", children: spec.label }),
284
+ /* @__PURE__ */ jsx("span", { className: "text-text-sm text-text-primary", children: spec.value })
285
+ ] }, si)) }) })
286
+ }
287
+ )
288
+ ] }, index);
289
+ })
290
+ }
291
+ );
292
+ }
293
+ export {
294
+ Accordion,
295
+ AccordionSpecs
296
+ };
297
+ //# sourceMappingURL=Accordion.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Accordion.js","sources":["../../../src/components/Accordion/Accordion.tsx"],"sourcesContent":["'use client';\n\nimport React, { useState, useRef, useCallback, useId, useEffect } from 'react';\nimport type { AccordionItem, AccordionVariant, AccordionSpecItem } from '../../types';\n\n// ---------------------------------------------------------------------------\n// Chevron icon\n// ---------------------------------------------------------------------------\n\nfunction ChevronIcon({ className }: { className?: string }) {\n return (\n <svg\n className={className}\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M6 9l6 6 6-6\" />\n </svg>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Variant style helpers\n// ---------------------------------------------------------------------------\n\nfunction triggerStyles(variant: AccordionVariant, disabled: boolean) {\n const base =\n 'flex w-full items-center justify-between py-space-4 px-space-4 text-form-text font-medium text-left transition-colors outline-none';\n\n if (disabled) {\n switch (variant) {\n case 'secondary':\n return `${base} bg-fill-action-primary-disabled text-text-inverse-disabled cursor-not-allowed`;\n case 'inverse':\n return `${base} text-text-disabled cursor-not-allowed`;\n default:\n return `${base} text-text-disabled cursor-not-allowed`;\n }\n }\n\n switch (variant) {\n case 'secondary':\n return `${base} bg-fill-action-primary text-text-primary-inverse hover:bg-fill-action-primary-hover active:bg-fill-action-primary-active focus-visible:outline-none cursor-pointer`;\n case 'inverse':\n return `${base} text-text-primary hover:bg-fill-bg-secondary active:bg-fill-bg-secondary focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-border-focus cursor-pointer`;\n default:\n return `${base} text-text-primary hover:bg-fill-bg-secondary active:bg-fill-bg-secondary focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-border-focus cursor-pointer`;\n }\n}\n\nfunction panelStyles(variant: AccordionVariant, disabled: boolean) {\n if (disabled) {\n switch (variant) {\n case 'secondary':\n return 'px-space-4 pb-space-4 text-text-sm text-text-inverse-disabled bg-fill-action-primary-disabled';\n default:\n return 'px-space-4 pb-space-4 text-text-sm text-text-disabled';\n }\n }\n switch (variant) {\n case 'secondary':\n return 'px-space-4 pb-space-4 text-text-sm text-text-primary-inverse bg-fill-action-primary';\n default:\n return 'px-space-4 pb-space-4 text-text-sm text-text-secondary';\n }\n}\n\nfunction wrapperBorder(variant: AccordionVariant) {\n switch (variant) {\n case 'secondary':\n return '';\n default:\n return 'divide-y divide-neutral-200 border-b border-neutral-200';\n }\n}\n\nfunction itemBorder(variant: AccordionVariant) {\n switch (variant) {\n case 'secondary':\n return 'rounded-rad-md overflow-hidden focus-within:outline-[1.5px] focus-within:outline-border-focus focus-within:outline-offset-[3px] focus-within:rounded-rad-lg';\n default:\n return '';\n }\n}\n\n// ---------------------------------------------------------------------------\n// Accordion (text variant)\n// ---------------------------------------------------------------------------\n\n/**\n * Props for the Accordion component. Each item has title, content, and optional disabled.\n */\nexport interface AccordionProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange'> {\n /**\n * Array of accordion items. Each item: title (string), content (ReactNode), disabled? (boolean).\n * @see AccordionItem\n */\n items: AccordionItem[];\n /**\n * Visual style of the accordion. 'primary' — neutral background, dividers; 'secondary' — filled\n * trigger panels; 'inverse' — for use on dark backgrounds.\n * @default 'primary'\n */\n variant?: AccordionVariant;\n /** Index of the panel open by default (uncontrolled). -1 = none. @default undefined */\n defaultOpenIndex?: number;\n /** Controlled open index. When set, accordion is controlled; use with onChange. @default undefined */\n value?: number;\n /** Called when the open panel changes (controlled). Receives the new index or -1 when closed. @default undefined */\n onChange?: (index: number) => void;\n /** Forwarded ref for the root div. @default undefined */\n ref?: React.Ref<HTMLDivElement>;\n}\n\n/**\n * Accordion of expandable panels. Renders a list of triggers; each expands to show its\n * content. Use for FAQs, disclosure sections, or any collapsible content. Supports\n * controlled (value/onChange) or uncontrolled (defaultOpenIndex) usage.\n *\n * @example\n * <Accordion items={[{ title: 'Section 1', content: <p>Content here.</p> }]} variant=\"primary\" />\n *\n * @example\n * <Accordion items={faqItems} defaultOpenIndex={0} variant=\"secondary\" />\n */\nexport function Accordion({ items, variant = 'primary', defaultOpenIndex, value, onChange, className = '', style, ref, ...rest }: AccordionProps) {\n const baseId = useId();\n const isControlled = value !== undefined;\n\n const [internalOpen, setInternalOpen] = useState<number>(defaultOpenIndex ?? -1);\n const openIndex = isControlled ? value : internalOpen;\n\n useEffect(() => {\n if (!isControlled && defaultOpenIndex !== undefined) {\n setInternalOpen(defaultOpenIndex);\n }\n }, [defaultOpenIndex, isControlled]);\n\n const triggerRefs = useRef<(HTMLButtonElement | null)[]>([]);\n\n const toggle = useCallback(\n (index: number) => {\n const next = openIndex === index ? -1 : index;\n if (isControlled) {\n onChange?.(next);\n } else {\n setInternalOpen(next);\n }\n },\n [openIndex, isControlled, onChange],\n );\n\n const focusTrigger = (index: number) => {\n triggerRefs.current[index]?.focus();\n };\n\n const handleKeyDown = (e: React.KeyboardEvent, index: number) => {\n const enabledIndices = items\n .map((item, i) => (item.disabled ? -1 : i))\n .filter((i) => i !== -1);\n const currentPos = enabledIndices.indexOf(index);\n\n switch (e.key) {\n case 'ArrowDown': {\n e.preventDefault();\n focusTrigger(enabledIndices[(currentPos + 1) % enabledIndices.length]);\n break;\n }\n case 'ArrowUp': {\n e.preventDefault();\n focusTrigger(enabledIndices[(currentPos - 1 + enabledIndices.length) % enabledIndices.length]);\n break;\n }\n case 'Home': {\n e.preventDefault();\n focusTrigger(enabledIndices[0]);\n break;\n }\n case 'End': {\n e.preventDefault();\n focusTrigger(enabledIndices[enabledIndices.length - 1]);\n break;\n }\n }\n };\n\n return (\n <div\n ref={ref}\n className={`w-full ${wrapperBorder(variant)} ${variant === 'secondary' ? 'flex flex-col gap-space-2' : ''} ${className}`}\n style={style}\n {...rest}\n >\n {items.map((item, index) => {\n const isOpen = openIndex === index;\n const triggerId = `${baseId}-trigger-${index}`;\n const panelId = `${baseId}-panel-${index}`;\n const disabled = !!item.disabled;\n\n return (\n <div key={index} className={itemBorder(variant)}>\n <h3>\n <button\n ref={(el) => { triggerRefs.current[index] = el; }}\n id={triggerId}\n type=\"button\"\n className={triggerStyles(variant, disabled)}\n aria-expanded={isOpen}\n aria-controls={panelId}\n aria-disabled={disabled || undefined}\n disabled={disabled}\n onClick={() => toggle(index)}\n onKeyDown={(e) => handleKeyDown(e, index)}\n >\n <span>{item.title}</span>\n <ChevronIcon\n className={`h-6 w-6 shrink-0 transition-transform duration-200 ${isOpen ? 'rotate-180' : ''}`}\n />\n </button>\n </h3>\n <div\n id={panelId}\n role=\"region\"\n aria-labelledby={triggerId}\n className={`overflow-hidden transition-all duration-200 ease-in-out ${\n isOpen ? 'max-h-[2000px] opacity-100' : 'max-h-0 opacity-0'\n }`}\n >\n <div className={panelStyles(variant, disabled)}>\n {item.content}\n </div>\n </div>\n </div>\n );\n })}\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// AccordionSpecs (product-specs variant)\n// ---------------------------------------------------------------------------\n\n/**\n * Props for AccordionSpecs. Each item has title and an array of label-value specs.\n */\nexport interface AccordionSpecsProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange'> {\n /**\n * Array of spec items. Each item: title (string), specs (array of { label, value }), disabled? (boolean).\n * @see AccordionSpecItem\n */\n items: AccordionSpecItem[];\n /**\n * Layout of label-value pairs when expanded. 'vertical' — stacked; 'horizontal' — grid row.\n * @default 'vertical'\n */\n layout?: 'vertical' | 'horizontal';\n /** Index of the panel open by default (uncontrolled). -1 = none. @default undefined */\n defaultOpenIndex?: number;\n /** Controlled open index. Use with onChange. @default undefined */\n value?: number;\n /** Called when the open panel changes. @default undefined */\n onChange?: (index: number) => void;\n /** Forwarded ref for the root div. @default undefined */\n ref?: React.Ref<HTMLDivElement>;\n}\n\n/**\n * Accordion that displays label-value pairs when expanded. Use for product specs, feature\n * lists, or any key-value content. Same expand/collapse behaviour as Accordion; items\n * use AccordionSpecItem (title + specs array) instead of raw content.\n *\n * @example\n * <AccordionSpecs items={[{ title: 'Engine', specs: [{ label: 'Type', value: '1.2L' }] }]} />\n *\n * @example\n * <AccordionSpecs items={specItems} layout=\"horizontal\" defaultOpenIndex={0} />\n */\nexport function AccordionSpecs({ items, layout = 'vertical', defaultOpenIndex, value, onChange, className = '', style, ref, ...rest }: AccordionSpecsProps) {\n const baseId = useId();\n const isControlled = value !== undefined;\n\n const [internalOpen, setInternalOpen] = useState<number>(defaultOpenIndex ?? -1);\n const openIndex = isControlled ? value : internalOpen;\n\n useEffect(() => {\n if (!isControlled && defaultOpenIndex !== undefined) {\n setInternalOpen(defaultOpenIndex);\n }\n }, [defaultOpenIndex, isControlled]);\n\n const triggerRefs = useRef<(HTMLButtonElement | null)[]>([]);\n\n const toggle = useCallback(\n (index: number) => {\n const next = openIndex === index ? -1 : index;\n if (isControlled) {\n onChange?.(next);\n } else {\n setInternalOpen(next);\n }\n },\n [openIndex, isControlled, onChange],\n );\n\n const focusTrigger = (index: number) => {\n triggerRefs.current[index]?.focus();\n };\n\n const handleKeyDown = (e: React.KeyboardEvent, index: number) => {\n const enabledIndices = items\n .map((item, i) => (item.disabled ? -1 : i))\n .filter((i) => i !== -1);\n const currentPos = enabledIndices.indexOf(index);\n\n switch (e.key) {\n case 'ArrowDown': {\n e.preventDefault();\n focusTrigger(enabledIndices[(currentPos + 1) % enabledIndices.length]);\n break;\n }\n case 'ArrowUp': {\n e.preventDefault();\n focusTrigger(enabledIndices[(currentPos - 1 + enabledIndices.length) % enabledIndices.length]);\n break;\n }\n case 'Home': {\n e.preventDefault();\n focusTrigger(enabledIndices[0]);\n break;\n }\n case 'End': {\n e.preventDefault();\n focusTrigger(enabledIndices[enabledIndices.length - 1]);\n break;\n }\n }\n };\n\n return (\n <div\n ref={ref}\n className={`w-full divide-y divide-neutral-200 border-b border-neutral-200 ${className}`}\n style={style}\n {...rest}\n >\n {items.map((item, index) => {\n const isOpen = openIndex === index;\n const triggerId = `${baseId}-spec-trigger-${index}`;\n const panelId = `${baseId}-spec-panel-${index}`;\n const disabled = !!item.disabled;\n\n return (\n <div key={index}>\n <h3>\n <button\n ref={(el) => { triggerRefs.current[index] = el; }}\n id={triggerId}\n type=\"button\"\n className={`flex w-full items-center justify-between py-space-4 px-space-4 text-form-text font-medium text-left transition-colors outline-none ${\n disabled\n ? 'text-text-disabled cursor-not-allowed'\n : 'text-text-primary hover:bg-fill-bg-secondary active:bg-fill-bg-secondary focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-border-focus cursor-pointer'\n }`}\n aria-expanded={isOpen}\n aria-controls={panelId}\n aria-disabled={disabled || undefined}\n disabled={disabled}\n onClick={() => toggle(index)}\n onKeyDown={(e) => handleKeyDown(e, index)}\n >\n <span>{item.title}</span>\n <ChevronIcon\n className={`h-6 w-6 shrink-0 transition-transform duration-200 ${isOpen ? 'rotate-180' : ''}`}\n />\n </button>\n </h3>\n <div\n id={panelId}\n role=\"region\"\n aria-labelledby={triggerId}\n className={`overflow-hidden transition-all duration-200 ease-in-out ${\n isOpen ? 'max-h-[4000px] opacity-100' : 'max-h-0 opacity-0'\n }`}\n >\n <div className={`px-space-4 pb-space-4 ${disabled ? 'opacity-50' : ''}`}>\n {layout === 'horizontal' ? (\n <div className=\"grid grid-cols-4 gap-space-2\">\n {item.specs.map((spec, si) => (\n <div key={si} className=\"flex flex-col gap-space-1\">\n <span className=\"text-text-xs text-text-secondary\">{spec.label}</span>\n <span className=\"text-text-sm text-text-primary\">{spec.value}</span>\n </div>\n ))}\n </div>\n ) : (\n <div className=\"flex flex-col gap-space-3\">\n {item.specs.map((spec, si) => (\n <div key={si} className=\"flex flex-col gap-space-1\">\n <span className=\"text-text-xs text-text-secondary\">{spec.label}</span>\n <span className=\"text-text-sm text-text-primary\">{spec.value}</span>\n </div>\n ))}\n </div>\n )}\n </div>\n </div>\n </div>\n );\n })}\n </div>\n );\n}\n"],"names":[],"mappings":";;;AASA;AACE;AACE;AAAC;AAAA;AACC;AACM;AACC;AACC;AACH;AACE;AACK;AACE;AACC;AACH;AAEW;AAAA;AAG7B;AAMA;AACE;AAGA;AACE;AAAQ;AAEJ;AAAc;AAEd;AAAc;AAEd;AAAc;AAAA;AAIpB;AAAQ;AAEJ;AAAc;AAEd;AAAc;AAEd;AAAc;AAEpB;AAEA;AACE;AACE;AAAQ;AAEJ;AAAO;AAEP;AAAO;AAAA;AAGb;AAAQ;AAEJ;AAAO;AAEP;AAAO;AAEb;AAEA;AACE;AAAQ;AAEJ;AAAO;AAEP;AAAO;AAEb;AAEA;AACE;AAAQ;AAEJ;AAAO;AAEP;AAAO;AAEb;AA0CO;AACH;AACA;AAEA;AACA;AAEA;AACE;AACE;AAAgC;AAClC;AAGF;AAEA;AAAe;AAEX;AACA;AACE;AAAW;AAEX;AAAoB;AACtB;AACF;AACkC;AAGpC;;AACE;AAA4B;AAG9B;AACE;AAGA;AAEA;AAAU;AAEN;AACA;AACA;AAAA;AACF;AAEE;AACA;AACA;AAAA;AACF;AAEE;AACA;AACA;AAAA;AACF;AAEE;AACA;AACA;AAAA;AACF;AAAA;AAIJ;AACE;AAAC;AAAA;AACC;AACsH;AACtH;AACI;AAGF;AACA;AACA;AACA;AAEA;AAEI;AACE;AAAC;AAAA;AACgB;AAA6B;AAAI;AAC5C;AACC;AACqC;AAC3B;AACA;AACY;AAC3B;AAC2B;AACa;AAExC;AAAkB;AAClB;AAAC;AAAA;AAC4F;AAAA;AAAA;AAC7F;AAAA;AAEJ;AACA;AAAC;AAAA;AACK;AACC;AACY;AAGjB;AAIA;AAAA;AAAA;AAEJ;AAEH;AAAA;AAGT;AAyCO;AACH;AACA;AAEA;AACA;AAEA;AACE;AACE;AAAgC;AAClC;AAGF;AAEA;AAAe;AAEX;AACA;AACE;AAAW;AAEX;AAAoB;AACtB;AACF;AACkC;AAGpC;;AACE;AAA4B;AAG9B;AACE;AAGA;AAEA;AAAU;AAEN;AACA;AACA;AAAA;AACF;AAEE;AACA;AACA;AAAA;AACF;AAEE;AACA;AACA;AAAA;AACF;AAEE;AACA;AACA;AAAA;AACF;AAAA;AAIJ;AACE;AAAC;AAAA;AACC;AACsF;AACtF;AACI;AAGF;AACA;AACA;AACA;AAEA;AAEI;AACE;AAAC;AAAA;AACgB;AAA6B;AAAI;AAC5C;AACC;AAKL;AACe;AACA;AACY;AAC3B;AAC2B;AACa;AAExC;AAAkB;AAClB;AAAC;AAAA;AAC4F;AAAA;AAAA;AAC7F;AAAA;AAEJ;AACA;AAAC;AAAA;AACK;AACC;AACY;AAGjB;AAOU;AAA+D;AACF;AAQ7D;AAA+D;AACF;AAKvE;AAAA;AAAA;AAEJ;AAEH;AAAA;AAGT;;;;;"}
@@ -0,0 +1,56 @@
1
+ import { default as React } from 'react';
2
+ import { SystemProps, ResponsiveValue } from '../../utils/responsive-props';
3
+ import { SpacingProps } from '../../types/spacing';
4
+ import { LayoutProps } from '../../types/layout';
5
+ type SystemPropsWithoutSpacing = Omit<SystemProps, 'p' | 'px' | 'py' | 'pt' | 'pb' | 'pl' | 'pr' | 'm' | 'mx' | 'my' | 'mt' | 'mb' | 'ml' | 'mr'>;
6
+ /** Omit display so LayoutProps (class-based) takes precedence over SystemProps (inline). */
7
+ type SystemPropsWithoutSpacingAndDisplay = Omit<SystemPropsWithoutSpacing, 'display'>;
8
+ /**
9
+ * Props for the Box component. Extends HTML attributes, system props
10
+ * (dimensions, position, flex), SpacingProps, and LayoutProps.
11
+ */
12
+ export interface BoxProps extends Omit<React.HTMLAttributes<HTMLElement>, 'display'>, SystemPropsWithoutSpacingAndDisplay, SpacingProps, LayoutProps {
13
+ /**
14
+ * The HTML element or React component to render as the root element.
15
+ * Accepts any valid HTML tag string ('div', 'section', 'article',
16
+ * 'span', 'main', 'aside', 'header', 'footer', 'nav', 'ul', 'ol' etc.)
17
+ * or a React component type.
18
+ *
19
+ * Use this to maintain correct semantic HTML without sacrificing
20
+ * design system layout control.
21
+ * @default 'div'
22
+ */
23
+ as?: React.ElementType;
24
+ /** Forwarded ref for the root element. @default undefined */
25
+ ref?: React.Ref<HTMLElement>;
26
+ /** Child content. @default undefined */
27
+ children?: React.ReactNode;
28
+ }
29
+ /**
30
+ * General-purpose layout primitive. Renders any HTML element via the
31
+ * as prop (default: div). Use Box when you need box-model control
32
+ * (spacing, sizing) or display/alignment props on an arbitrary element.
33
+ * Prefer Stack for linear sequences, Grid for multi-column layouts,
34
+ * and Container for page-width constraints.
35
+ *
36
+ * @example
37
+ * // Basic spacing
38
+ * <Box p="space-4" mt="space-8">Content</Box>
39
+ *
40
+ * @example
41
+ * // Inline flex wrapper
42
+ * <Box as="span" display="inline-flex" alignItems="center">
43
+ * <Icon />
44
+ * Label
45
+ * </Box>
46
+ *
47
+ * @example
48
+ * // Semantic section element
49
+ * <Box as="section" py="fluid-8-16">Content</Box>
50
+ */
51
+ export declare function Box({ as: Tag, children, className, style, ref, ...allRest }: BoxProps): import("react/jsx-runtime").JSX.Element;
52
+ export declare namespace Box {
53
+ var displayName: string;
54
+ }
55
+ export type { ResponsiveValue };
56
+ //# sourceMappingURL=Box.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Box.d.ts","sourceRoot":"","sources":["../../../src/components/Box/Box.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAGL,KAAK,WAAW,EAChB,KAAK,eAAe,EACrB,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAItD,KAAK,yBAAyB,GAAG,IAAI,CACnC,WAAW,EACX,GAAG,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,GAAG,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAC9F,CAAC;AAEF,4FAA4F;AAC5F,KAAK,mCAAmC,GAAG,IAAI,CAAC,yBAAyB,EAAE,SAAS,CAAC,CAAC;AAEtF;;;GAGG;AACH,MAAM,WAAW,QACf,SAAQ,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,WAAW,CAAC,EAAE,SAAS,CAAC,EACxD,mCAAmC,EACnC,YAAY,EACZ,WAAW;IACb;;;;;;;;;OASG;IACH,EAAE,CAAC,EAAE,KAAK,CAAC,WAAW,CAAC;IACvB,6DAA6D;IAC7D,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAC7B,wCAAwC;IACxC,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,GAAG,CAAC,EAClB,EAAE,EAAE,GAAW,EACf,QAAQ,EACR,SAAc,EACd,KAAK,EACL,GAAG,EACH,GAAG,OAAO,EACX,EAAE,QAAQ,2CAyCV;yBAhDe,GAAG;;;AAoDnB,YAAY,EAAE,eAAe,EAAE,CAAC"}
@@ -0,0 +1,51 @@
1
+ import { jsxs, Fragment } from "react/jsx-runtime";
2
+ import React from "react";
3
+ import { stripSystemProps, renderSystemProps } from "../../utils/responsive-props.js";
4
+ import { SPACING_PROP_KEYS, resolveSpacing } from "../../utils/spacing.js";
5
+ import { LAYOUT_PROP_KEYS, resolveLayout } from "../../utils/layoutClasses.js";
6
+ function Box({
7
+ as: Tag = "div",
8
+ children,
9
+ className = "",
10
+ style,
11
+ ref,
12
+ ...allRest
13
+ }) {
14
+ const systemPropsOnly = { ...allRest };
15
+ for (const key of SPACING_PROP_KEYS) {
16
+ delete systemPropsOnly[key];
17
+ }
18
+ for (const key of LAYOUT_PROP_KEYS) {
19
+ delete systemPropsOnly[key];
20
+ }
21
+ const rest = stripSystemProps(allRest);
22
+ const domRest = { ...rest };
23
+ for (const key of LAYOUT_PROP_KEYS) {
24
+ delete domRest[key];
25
+ }
26
+ const { style: systemStyle, styleTag, dataId } = renderSystemProps(
27
+ systemPropsOnly,
28
+ style
29
+ );
30
+ const spacingClasses = resolveSpacing(allRest);
31
+ const layoutClasses = resolveLayout(allRest);
32
+ const mergedClassName = [layoutClasses, spacingClasses, className].filter(Boolean).join(" ");
33
+ const elementProps = {
34
+ ref,
35
+ className: mergedClassName || void 0,
36
+ style: systemStyle,
37
+ ...domRest
38
+ };
39
+ if (dataId) {
40
+ elementProps["data-jds"] = dataId;
41
+ }
42
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
43
+ styleTag,
44
+ React.createElement(Tag, elementProps, children)
45
+ ] });
46
+ }
47
+ Box.displayName = "Box";
48
+ export {
49
+ Box
50
+ };
51
+ //# sourceMappingURL=Box.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Box.js","sources":["../../../src/components/Box/Box.tsx"],"sourcesContent":["import React from 'react';\nimport {\n renderSystemProps,\n stripSystemProps,\n type SystemProps,\n type ResponsiveValue,\n} from '../../utils/responsive-props';\nimport type { SpacingProps } from '../../types/spacing';\nimport type { LayoutProps } from '../../types/layout';\nimport { resolveSpacing, SPACING_PROP_KEYS } from '../../utils/spacing';\nimport { resolveLayout, LAYOUT_PROP_KEYS } from '../../utils/layoutClasses';\n\ntype SystemPropsWithoutSpacing = Omit<\n SystemProps,\n 'p' | 'px' | 'py' | 'pt' | 'pb' | 'pl' | 'pr' | 'm' | 'mx' | 'my' | 'mt' | 'mb' | 'ml' | 'mr'\n>;\n\n/** Omit display so LayoutProps (class-based) takes precedence over SystemProps (inline). */\ntype SystemPropsWithoutSpacingAndDisplay = Omit<SystemPropsWithoutSpacing, 'display'>;\n\n/**\n * Props for the Box component. Extends HTML attributes, system props\n * (dimensions, position, flex), SpacingProps, and LayoutProps.\n */\nexport interface BoxProps\n extends Omit<React.HTMLAttributes<HTMLElement>, 'display'>,\n SystemPropsWithoutSpacingAndDisplay,\n SpacingProps,\n LayoutProps {\n /**\n * The HTML element or React component to render as the root element.\n * Accepts any valid HTML tag string ('div', 'section', 'article',\n * 'span', 'main', 'aside', 'header', 'footer', 'nav', 'ul', 'ol' etc.)\n * or a React component type.\n *\n * Use this to maintain correct semantic HTML without sacrificing\n * design system layout control.\n * @default 'div'\n */\n as?: React.ElementType;\n /** Forwarded ref for the root element. @default undefined */\n ref?: React.Ref<HTMLElement>;\n /** Child content. @default undefined */\n children?: React.ReactNode;\n}\n\n/**\n * General-purpose layout primitive. Renders any HTML element via the\n * as prop (default: div). Use Box when you need box-model control\n * (spacing, sizing) or display/alignment props on an arbitrary element.\n * Prefer Stack for linear sequences, Grid for multi-column layouts,\n * and Container for page-width constraints.\n *\n * @example\n * // Basic spacing\n * <Box p=\"space-4\" mt=\"space-8\">Content</Box>\n *\n * @example\n * // Inline flex wrapper\n * <Box as=\"span\" display=\"inline-flex\" alignItems=\"center\">\n * <Icon />\n * Label\n * </Box>\n *\n * @example\n * // Semantic section element\n * <Box as=\"section\" py=\"fluid-8-16\">Content</Box>\n */\nexport function Box({\n as: Tag = 'div',\n children,\n className = '',\n style,\n ref,\n ...allRest\n}: BoxProps) {\n const systemPropsOnly = { ...allRest };\n for (const key of SPACING_PROP_KEYS) {\n delete (systemPropsOnly as Record<string, unknown>)[key];\n }\n for (const key of LAYOUT_PROP_KEYS) {\n delete (systemPropsOnly as Record<string, unknown>)[key];\n }\n const rest = stripSystemProps(allRest);\n const domRest = { ...rest };\n for (const key of LAYOUT_PROP_KEYS) {\n delete (domRest as Record<string, unknown>)[key];\n }\n const { style: systemStyle, styleTag, dataId } = renderSystemProps(\n systemPropsOnly as SystemPropsWithoutSpacingAndDisplay,\n style,\n );\n\n const spacingClasses = resolveSpacing(allRest);\n const layoutClasses = resolveLayout(allRest as LayoutProps);\n const mergedClassName = [layoutClasses, spacingClasses, className]\n .filter(Boolean)\n .join(' ');\n\n const elementProps: Record<string, unknown> = {\n ref,\n className: mergedClassName || undefined,\n style: systemStyle,\n ...domRest,\n };\n\n if (dataId) {\n elementProps['data-jds'] = dataId;\n }\n\n return (\n <>\n {styleTag}\n {React.createElement(Tag, elementProps, children)}\n </>\n );\n}\n\nBox.displayName = 'Box';\n\nexport type { ResponsiveValue };\n"],"names":[],"mappings":";;;;;AAoEO,SAAS,IAAI;AAAA,EAClB,IAAI,MAAM;AAAA,EACV;AAAA,EACA,YAAY;AAAA,EACZ;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAAa;AACX,QAAM,kBAAkB,EAAE,GAAG,QAAA;AAC7B,aAAW,OAAO,mBAAmB;AACnC,WAAQ,gBAA4C,GAAG;AAAA,EACzD;AACA,aAAW,OAAO,kBAAkB;AAClC,WAAQ,gBAA4C,GAAG;AAAA,EACzD;AACA,QAAM,OAAO,iBAAiB,OAAO;AACrC,QAAM,UAAU,EAAE,GAAG,KAAA;AACrB,aAAW,OAAO,kBAAkB;AAClC,WAAQ,QAAoC,GAAG;AAAA,EACjD;AACA,QAAM,EAAE,OAAO,aAAa,UAAU,WAAW;AAAA,IAC/C;AAAA,IACA;AAAA,EAAA;AAGF,QAAM,iBAAiB,eAAe,OAAO;AAC7C,QAAM,gBAAgB,cAAc,OAAsB;AAC1D,QAAM,kBAAkB,CAAC,eAAe,gBAAgB,SAAS,EAC9D,OAAO,OAAO,EACd,KAAK,GAAG;AAEX,QAAM,eAAwC;AAAA,IAC5C;AAAA,IACA,WAAW,mBAAmB;AAAA,IAC9B,OAAO;AAAA,IACP,GAAG;AAAA,EAAA;AAGL,MAAI,QAAQ;AACV,iBAAa,UAAU,IAAI;AAAA,EAC7B;AAEA,SACE,qBAAA,UAAA,EACG,UAAA;AAAA,IAAA;AAAA,IACA,MAAM,cAAc,KAAK,cAAc,QAAQ;AAAA,EAAA,GAClD;AAEJ;AAEA,IAAI,cAAc;"}
@@ -0,0 +1,66 @@
1
+ import { default as React } from 'react';
2
+ import { LinkVariant } from '../../types';
3
+ /**
4
+ * A single breadcrumb item. If `href` is provided, the item is rendered as a link;
5
+ * otherwise it is the current page (last segment) and rendered as text with aria-current="page".
6
+ */
7
+ export interface BreadcrumbItem {
8
+ /** Display label for the segment. */
9
+ label: string;
10
+ /** Optional URL. Omit for the current page (typically the last item). */
11
+ href?: string;
12
+ }
13
+ /**
14
+ * Visual style for the separator between breadcrumb items.
15
+ * - 'slash' Forward slash (/) — matches design system default.
16
+ * - 'chevron' Right-pointing chevron.
17
+ */
18
+ export type BreadcrumbSeparator = 'slash' | 'chevron';
19
+ /**
20
+ * Props for the Breadcrumb component. Renders a WAI-ARIA compliant breadcrumb navigation.
21
+ * Matches design: slash separators, optional truncation with ellipsis for long paths.
22
+ */
23
+ export interface BreadcrumbProps {
24
+ /** List of breadcrumb segments. Last item without `href` is treated as current page. */
25
+ items: BreadcrumbItem[];
26
+ /**
27
+ * When true and there are more than 3 items, collapse the middle to "..." (e.g. Root ... Level-04 / Level-05).
28
+ * @default false
29
+ */
30
+ truncate?: boolean;
31
+ /**
32
+ * Link variant for non-current segments. Use tertiary or secondary for muted breadcrumb links.
33
+ * @default 'tertiary'
34
+ */
35
+ linkVariant?: LinkVariant;
36
+ /**
37
+ * Separator between items.
38
+ * @default 'slash'
39
+ */
40
+ separator?: BreadcrumbSeparator;
41
+ /** Accessible name for the navigation landmark. @default 'Breadcrumb' */
42
+ 'aria-label'?: string;
43
+ /** Additional CSS class names. */
44
+ className?: string;
45
+ /** Inline styles. */
46
+ style?: React.CSSProperties;
47
+ }
48
+ /**
49
+ * Renders a breadcrumb navigation with accessible structure (nav + list), slash or
50
+ * chevron separators, and optional truncation (first ... second-to-last / current).
51
+ * Matches design: links underlined, current page not underlined, separators in disabled color.
52
+ *
53
+ * @example
54
+ * ```tsx
55
+ * <Breadcrumb
56
+ * items={[
57
+ * { label: 'Root', href: '/' },
58
+ * { label: 'Level-01', href: '/l1' },
59
+ * { label: 'Level-02' },
60
+ * ]}
61
+ * />
62
+ * <Breadcrumb items={manyItems} truncate />
63
+ * ```
64
+ */
65
+ export declare function Breadcrumb({ items, truncate, linkVariant, separator, 'aria-label': ariaLabel, className, style, }: BreadcrumbProps): import("react/jsx-runtime").JSX.Element | null;
66
+ //# sourceMappingURL=Breadcrumb.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Breadcrumb.d.ts","sourceRoot":"","sources":["../../../src/components/Breadcrumb/Breadcrumb.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,qCAAqC;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,yEAAyE;IACzE,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;GAIG;AACH,MAAM,MAAM,mBAAmB,GAAG,OAAO,GAAG,SAAS,CAAC;AAEtD;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,wFAAwF;IACxF,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;OAGG;IACH,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B;;;OAGG;IACH,SAAS,CAAC,EAAE,mBAAmB,CAAC;IAChC,yEAAyE;IACzE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kCAAkC;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qBAAqB;IACrB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;CAC7B;AAUD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,UAAU,CAAC,EACzB,KAAK,EACL,QAAgB,EAChB,WAAwB,EACxB,SAAmB,EACnB,YAAY,EAAE,SAAwB,EACtC,SAAc,EACd,KAAK,GACN,EAAE,eAAe,kDAwFjB"}
@@ -0,0 +1,54 @@
1
+ import { default as React } from 'react';
2
+ import { ButtonVariant, ButtonSize } from '../../types';
3
+ /**
4
+ * Props for the Button component. Extends native button HTML attributes.
5
+ */
6
+ export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
7
+ /** Visual style variant (primary, secondary, inverse, ghost). */
8
+ variant: ButtonVariant;
9
+ /**
10
+ * Button size. Affects height, padding, and typography.
11
+ * @default 'small'
12
+ */
13
+ size?: ButtonSize;
14
+ /** Icon or element rendered before the button text. @default undefined */
15
+ iconLeft?: React.ReactNode;
16
+ /** Icon or element rendered after the button text. @default undefined */
17
+ iconRight?: React.ReactNode;
18
+ /**
19
+ * When provided, renders a square icon-only button with no text.
20
+ * You must provide aria-label for accessibility.
21
+ * @default undefined
22
+ * @see aria-label
23
+ */
24
+ iconOnly?: React.ReactNode;
25
+ /** When true, disables the button and applies disabled styling. @default false */
26
+ disabled?: boolean;
27
+ /** Button label or content. Omit when using iconOnly. @default undefined */
28
+ children?: React.ReactNode;
29
+ /** Additional CSS class names. Merged with variant/size classes. @default undefined */
30
+ className?: string;
31
+ /** Inline styles. @default undefined */
32
+ style?: React.CSSProperties;
33
+ /**
34
+ * Accessible label. Required when iconOnly is set; recommended for icon buttons.
35
+ * @default undefined
36
+ * @see iconOnly
37
+ */
38
+ 'aria-label'?: string;
39
+ /** Forwarded ref for the button element. @default undefined */
40
+ ref?: React.Ref<HTMLButtonElement>;
41
+ }
42
+ /**
43
+ * Button component with design-system variants, sizes, icon support, and
44
+ * an accessible focus ring that appears only on keyboard navigation.
45
+ *
46
+ * @example
47
+ * ```tsx
48
+ * <Button variant="primary" size="large">Click Me</Button>
49
+ * <Button variant="secondary" iconLeft={<SearchIcon />}>Search</Button>
50
+ * <Button variant="ghost" iconOnly={<MenuIcon />} aria-label="Open menu" />
51
+ * ```
52
+ */
53
+ export declare function Button({ variant, size, iconLeft, iconRight, iconOnly, disabled, children, className, style, ref, ...rest }: ButtonProps): import("react/jsx-runtime").JSX.Element;
54
+ //# sourceMappingURL=Button.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Button.d.ts","sourceRoot":"","sources":["../../../src/components/Button/Button.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE7D;;GAEG;AACH,MAAM,WAAW,WAAY,SAAQ,KAAK,CAAC,oBAAoB,CAAC,iBAAiB,CAAC;IAChF,iEAAiE;IACjE,OAAO,EAAE,aAAa,CAAC;IACvB;;;OAGG;IACH,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,yEAAyE;IACzE,SAAS,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC5B;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,kFAAkF;IAClF,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,uFAAuF;IACvF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wCAAwC;IACxC,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,+DAA+D;IAC/D,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;CACpC;AAkED;;;;;;;;;;GAUG;AACH,wBAAgB,MAAM,CAAC,EACrB,OAAO,EACP,IAAc,EACd,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,QAAgB,EAChB,QAAQ,EACR,SAAc,EACd,KAAK,EACL,GAAG,EACH,GAAG,IAAI,EACR,EAAE,WAAW,2CAqDb"}