premium-ds 0.1.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 (257) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +113 -0
  3. package/dist/alert.d.ts +31 -0
  4. package/dist/alert.js +6 -0
  5. package/dist/alert.js.map +1 -0
  6. package/dist/avatar-group.d.ts +13 -0
  7. package/dist/avatar-group.js +3 -0
  8. package/dist/avatar-group.js.map +1 -0
  9. package/dist/avatar.d.ts +25 -0
  10. package/dist/avatar.js +3 -0
  11. package/dist/avatar.js.map +1 -0
  12. package/dist/badge.d.ts +23 -0
  13. package/dist/badge.js +3 -0
  14. package/dist/badge.js.map +1 -0
  15. package/dist/button.d.ts +20 -0
  16. package/dist/button.js +3 -0
  17. package/dist/button.js.map +1 -0
  18. package/dist/checkbox.d.ts +25 -0
  19. package/dist/checkbox.js +3 -0
  20. package/dist/checkbox.js.map +1 -0
  21. package/dist/chunk-2OWHZ4JT.js +36 -0
  22. package/dist/chunk-2OWHZ4JT.js.map +1 -0
  23. package/dist/chunk-34SIXSYL.js +64 -0
  24. package/dist/chunk-34SIXSYL.js.map +1 -0
  25. package/dist/chunk-37O2ZXD6.js +55 -0
  26. package/dist/chunk-37O2ZXD6.js.map +1 -0
  27. package/dist/chunk-4AZL76UJ.js +89 -0
  28. package/dist/chunk-4AZL76UJ.js.map +1 -0
  29. package/dist/chunk-4HSCN5TZ.js +86 -0
  30. package/dist/chunk-4HSCN5TZ.js.map +1 -0
  31. package/dist/chunk-5DDOOT33.js +258 -0
  32. package/dist/chunk-5DDOOT33.js.map +1 -0
  33. package/dist/chunk-5FVHWIMY.js +117 -0
  34. package/dist/chunk-5FVHWIMY.js.map +1 -0
  35. package/dist/chunk-5K6KRJGX.js +147 -0
  36. package/dist/chunk-5K6KRJGX.js.map +1 -0
  37. package/dist/chunk-5PQMQBQC.js +74 -0
  38. package/dist/chunk-5PQMQBQC.js.map +1 -0
  39. package/dist/chunk-7OCTVQ7C.js +95 -0
  40. package/dist/chunk-7OCTVQ7C.js.map +1 -0
  41. package/dist/chunk-7OPMOET7.js +39 -0
  42. package/dist/chunk-7OPMOET7.js.map +1 -0
  43. package/dist/chunk-BXXS7YRC.js +270 -0
  44. package/dist/chunk-BXXS7YRC.js.map +1 -0
  45. package/dist/chunk-CV2Q4YXX.js +272 -0
  46. package/dist/chunk-CV2Q4YXX.js.map +1 -0
  47. package/dist/chunk-EIMMDWIW.js +282 -0
  48. package/dist/chunk-EIMMDWIW.js.map +1 -0
  49. package/dist/chunk-EZ2CWTBE.js +230 -0
  50. package/dist/chunk-EZ2CWTBE.js.map +1 -0
  51. package/dist/chunk-FGHDG3Y4.js +89 -0
  52. package/dist/chunk-FGHDG3Y4.js.map +1 -0
  53. package/dist/chunk-FPP2XLKX.js +127 -0
  54. package/dist/chunk-FPP2XLKX.js.map +1 -0
  55. package/dist/chunk-G6OY35DI.js +295 -0
  56. package/dist/chunk-G6OY35DI.js.map +1 -0
  57. package/dist/chunk-H6KWJNOE.js +65 -0
  58. package/dist/chunk-H6KWJNOE.js.map +1 -0
  59. package/dist/chunk-HGILYGY3.js +45 -0
  60. package/dist/chunk-HGILYGY3.js.map +1 -0
  61. package/dist/chunk-I3BCB4Z5.js +88 -0
  62. package/dist/chunk-I3BCB4Z5.js.map +1 -0
  63. package/dist/chunk-KBWNUUWM.js +582 -0
  64. package/dist/chunk-KBWNUUWM.js.map +1 -0
  65. package/dist/chunk-KN7JFAZ6.js +113 -0
  66. package/dist/chunk-KN7JFAZ6.js.map +1 -0
  67. package/dist/chunk-MEF7PI6U.js +16 -0
  68. package/dist/chunk-MEF7PI6U.js.map +1 -0
  69. package/dist/chunk-NKGMQL6I.js +310 -0
  70. package/dist/chunk-NKGMQL6I.js.map +1 -0
  71. package/dist/chunk-NMFQRGLL.js +127 -0
  72. package/dist/chunk-NMFQRGLL.js.map +1 -0
  73. package/dist/chunk-OUBWD6CX.js +433 -0
  74. package/dist/chunk-OUBWD6CX.js.map +1 -0
  75. package/dist/chunk-PFNXVBLU.js +96 -0
  76. package/dist/chunk-PFNXVBLU.js.map +1 -0
  77. package/dist/chunk-PUPZ4HME.js +165 -0
  78. package/dist/chunk-PUPZ4HME.js.map +1 -0
  79. package/dist/chunk-QFS52OK5.js +690 -0
  80. package/dist/chunk-QFS52OK5.js.map +1 -0
  81. package/dist/chunk-QNC6O3PG.js +45 -0
  82. package/dist/chunk-QNC6O3PG.js.map +1 -0
  83. package/dist/chunk-QUHOXWBK.js +82 -0
  84. package/dist/chunk-QUHOXWBK.js.map +1 -0
  85. package/dist/chunk-UIQGSTBJ.js +106 -0
  86. package/dist/chunk-UIQGSTBJ.js.map +1 -0
  87. package/dist/chunk-UJQKVP6V.js +193 -0
  88. package/dist/chunk-UJQKVP6V.js.map +1 -0
  89. package/dist/chunk-VVPGEAC6.js +11 -0
  90. package/dist/chunk-VVPGEAC6.js.map +1 -0
  91. package/dist/chunk-XA3T5KWA.js +58 -0
  92. package/dist/chunk-XA3T5KWA.js.map +1 -0
  93. package/dist/chunk-YSHJHSJM.js +19 -0
  94. package/dist/chunk-YSHJHSJM.js.map +1 -0
  95. package/dist/chunk-YVHOAVSM.js +182 -0
  96. package/dist/chunk-YVHOAVSM.js.map +1 -0
  97. package/dist/collapse.d.ts +16 -0
  98. package/dist/collapse.js +3 -0
  99. package/dist/collapse.js.map +1 -0
  100. package/dist/count-badge.d.ts +11 -0
  101. package/dist/count-badge.js +4 -0
  102. package/dist/count-badge.js.map +1 -0
  103. package/dist/date-field.d.ts +39 -0
  104. package/dist/date-field.js +8 -0
  105. package/dist/date-field.js.map +1 -0
  106. package/dist/date-range-field.d.ts +30 -0
  107. package/dist/date-range-field.js +8 -0
  108. package/dist/date-range-field.js.map +1 -0
  109. package/dist/datetime-field.d.ts +28 -0
  110. package/dist/datetime-field.js +10 -0
  111. package/dist/datetime-field.js.map +1 -0
  112. package/dist/dialog.d.ts +26 -0
  113. package/dist/dialog.js +7 -0
  114. package/dist/dialog.js.map +1 -0
  115. package/dist/index.d.ts +35 -0
  116. package/dist/index.js +40 -0
  117. package/dist/index.js.map +1 -0
  118. package/dist/motion-tokens.d.ts +29 -0
  119. package/dist/motion-tokens.js +3 -0
  120. package/dist/motion-tokens.js.map +1 -0
  121. package/dist/multi-select.d.ts +25 -0
  122. package/dist/multi-select.js +7 -0
  123. package/dist/multi-select.js.map +1 -0
  124. package/dist/number-field.d.ts +24 -0
  125. package/dist/number-field.js +4 -0
  126. package/dist/number-field.js.map +1 -0
  127. package/dist/otp-field.d.ts +20 -0
  128. package/dist/otp-field.js +3 -0
  129. package/dist/otp-field.js.map +1 -0
  130. package/dist/overlay.d.ts +31 -0
  131. package/dist/overlay.js +4 -0
  132. package/dist/overlay.js.map +1 -0
  133. package/dist/pagination.d.ts +24 -0
  134. package/dist/pagination.js +5 -0
  135. package/dist/pagination.js.map +1 -0
  136. package/dist/radio-group.d.ts +46 -0
  137. package/dist/radio-group.js +6 -0
  138. package/dist/radio-group.js.map +1 -0
  139. package/dist/select-core-SAyS-8w0.d.ts +16 -0
  140. package/dist/select.d.ts +27 -0
  141. package/dist/select.js +7 -0
  142. package/dist/select.js.map +1 -0
  143. package/dist/status-badge.d.ts +17 -0
  144. package/dist/status-badge.js +5 -0
  145. package/dist/status-badge.js.map +1 -0
  146. package/dist/table.d.ts +65 -0
  147. package/dist/table.js +5 -0
  148. package/dist/table.js.map +1 -0
  149. package/dist/tabs.d.ts +44 -0
  150. package/dist/tabs.js +5 -0
  151. package/dist/tabs.js.map +1 -0
  152. package/dist/tag.d.ts +28 -0
  153. package/dist/tag.js +5 -0
  154. package/dist/tag.js.map +1 -0
  155. package/dist/text-field.d.ts +30 -0
  156. package/dist/text-field.js +6 -0
  157. package/dist/text-field.js.map +1 -0
  158. package/dist/textarea.d.ts +33 -0
  159. package/dist/textarea.js +5 -0
  160. package/dist/textarea.js.map +1 -0
  161. package/dist/time-field.d.ts +27 -0
  162. package/dist/time-field.js +6 -0
  163. package/dist/time-field.js.map +1 -0
  164. package/dist/toast-store.d.ts +75 -0
  165. package/dist/toast-store.js +3 -0
  166. package/dist/toast-store.js.map +1 -0
  167. package/dist/toast.d.ts +3 -0
  168. package/dist/toast.js +6 -0
  169. package/dist/toast.js.map +1 -0
  170. package/dist/toggle-tag.d.ts +24 -0
  171. package/dist/toggle-tag.js +4 -0
  172. package/dist/toggle-tag.js.map +1 -0
  173. package/dist/toggle.d.ts +21 -0
  174. package/dist/toggle.js +3 -0
  175. package/dist/toggle.js.map +1 -0
  176. package/dist/tooltip.d.ts +27 -0
  177. package/dist/tooltip.js +4 -0
  178. package/dist/tooltip.js.map +1 -0
  179. package/llms.txt +165 -0
  180. package/package.json +205 -0
  181. package/src/components/alert/Alert.tsx +118 -0
  182. package/src/components/alert/alert.css +136 -0
  183. package/src/components/avatar/Avatar.tsx +128 -0
  184. package/src/components/avatar/AvatarGroup.tsx +50 -0
  185. package/src/components/avatar/avatar.css +200 -0
  186. package/src/components/badge/Badge.tsx +66 -0
  187. package/src/components/badge/CountBadge.tsx +46 -0
  188. package/src/components/badge/StatusBadge.tsx +132 -0
  189. package/src/components/badge/badge.css +243 -0
  190. package/src/components/button/Button.tsx +68 -0
  191. package/src/components/button/button.css +222 -0
  192. package/src/components/checkbox/Checkbox.tsx +90 -0
  193. package/src/components/checkbox/checkbox.css +179 -0
  194. package/src/components/date-picker/DateField.tsx +362 -0
  195. package/src/components/date-picker/DateRangeField.tsx +533 -0
  196. package/src/components/date-picker/DateTimeField.tsx +177 -0
  197. package/src/components/date-picker/TimeField.tsx +100 -0
  198. package/src/components/date-picker/date-picker.css +591 -0
  199. package/src/components/date-picker/date-utils.ts +55 -0
  200. package/src/components/date-picker/field-shell.tsx +78 -0
  201. package/src/components/date-picker/glide-pill.tsx +81 -0
  202. package/src/components/date-picker/time-core.tsx +305 -0
  203. package/src/components/dialog/Dialog.tsx +181 -0
  204. package/src/components/dialog/dialog.css +170 -0
  205. package/src/components/glass/glass.css +100 -0
  206. package/src/components/icon/Icon.tsx +76 -0
  207. package/src/components/icon/IconSlot.tsx +11 -0
  208. package/src/components/icon/icon.css +33 -0
  209. package/src/components/input/NumberField.tsx +117 -0
  210. package/src/components/input/OtpField.tsx +118 -0
  211. package/src/components/input/TextField.tsx +123 -0
  212. package/src/components/input/input.css +335 -0
  213. package/src/components/motion/Collapse.tsx +33 -0
  214. package/src/components/motion/collapse.css +41 -0
  215. package/src/components/overlay/Overlay.tsx +239 -0
  216. package/src/components/overlay/overlay-core.tsx +565 -0
  217. package/src/components/overlay/overlay.css +119 -0
  218. package/src/components/overlay/sheet-drag.tsx +146 -0
  219. package/src/components/pagination/Pagination.tsx +140 -0
  220. package/src/components/pagination/pagination.css +48 -0
  221. package/src/components/radio-group/RadioGroup.tsx +182 -0
  222. package/src/components/radio-group/radio-group.css +277 -0
  223. package/src/components/select/MultiSelect.tsx +251 -0
  224. package/src/components/select/Select.tsx +235 -0
  225. package/src/components/select/select-core.tsx +417 -0
  226. package/src/components/select/select.css +386 -0
  227. package/src/components/table/Table.tsx +433 -0
  228. package/src/components/table/table.css +348 -0
  229. package/src/components/tabs/Tabs.tsx +371 -0
  230. package/src/components/tabs/tabs.css +228 -0
  231. package/src/components/tag/Tag.tsx +145 -0
  232. package/src/components/tag/ToggleTag.tsx +125 -0
  233. package/src/components/tag/tag.css +248 -0
  234. package/src/components/textarea/Textarea.tsx +197 -0
  235. package/src/components/textarea/textarea.css +219 -0
  236. package/src/components/toast/Toast.tsx +349 -0
  237. package/src/components/toast/toast-store.ts +266 -0
  238. package/src/components/toast/toast.css +233 -0
  239. package/src/components/toggle/Toggle.tsx +94 -0
  240. package/src/components/toggle/toggle.css +152 -0
  241. package/src/components/tooltip/Tooltip.tsx +365 -0
  242. package/src/components/tooltip/tooltip.css +86 -0
  243. package/src/index.ts +42 -0
  244. package/src/styles.css +39 -0
  245. package/src/tokens/avatar.css +20 -0
  246. package/src/tokens/color.css +56 -0
  247. package/src/tokens/elevation.css +20 -0
  248. package/src/tokens/fonts.css +3 -0
  249. package/src/tokens/glass.css +21 -0
  250. package/src/tokens/icons.css +7 -0
  251. package/src/tokens/layers.css +6 -0
  252. package/src/tokens/motion-tokens.ts +72 -0
  253. package/src/tokens/motion.css +49 -0
  254. package/src/tokens/radius.css +11 -0
  255. package/src/tokens/semantic.css +75 -0
  256. package/src/tokens/spacing.css +26 -0
  257. package/src/tokens/typography.css +54 -0
@@ -0,0 +1,147 @@
1
+ 'use client';import { Icon } from './chunk-KBWNUUWM.js';
2
+ import { Collapse } from './chunk-YSHJHSJM.js';
3
+ import * as React from 'react';
4
+ import { jsxs, jsx } from 'react/jsx-runtime';
5
+
6
+ var RING_C = (2 * Math.PI * 7).toFixed(2);
7
+ function Textarea({
8
+ id,
9
+ label,
10
+ required,
11
+ optional,
12
+ placeholder,
13
+ helper,
14
+ error,
15
+ warning,
16
+ success,
17
+ value = "",
18
+ onChange,
19
+ onSubmit,
20
+ max,
21
+ minRows = 3,
22
+ maxRows = 10,
23
+ warnAt = 20,
24
+ hint,
25
+ size,
26
+ disabled,
27
+ readOnly,
28
+ className = "",
29
+ ...rest
30
+ }) {
31
+ const taRef = React.useRef(null);
32
+ const stackRef = React.useRef(null);
33
+ const mirrorRef = React.useRef(null);
34
+ const text = value ?? "";
35
+ const count = text.length;
36
+ const over = max ? Math.max(count - max, 0) : 0;
37
+ const remaining = max ? max - count : 0;
38
+ const meterState = over ? "is-over" : max && remaining <= warnAt ? "is-near" : "";
39
+ const state = error ? "is-error" : warning ? "is-warning" : success ? "is-success" : "";
40
+ const msg = error || warning || success || helper;
41
+ const msgIcon = error ? "warning-circle" : warning ? "warning" : success ? "check-circle" : null;
42
+ const resize = () => {
43
+ const el = taRef.current, stack = stackRef.current;
44
+ if (!el || !stack) return;
45
+ const start = stack.offsetHeight;
46
+ el.style.height = "auto";
47
+ el.style.height = el.scrollHeight + "px";
48
+ const content = el.offsetHeight;
49
+ const maxPx = parseFloat(getComputedStyle(stack).maxHeight) || Infinity;
50
+ const target = Math.min(content, maxPx);
51
+ if (target === start) {
52
+ stack.style.overflowY = content > maxPx ? "auto" : "clip";
53
+ return;
54
+ }
55
+ stack.style.overflowY = "clip";
56
+ stack.style.height = start + "px";
57
+ void stack.offsetHeight;
58
+ stack.style.height = target + "px";
59
+ };
60
+ React.useLayoutEffect(resize, [text, size]);
61
+ React.useEffect(() => {
62
+ window.addEventListener("resize", resize);
63
+ return () => window.removeEventListener("resize", resize);
64
+ }, []);
65
+ const onKeyDown = (e) => {
66
+ if (onSubmit && (e.metaKey || e.ctrlKey) && e.key === "Enter") {
67
+ e.preventDefault();
68
+ onSubmit(text);
69
+ }
70
+ rest.onKeyDown && rest.onKeyDown(e);
71
+ };
72
+ const cls = ["fld", "fld--txa", size === "lg" && "fld--lg", state, className].filter(Boolean).join(" ");
73
+ const boxCls = ["txa", disabled && "is-disabled", readOnly && "is-readonly"].filter(Boolean).join(" ");
74
+ return /* @__PURE__ */ jsxs("div", { className: cls, children: [
75
+ label && /* @__PURE__ */ jsxs("label", { className: "fld__label", htmlFor: id, children: [
76
+ label,
77
+ required && /* @__PURE__ */ jsx("span", { className: "fld__req", "aria-hidden": "true", children: "*" }),
78
+ optional && /* @__PURE__ */ jsx("span", { className: "fld__optional", children: "(optional)" })
79
+ ] }),
80
+ /* @__PURE__ */ jsxs(
81
+ "div",
82
+ {
83
+ className: boxCls,
84
+ style: { "--txa-min-rows": minRows, "--txa-max-rows": maxRows },
85
+ children: [
86
+ /* @__PURE__ */ jsxs("div", { className: "txa__stack", ref: stackRef, children: [
87
+ /* @__PURE__ */ jsxs("div", { className: "txa__mirror", ref: mirrorRef, "aria-hidden": "true", children: [
88
+ over ? text.slice(0, max) : text,
89
+ over ? /* @__PURE__ */ jsx("mark", { children: text.slice(max) }) : null,
90
+ "\n"
91
+ ] }),
92
+ /* @__PURE__ */ jsx(
93
+ "textarea",
94
+ {
95
+ id,
96
+ className: "txa__input",
97
+ ref: taRef,
98
+ rows: minRows,
99
+ value: text,
100
+ placeholder,
101
+ disabled,
102
+ readOnly,
103
+ onChange,
104
+ onKeyDown,
105
+ onScroll: () => {
106
+ if (mirrorRef.current) mirrorRef.current.scrollTop = taRef.current.scrollTop;
107
+ },
108
+ "aria-invalid": error ? true : void 0,
109
+ ...rest
110
+ }
111
+ )
112
+ ] }),
113
+ (max || hint) && /* @__PURE__ */ jsxs("div", { className: "txa__bar", children: [
114
+ hint && /* @__PURE__ */ jsx("span", { className: "txa__hint", children: hint }),
115
+ max && /* @__PURE__ */ jsxs("span", { className: ["txa__meter", meterState].filter(Boolean).join(" "), children: [
116
+ /* @__PURE__ */ jsx("span", { className: "txa__count", children: over || remaining <= warnAt ? remaining : `${count} / ${max}` }),
117
+ /* @__PURE__ */ jsxs(
118
+ "svg",
119
+ {
120
+ className: "txa__ring",
121
+ viewBox: "0 0 16 16",
122
+ "aria-hidden": "true",
123
+ style: {
124
+ "--txa-ring-c": RING_C,
125
+ "--txa-ring-p": Math.min(count / max, 1)
126
+ },
127
+ children: [
128
+ /* @__PURE__ */ jsx("circle", { className: "txa__ring-trk", cx: "8", cy: "8", r: "7" }),
129
+ /* @__PURE__ */ jsx("circle", { className: "txa__ring-prg", cx: "8", cy: "8", r: "7" })
130
+ ]
131
+ }
132
+ )
133
+ ] })
134
+ ] })
135
+ ]
136
+ }
137
+ ),
138
+ /* @__PURE__ */ jsx(Collapse, { open: !!msg, className: "fld__msg-wrap", children: /* @__PURE__ */ jsxs("div", { className: "fld__msg", children: [
139
+ msgIcon && /* @__PURE__ */ jsx(Icon, { name: msgIcon, size: "sm", weight: "fill" }),
140
+ msg
141
+ ] }) })
142
+ ] });
143
+ }
144
+
145
+ export { Textarea };
146
+ //# sourceMappingURL=chunk-5K6KRJGX.js.map
147
+ //# sourceMappingURL=chunk-5K6KRJGX.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/textarea/Textarea.tsx"],"names":[],"mappings":"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","file":"chunk-5K6KRJGX.js","sourcesContent":["'use client';\n\n// Textarea.tsx - multiline input: TextField anatomy plus auto-grow, char meter, over-limit highlight, ⌘/Ctrl+↵ submit.\n\nimport * as React from 'react';\nimport { Icon } from '../icon/Icon';\nimport { Collapse } from '../motion/Collapse';\n\nconst RING_C = (2 * Math.PI * 7).toFixed(2);\n\nexport interface TextareaProps extends Omit<\n React.TextareaHTMLAttributes<HTMLTextAreaElement>,\n 'size' | 'rows' | 'onSubmit'\n> {\n id?: string;\n /** Label text (sentence case). */\n label?: React.ReactNode;\n required?: boolean;\n optional?: boolean;\n /** Neutral helper - shown when there's no validation message. */\n helper?: React.ReactNode;\n /** Sets the matching state (border + icon + colour). error wins over warning/success/helper. */\n error?: React.ReactNode;\n warning?: React.ReactNode;\n success?: React.ReactNode;\n value?: string;\n onChange?: React.ChangeEventHandler<HTMLTextAreaElement>;\n /** Fired on ⌘/Ctrl+Enter with the current text. */\n onSubmit?: (value: string) => void;\n /** Soft char limit: shows the meter + over-limit highlight. Does NOT truncate (use native maxLength for a hard stop). */\n max?: number;\n /** Visible rows before growing (default 3) and the cap before it scrolls (default 10). */\n minRows?: number;\n maxRows?: number;\n /** Remaining-chars threshold that flips the meter amber. Default 20. */\n warnAt?: number;\n /** Footer hint, left of the meter - e.g. a ⌘↵ affordance. */\n hint?: React.ReactNode;\n /** md (default) - lg (prominent composer). */\n size?: 'md' | 'lg';\n}\n\nexport function Textarea({\n id,\n label,\n required,\n optional,\n placeholder,\n helper,\n error,\n warning,\n success,\n value = '',\n onChange,\n onSubmit,\n max,\n minRows = 3,\n maxRows = 10,\n warnAt = 20,\n hint,\n size,\n disabled,\n readOnly,\n className = '',\n ...rest\n}: TextareaProps) {\n const taRef = React.useRef<HTMLTextAreaElement>(null);\n const stackRef = React.useRef<HTMLDivElement>(null);\n const mirrorRef = React.useRef<HTMLDivElement>(null);\n const text = value ?? '';\n const count = text.length;\n const over = max ? Math.max(count - max, 0) : 0;\n const remaining = max ? max - count : 0;\n const meterState = over ? 'is-over' : max && remaining <= warnAt ? 'is-near' : '';\n\n const state = error ? 'is-error' : warning ? 'is-warning' : success ? 'is-success' : '';\n const msg = error || warning || success || helper;\n const msgIcon = error ? 'warning-circle' : warning ? 'warning' : success ? 'check-circle' : null;\n\n // Auto-grow without a caret jump: the .txa__stack wrapper animates its height and is overflow:clip while growing (a clip box can't scroll to the caret); scroll is enabled only past max-height.\n const resize = () => {\n const el = taRef.current,\n stack = stackRef.current;\n if (!el || !stack) return;\n const start = stack.offsetHeight; // capture the start height before mutating layout below\n el.style.height = 'auto';\n el.style.height = el.scrollHeight + 'px';\n const content = el.offsetHeight;\n const maxPx = parseFloat(getComputedStyle(stack).maxHeight) || Infinity;\n const target = Math.min(content, maxPx);\n if (target === start) {\n stack.style.overflowY = content > maxPx ? 'auto' : 'clip';\n return;\n }\n stack.style.overflowY = 'clip';\n stack.style.height = start + 'px';\n void stack.offsetHeight; // force a reflow so the height transition runs from start\n stack.style.height = target + 'px';\n };\n React.useLayoutEffect(resize, [text, size]);\n React.useEffect(() => {\n window.addEventListener('resize', resize);\n return () => window.removeEventListener('resize', resize);\n }, []);\n\n const onKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (onSubmit && (e.metaKey || e.ctrlKey) && e.key === 'Enter') {\n e.preventDefault();\n onSubmit(text);\n }\n rest.onKeyDown && rest.onKeyDown(e);\n };\n\n const cls = ['fld', 'fld--txa', size === 'lg' && 'fld--lg', state, className]\n .filter(Boolean)\n .join(' ');\n const boxCls = ['txa', disabled && 'is-disabled', readOnly && 'is-readonly']\n .filter(Boolean)\n .join(' ');\n\n return (\n <div className={cls}>\n {label && (\n <label className=\"fld__label\" htmlFor={id}>\n {label}\n {required && (\n <span className=\"fld__req\" aria-hidden=\"true\">\n *\n </span>\n )}\n {optional && <span className=\"fld__optional\">(optional)</span>}\n </label>\n )}\n <div\n className={boxCls}\n style={{ '--txa-min-rows': minRows, '--txa-max-rows': maxRows } as React.CSSProperties}\n >\n <div className=\"txa__stack\" ref={stackRef}>\n <div className=\"txa__mirror\" ref={mirrorRef} aria-hidden=\"true\">\n {over ? text.slice(0, max) : text}\n {over ? <mark>{text.slice(max)}</mark> : null}\n {'\\n'}\n </div>\n <textarea\n id={id}\n className=\"txa__input\"\n ref={taRef}\n rows={minRows}\n value={text}\n placeholder={placeholder}\n disabled={disabled}\n readOnly={readOnly}\n onChange={onChange}\n onKeyDown={onKeyDown}\n onScroll={() => {\n if (mirrorRef.current) mirrorRef.current.scrollTop = taRef.current.scrollTop;\n }}\n aria-invalid={error ? true : undefined}\n {...rest}\n />\n </div>\n {(max || hint) && (\n <div className=\"txa__bar\">\n {hint && <span className=\"txa__hint\">{hint}</span>}\n {max && (\n <span className={['txa__meter', meterState].filter(Boolean).join(' ')}>\n <span className=\"txa__count\">\n {over || remaining <= warnAt ? remaining : `${count} / ${max}`}\n </span>\n <svg\n className=\"txa__ring\"\n viewBox=\"0 0 16 16\"\n aria-hidden=\"true\"\n style={\n {\n '--txa-ring-c': RING_C,\n '--txa-ring-p': Math.min(count / max, 1),\n } as React.CSSProperties\n }\n >\n <circle className=\"txa__ring-trk\" cx=\"8\" cy=\"8\" r=\"7\" />\n <circle className=\"txa__ring-prg\" cx=\"8\" cy=\"8\" r=\"7\" />\n </svg>\n </span>\n )}\n </div>\n )}\n </div>\n <Collapse open={!!msg} className=\"fld__msg-wrap\">\n <div className=\"fld__msg\">\n {msgIcon && <Icon name={msgIcon} size=\"sm\" weight=\"fill\" />}\n {msg}\n </div>\n </Collapse>\n </div>\n );\n}\n"]}
@@ -0,0 +1,74 @@
1
+ 'use client';import * as React from 'react';
2
+ import { jsxs, jsx } from 'react/jsx-runtime';
3
+
4
+ // src/components/toggle/Toggle.tsx
5
+ var { useState } = React;
6
+ function Toggle({
7
+ checked,
8
+ defaultChecked = false,
9
+ disabled = false,
10
+ size = "md",
11
+ label,
12
+ description,
13
+ className = "",
14
+ onChange,
15
+ ...rest
16
+ }) {
17
+ const controlled = checked !== void 0;
18
+ const [internal, setInternal] = useState(!!defaultChecked);
19
+ const isOn = controlled ? !!checked : internal;
20
+ const classes = ["sw", size === "sm" ? "sw--sm" : "", disabled ? "sw--disabled" : "", className].filter(Boolean).join(" ");
21
+ const [pressed, setPressed] = useState(false);
22
+ function press(on) {
23
+ return () => {
24
+ if (!disabled) setPressed(on);
25
+ };
26
+ }
27
+ function handleChange(e) {
28
+ if (!controlled) setInternal(e.target.checked);
29
+ if (onChange) onChange(e);
30
+ }
31
+ return /* @__PURE__ */ jsxs(
32
+ "label",
33
+ {
34
+ className: classes,
35
+ onPointerDown: press(true),
36
+ onPointerUp: press(false),
37
+ onPointerLeave: press(false),
38
+ onPointerCancel: press(false),
39
+ children: [
40
+ /* @__PURE__ */ jsx(
41
+ "input",
42
+ {
43
+ type: "checkbox",
44
+ role: "switch",
45
+ className: "sw__input",
46
+ disabled,
47
+ checked: isOn,
48
+ onChange: handleChange,
49
+ ...rest,
50
+ defaultChecked: void 0
51
+ }
52
+ ),
53
+ /* @__PURE__ */ jsx(
54
+ "span",
55
+ {
56
+ className: "sw__track",
57
+ "data-on": isOn ? "true" : void 0,
58
+ "data-pressed": pressed ? "true" : void 0,
59
+ "aria-hidden": "true",
60
+ children: /* @__PURE__ */ jsx("span", { className: "sw__thumb" })
61
+ }
62
+ ),
63
+ label || description ? /* @__PURE__ */ jsxs("span", { className: "sw__text", children: [
64
+ label ? /* @__PURE__ */ jsx("span", { className: "sw__label", children: label }) : null,
65
+ description ? /* @__PURE__ */ jsx("span", { className: "sw__desc", children: description }) : null
66
+ ] }) : null
67
+ ]
68
+ }
69
+ );
70
+ }
71
+
72
+ export { Toggle };
73
+ //# sourceMappingURL=chunk-5PQMQBQC.js.map
74
+ //# sourceMappingURL=chunk-5PQMQBQC.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/toggle/Toggle.tsx"],"names":[],"mappings":";;;;AAMA,IAAM,EAAE,UAAS,GAAI,KAAA;AAsBd,SAAS,MAAA,CAAO;AAAA,EACrB,OAAA;AAAA,EACA,cAAA,GAAiB,KAAA;AAAA,EACjB,QAAA,GAAW,KAAA;AAAA,EACX,IAAA,GAAO,IAAA;AAAA,EACP,KAAA;AAAA,EACA,WAAA;AAAA,EACA,SAAA,GAAY,EAAA;AAAA,EACZ,QAAA;AAAA,EACA,GAAG;AACL,CAAA,EAAgB;AACd,EAAA,MAAM,aAAa,OAAA,KAAY,MAAA;AAC/B,EAAA,MAAM,CAAC,QAAA,EAAU,WAAW,IAAI,QAAA,CAAS,CAAC,CAAC,cAAc,CAAA;AACzD,EAAA,MAAM,IAAA,GAAO,UAAA,GAAa,CAAC,CAAC,OAAA,GAAU,QAAA;AAEtC,EAAA,MAAM,UAAU,CAAC,IAAA,EAAM,IAAA,KAAS,IAAA,GAAO,WAAW,EAAA,EAAI,QAAA,GAAW,cAAA,GAAiB,EAAA,EAAI,SAAS,CAAA,CAC5F,MAAA,CAAO,OAAO,CAAA,CACd,KAAK,GAAG,CAAA;AAEX,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAI,SAAS,KAAK,CAAA;AAC5C,EAAA,SAAS,MAAM,EAAA,EAAa;AAC1B,IAAA,OAAO,MAAM;AACX,MAAA,IAAI,CAAC,QAAA,EAAU,UAAA,CAAW,EAAE,CAAA;AAAA,IAC9B,CAAA;AAAA,EACF;AAEA,EAAA,SAAS,aAAa,CAAA,EAAwC;AAC5D,IAAA,IAAI,CAAC,UAAA,EAAY,WAAA,CAAY,CAAA,CAAE,OAAO,OAAO,CAAA;AAC7C,IAAA,IAAI,QAAA,WAAmB,CAAC,CAAA;AAAA,EAC1B;AAEA,EAAA,uBACE,IAAA;AAAA,IAAC,OAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAW,OAAA;AAAA,MACX,aAAA,EAAe,MAAM,IAAI,CAAA;AAAA,MACzB,WAAA,EAAa,MAAM,KAAK,CAAA;AAAA,MACxB,cAAA,EAAgB,MAAM,KAAK,CAAA;AAAA,MAC3B,eAAA,EAAiB,MAAM,KAAK,CAAA;AAAA,MAE5B,QAAA,EAAA;AAAA,wBAAA,GAAA;AAAA,UAAC,OAAA;AAAA,UAAA;AAAA,YACC,IAAA,EAAK,UAAA;AAAA,YACL,IAAA,EAAK,QAAA;AAAA,YACL,SAAA,EAAU,WAAA;AAAA,YACV,QAAA;AAAA,YACA,OAAA,EAAS,IAAA;AAAA,YACT,QAAA,EAAU,YAAA;AAAA,YACT,GAAG,IAAA;AAAA,YACJ,cAAA,EAAgB;AAAA;AAAA,SAClB;AAAA,wBACA,GAAA;AAAA,UAAC,MAAA;AAAA,UAAA;AAAA,YACC,SAAA,EAAU,WAAA;AAAA,YACV,SAAA,EAAS,OAAO,MAAA,GAAS,MAAA;AAAA,YACzB,cAAA,EAAc,UAAU,MAAA,GAAS,MAAA;AAAA,YACjC,aAAA,EAAY,MAAA;AAAA,YAEZ,QAAA,kBAAA,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,WAAA,EAAY;AAAA;AAAA,SAC9B;AAAA,QACC,KAAA,IAAS,WAAA,mBACR,IAAA,CAAC,MAAA,EAAA,EAAK,WAAU,UAAA,EACb,QAAA,EAAA;AAAA,UAAA,KAAA,mBAAQ,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,WAAA,EAAa,iBAAM,CAAA,GAAU,IAAA;AAAA,UACrD,8BAAc,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,UAAA,EAAY,uBAAY,CAAA,GAAU;AAAA,SAAA,EACnE,CAAA,GACE;AAAA;AAAA;AAAA,GACN;AAEJ","file":"chunk-5PQMQBQC.js","sourcesContent":["'use client';\n\n// Toggle - binary on/off switch for an immediate setting (vs. Checkbox, which stages a choice).\n\nimport * as React from 'react';\n\nconst { useState } = React;\n\nexport interface ToggleProps extends Omit<\n React.InputHTMLAttributes<HTMLInputElement>,\n 'size' | 'type'\n> {\n /** Controlled checked state. Omit for uncontrolled (use `defaultChecked`). */\n checked?: boolean;\n /** Uncontrolled initial state. */\n defaultChecked?: boolean;\n /** Disabled - inert and de-emphasized (faded track, retains its position). */\n disabled?: boolean;\n /** Track size: `md` 36x20 - `sm` 28x16 for dense settings/table rows. @default 'md' */\n size?: 'sm' | 'md';\n /** Label text beside the track. */\n label?: React.ReactNode;\n /** Optional secondary line under the label (settings rows). */\n description?: React.ReactNode;\n /** Fires on flip - read `e.target.checked`. */\n onChange?: React.ChangeEventHandler<HTMLInputElement>;\n}\n\nexport function Toggle({\n checked,\n defaultChecked = false,\n disabled = false,\n size = 'md',\n label,\n description,\n className = '',\n onChange,\n ...rest\n}: ToggleProps) {\n const controlled = checked !== undefined;\n const [internal, setInternal] = useState(!!defaultChecked);\n const isOn = controlled ? !!checked : internal;\n\n const classes = ['sw', size === 'sm' ? 'sw--sm' : '', disabled ? 'sw--disabled' : '', className]\n .filter(Boolean)\n .join(' ');\n\n const [pressed, setPressed] = useState(false);\n function press(on: boolean) {\n return () => {\n if (!disabled) setPressed(on);\n };\n }\n\n function handleChange(e: React.ChangeEvent<HTMLInputElement>) {\n if (!controlled) setInternal(e.target.checked);\n if (onChange) onChange(e);\n }\n\n return (\n <label\n className={classes}\n onPointerDown={press(true)}\n onPointerUp={press(false)}\n onPointerLeave={press(false)}\n onPointerCancel={press(false)}\n >\n <input\n type=\"checkbox\"\n role=\"switch\"\n className=\"sw__input\"\n disabled={disabled}\n checked={isOn}\n onChange={handleChange}\n {...rest}\n defaultChecked={undefined}\n />\n <span\n className=\"sw__track\"\n data-on={isOn ? 'true' : undefined}\n data-pressed={pressed ? 'true' : undefined}\n aria-hidden=\"true\"\n >\n <span className=\"sw__thumb\"></span>\n </span>\n {label || description ? (\n <span className=\"sw__text\">\n {label ? <span className=\"sw__label\">{label}</span> : null}\n {description ? <span className=\"sw__desc\">{description}</span> : null}\n </span>\n ) : null}\n </label>\n );\n}\n"]}
@@ -0,0 +1,95 @@
1
+ 'use client';import { useRef } from 'react';
2
+ import { jsx } from 'react/jsx-runtime';
3
+
4
+ // src/components/input/OtpField.tsx
5
+ function OtpField({
6
+ length = 6,
7
+ value = "",
8
+ onChange,
9
+ group,
10
+ error,
11
+ disabled,
12
+ size,
13
+ className = ""
14
+ }) {
15
+ const refs = useRef([]);
16
+ const chars = String(value).slice(0, length).padEnd(length).split("");
17
+ const emit = (s) => onChange && onChange(s.replace(/ +$/, "").slice(0, length));
18
+ const setAt = (i, ch) => {
19
+ const a = chars.slice();
20
+ a[i] = ch || " ";
21
+ emit(a.join(""));
22
+ };
23
+ const caretEnd = (el) => {
24
+ if (!el) return;
25
+ const n = el.value.length;
26
+ try {
27
+ el.setSelectionRange(n, n);
28
+ } catch {
29
+ }
30
+ };
31
+ const go = (j) => {
32
+ const el = refs.current[j];
33
+ if (el) {
34
+ el.focus();
35
+ caretEnd(el);
36
+ }
37
+ };
38
+ const cls = ["otp", size === "sm" ? "otp--sm" : "", error ? "is-error" : "", className].filter(Boolean).join(" ");
39
+ const cells = [];
40
+ for (let i = 0; i < length; i++) {
41
+ if (group && i > 0 && i % group === 0)
42
+ cells.push(/* @__PURE__ */ jsx("span", { className: "otp__sep" }, `sep${i}`));
43
+ cells.push(
44
+ /* @__PURE__ */ jsx(
45
+ "input",
46
+ {
47
+ ref: (el) => {
48
+ refs.current[i] = el;
49
+ },
50
+ className: "otp__slot",
51
+ inputMode: "numeric",
52
+ autoComplete: "one-time-code",
53
+ disabled,
54
+ value: chars[i].trim(),
55
+ "data-filled": chars[i].trim() ? "true" : "false",
56
+ onFocus: (e) => caretEnd(e.target),
57
+ onMouseDown: (e) => {
58
+ e.preventDefault();
59
+ go(i);
60
+ },
61
+ onChange: (e) => {
62
+ const ch = e.target.value.replace(/[^\d]/g, "").slice(-1);
63
+ setAt(i, ch);
64
+ if (ch && i < length - 1) go(i + 1);
65
+ },
66
+ onKeyDown: (e) => {
67
+ if (e.key === "Backspace" && !chars[i].trim() && i > 0) {
68
+ e.preventDefault();
69
+ setAt(i - 1, "");
70
+ go(i - 1);
71
+ } else if (e.key === "ArrowLeft" && i > 0) {
72
+ e.preventDefault();
73
+ go(i - 1);
74
+ } else if (e.key === "ArrowRight" && i < length - 1) {
75
+ e.preventDefault();
76
+ go(i + 1);
77
+ }
78
+ },
79
+ onPaste: (e) => {
80
+ e.preventDefault();
81
+ const d = (e.clipboardData.getData("text") || "").replace(/[^\d]/g, "");
82
+ emit(chars.slice(0, i).join("") + d);
83
+ refs.current[Math.min(i + d.length, length - 1)]?.focus();
84
+ }
85
+ },
86
+ i
87
+ )
88
+ );
89
+ }
90
+ return /* @__PURE__ */ jsx("div", { className: cls, children: cells });
91
+ }
92
+
93
+ export { OtpField };
94
+ //# sourceMappingURL=chunk-7OCTVQ7C.js.map
95
+ //# sourceMappingURL=chunk-7OCTVQ7C.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/input/OtpField.tsx"],"names":[],"mappings":"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","file":"chunk-7OCTVQ7C.js","sourcesContent":["'use client';\n\n// OtpField.tsx - segmented one-time-code input: mono slots, auto-advance, arrow nav, paste-to-fill, grouping.\n\nimport { useRef } from 'react';\nimport type {\n ChangeEvent,\n ClipboardEvent,\n FocusEvent,\n KeyboardEvent,\n MouseEvent,\n ReactNode,\n} from 'react';\n\nexport interface OtpFieldProps {\n /** Number of slots. @default 6 */\n length?: number;\n /** Controlled value (digit string). */\n value?: string;\n /** Called with the next value string. */\n onChange?: (value: string) => void;\n /** Insert a separator every N slots (e.g. 3 - \"-------\"). */\n group?: number;\n /** Error state (red slots + ring). */\n error?: boolean;\n disabled?: boolean;\n size?: 'sm';\n className?: string;\n}\n\nexport function OtpField({\n length = 6,\n value = '',\n onChange,\n group,\n error,\n disabled,\n size,\n className = '',\n}: OtpFieldProps) {\n const refs = useRef<(HTMLInputElement | null)[]>([]);\n const chars = String(value).slice(0, length).padEnd(length).split('');\n const emit = (s: string) => onChange && onChange(s.replace(/ +$/, '').slice(0, length));\n const setAt = (i: number, ch: string) => {\n const a = chars.slice();\n a[i] = ch || ' ';\n emit(a.join(''));\n };\n // place caret at the end (no selection highlight); replacement handled by slice(-1)\n const caretEnd = (el: HTMLInputElement | null) => {\n if (!el) return;\n const n = el.value.length;\n try {\n el.setSelectionRange(n, n);\n } catch {}\n };\n const go = (j: number) => {\n const el = refs.current[j];\n if (el) {\n el.focus();\n caretEnd(el);\n }\n };\n\n const cls = ['otp', size === 'sm' ? 'otp--sm' : '', error ? 'is-error' : '', className]\n .filter(Boolean)\n .join(' ');\n\n const cells: ReactNode[] = [];\n for (let i = 0; i < length; i++) {\n if (group && i > 0 && i % group === 0)\n cells.push(<span key={`sep${i}`} className=\"otp__sep\" />);\n cells.push(\n <input\n key={i}\n ref={(el) => {\n refs.current[i] = el;\n }}\n className=\"otp__slot\"\n inputMode=\"numeric\"\n autoComplete=\"one-time-code\"\n disabled={disabled}\n value={chars[i].trim()}\n data-filled={chars[i].trim() ? 'true' : 'false'}\n onFocus={(e: FocusEvent<HTMLInputElement>) => caretEnd(e.target)}\n onMouseDown={(e: MouseEvent<HTMLInputElement>) => {\n e.preventDefault();\n go(i);\n }}\n onChange={(e: ChangeEvent<HTMLInputElement>) => {\n const ch = e.target.value.replace(/[^\\d]/g, '').slice(-1);\n setAt(i, ch);\n if (ch && i < length - 1) go(i + 1);\n }}\n onKeyDown={(e: KeyboardEvent<HTMLInputElement>) => {\n if (e.key === 'Backspace' && !chars[i].trim() && i > 0) {\n e.preventDefault();\n setAt(i - 1, '');\n go(i - 1);\n } else if (e.key === 'ArrowLeft' && i > 0) {\n e.preventDefault();\n go(i - 1);\n } else if (e.key === 'ArrowRight' && i < length - 1) {\n e.preventDefault();\n go(i + 1);\n }\n }}\n onPaste={(e: ClipboardEvent<HTMLInputElement>) => {\n e.preventDefault();\n const d = (e.clipboardData.getData('text') || '').replace(/[^\\d]/g, '');\n emit(chars.slice(0, i).join('') + d);\n refs.current[Math.min(i + d.length, length - 1)]?.focus();\n }}\n />,\n );\n }\n return <div className={cls}>{cells}</div>;\n}\n"]}
@@ -0,0 +1,39 @@
1
+ 'use client';import * as React from 'react';
2
+ import { jsxs, jsx } from 'react/jsx-runtime';
3
+
4
+ // src/components/avatar/AvatarGroup.tsx
5
+ function AvatarGroup({
6
+ children,
7
+ max = 5,
8
+ size = "md",
9
+ className = "",
10
+ ...rest
11
+ }) {
12
+ const items = React.Children.toArray(children);
13
+ const visible = max > 0 ? items.slice(0, max) : items;
14
+ const overflow = items.length - visible.length;
15
+ return /* @__PURE__ */ jsxs("span", { className: ["avatar-group", className].filter(Boolean).join(" "), ...rest, children: [
16
+ visible.map(
17
+ (child, i) => React.isValidElement(child) ? React.cloneElement(child, {
18
+ size,
19
+ key: child.key ?? i
20
+ }) : child
21
+ ),
22
+ overflow > 0 && /* @__PURE__ */ jsx(
23
+ "span",
24
+ {
25
+ className: `avatar avatar--${size} avatar--overflow`,
26
+ role: "img",
27
+ "aria-label": `${overflow} more`,
28
+ children: /* @__PURE__ */ jsx("span", { className: "avatar__face", children: /* @__PURE__ */ jsxs("span", { className: "avatar__initials", children: [
29
+ "+",
30
+ overflow
31
+ ] }) })
32
+ }
33
+ )
34
+ ] });
35
+ }
36
+
37
+ export { AvatarGroup };
38
+ //# sourceMappingURL=chunk-7OPMOET7.js.map
39
+ //# sourceMappingURL=chunk-7OPMOET7.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/avatar/AvatarGroup.tsx"],"names":[],"mappings":";;;;AAeO,SAAS,WAAA,CAAY;AAAA,EAC1B,QAAA;AAAA,EACA,GAAA,GAAM,CAAA;AAAA,EACN,IAAA,GAAO,IAAA;AAAA,EACP,SAAA,GAAY,EAAA;AAAA,EACZ,GAAG;AACL,CAAA,EAAqB;AACnB,EAAA,MAAM,KAAA,GAAc,KAAA,CAAA,QAAA,CAAS,OAAA,CAAQ,QAAQ,CAAA;AAC7C,EAAA,MAAM,UAAU,GAAA,GAAM,CAAA,GAAI,MAAM,KAAA,CAAM,CAAA,EAAG,GAAG,CAAA,GAAI,KAAA;AAChD,EAAA,MAAM,QAAA,GAAW,KAAA,CAAM,MAAA,GAAS,OAAA,CAAQ,MAAA;AAExC,EAAA,uBACE,IAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAW,CAAC,gBAAgB,SAAS,CAAA,CAAE,MAAA,CAAO,OAAO,CAAA,CAAE,IAAA,CAAK,GAAG,CAAA,EAAI,GAAG,IAAA,EACzE,QAAA,EAAA;AAAA,IAAA,OAAA,CAAQ,GAAA;AAAA,MAAI,CAAC,KAAA,EAAO,CAAA,KACb,qBAAe,KAAK,CAAA,GAChB,mBAAa,KAAA,EAAoD;AAAA,QACrE,IAAA;AAAA,QACA,GAAA,EAAK,MAAM,GAAA,IAAO;AAAA,OACnB,CAAA,GACD;AAAA,KACN;AAAA,IACC,WAAW,CAAA,oBACV,GAAA;AAAA,MAAC,MAAA;AAAA,MAAA;AAAA,QACC,SAAA,EAAW,kBAAkB,IAAI,CAAA,iBAAA,CAAA;AAAA,QACjC,IAAA,EAAK,KAAA;AAAA,QACL,YAAA,EAAY,GAAG,QAAQ,CAAA,KAAA,CAAA;AAAA,QAEvB,8BAAC,MAAA,EAAA,EAAK,SAAA,EAAU,gBACd,QAAA,kBAAA,IAAA,CAAC,MAAA,EAAA,EAAK,WAAU,kBAAA,EAAmB,QAAA,EAAA;AAAA,UAAA,GAAA;AAAA,UAAE;AAAA,SAAA,EAAS,CAAA,EAChD;AAAA;AAAA;AACF,GAAA,EAEJ,CAAA;AAEJ","file":"chunk-7OPMOET7.js","sourcesContent":["'use client';\n\n// AvatarGroup - stacks Avatars with overlap + a \"+N\" overflow chip; CSS drives the hover-spread.\n\nimport * as React from 'react';\nimport type { AvatarSize } from './Avatar';\n\nexport interface AvatarGroupProps extends React.HTMLAttributes<HTMLSpanElement> {\n children: React.ReactNode;\n /** Max visible avatars before \"+N\" overflow chip. Default 5. */\n max?: number;\n /** Uniform size applied to all children. Default 'md'. */\n size?: AvatarSize;\n}\n\nexport function AvatarGroup({\n children,\n max = 5,\n size = 'md',\n className = '',\n ...rest\n}: AvatarGroupProps) {\n const items = React.Children.toArray(children);\n const visible = max > 0 ? items.slice(0, max) : items;\n const overflow = items.length - visible.length;\n\n return (\n <span className={['avatar-group', className].filter(Boolean).join(' ')} {...rest}>\n {visible.map((child, i) =>\n React.isValidElement(child)\n ? React.cloneElement(child as React.ReactElement<{ size?: AvatarSize }>, {\n size,\n key: child.key ?? i,\n })\n : child,\n )}\n {overflow > 0 && (\n <span\n className={`avatar avatar--${size} avatar--overflow`}\n role=\"img\"\n aria-label={`${overflow} more`}\n >\n <span className=\"avatar__face\">\n <span className=\"avatar__initials\">+{overflow}</span>\n </span>\n </span>\n )}\n </span>\n );\n}\n"]}