@hex-core/components 1.3.0 → 1.4.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 (186) hide show
  1. package/README.md +183 -9
  2. package/dist/accordion.d.ts +13 -0
  3. package/dist/accordion.js +62 -0
  4. package/dist/accordion.js.map +1 -0
  5. package/dist/alert-dialog.d.ts +34 -0
  6. package/dist/alert-dialog.js +125 -0
  7. package/dist/alert-dialog.js.map +1 -0
  8. package/dist/alert.d.ts +17 -0
  9. package/dist/alert.js +54 -0
  10. package/dist/alert.js.map +1 -0
  11. package/dist/aspect-ratio.d.ts +7 -0
  12. package/dist/aspect-ratio.js +8 -0
  13. package/dist/aspect-ratio.js.map +1 -0
  14. package/dist/avatar.d.ts +11 -0
  15. package/dist/avatar.js +44 -0
  16. package/dist/avatar.js.map +1 -0
  17. package/dist/badge.d.ts +22 -0
  18. package/dist/badge.js +36 -0
  19. package/dist/badge.js.map +1 -0
  20. package/dist/breadcrumb.d.ts +27 -0
  21. package/dist/breadcrumb.js +120 -0
  22. package/dist/breadcrumb.js.map +1 -0
  23. package/dist/button-variants-Bx6gCUFp.d.ts +19 -0
  24. package/dist/button.d.ts +13 -0
  25. package/dist/button.js +113 -0
  26. package/dist/button.js.map +1 -0
  27. package/dist/calendar.d.ts +17 -0
  28. package/dist/calendar.js +126 -0
  29. package/dist/calendar.js.map +1 -0
  30. package/dist/card.d.ts +16 -0
  31. package/dist/card.js +68 -0
  32. package/dist/card.js.map +1 -0
  33. package/dist/checkbox.d.ts +11 -0
  34. package/dist/checkbox.js +65 -0
  35. package/dist/checkbox.js.map +1 -0
  36. package/dist/cluster.d.ts +34 -0
  37. package/dist/cluster.js +50 -0
  38. package/dist/cluster.js.map +1 -0
  39. package/dist/collapsible.d.ts +11 -0
  40. package/dist/collapsible.js +10 -0
  41. package/dist/collapsible.js.map +1 -0
  42. package/dist/color-picker.d.ts +44 -0
  43. package/dist/color-picker.js +321 -0
  44. package/dist/color-picker.js.map +1 -0
  45. package/dist/combobox.d.ts +45 -0
  46. package/dist/combobox.js +226 -0
  47. package/dist/combobox.js.map +1 -0
  48. package/dist/command.d.ts +111 -0
  49. package/dist/command.js +232 -0
  50. package/dist/command.js.map +1 -0
  51. package/dist/container.d.ts +41 -0
  52. package/dist/container.js +39 -0
  53. package/dist/container.js.map +1 -0
  54. package/dist/context-menu.d.ts +37 -0
  55. package/dist/context-menu.js +130 -0
  56. package/dist/context-menu.js.map +1 -0
  57. package/dist/data-table.d.ts +33 -0
  58. package/dist/data-table.js +103 -0
  59. package/dist/data-table.js.map +1 -0
  60. package/dist/date-picker.d.ts +43 -0
  61. package/dist/date-picker.js +221 -0
  62. package/dist/date-picker.js.map +1 -0
  63. package/dist/dialog.d.ts +46 -0
  64. package/dist/dialog.js +125 -0
  65. package/dist/dialog.js.map +1 -0
  66. package/dist/drawer.d.ts +41 -0
  67. package/dist/drawer.js +82 -0
  68. package/dist/drawer.js.map +1 -0
  69. package/dist/dropdown-menu.d.ts +39 -0
  70. package/dist/dropdown-menu.js +133 -0
  71. package/dist/dropdown-menu.js.map +1 -0
  72. package/dist/dropzone.d.ts +54 -0
  73. package/dist/dropzone.js +194 -0
  74. package/dist/dropzone.js.map +1 -0
  75. package/dist/file-tree.d.ts +53 -0
  76. package/dist/file-tree.js +322 -0
  77. package/dist/file-tree.js.map +1 -0
  78. package/dist/form.d.ts +45 -0
  79. package/dist/form.js +114 -0
  80. package/dist/form.js.map +1 -0
  81. package/dist/grid.d.ts +50 -0
  82. package/dist/grid.js +58 -0
  83. package/dist/grid.js.map +1 -0
  84. package/dist/hover-card.d.ts +11 -0
  85. package/dist/hover-card.js +34 -0
  86. package/dist/hover-card.js.map +1 -0
  87. package/dist/index.d.ts +98 -1564
  88. package/dist/index.js +527 -5536
  89. package/dist/index.js.map +1 -1
  90. package/dist/input-otp.d.ts +19 -0
  91. package/dist/input-otp.js +71 -0
  92. package/dist/input-otp.js.map +1 -0
  93. package/dist/input.d.ts +6 -0
  94. package/dist/input.js +40 -0
  95. package/dist/input.js.map +1 -0
  96. package/dist/label.d.ts +11 -0
  97. package/dist/label.js +22 -0
  98. package/dist/label.js.map +1 -0
  99. package/dist/menubar.d.ts +35 -0
  100. package/dist/menubar.js +106 -0
  101. package/dist/menubar.js.map +1 -0
  102. package/dist/multi-combobox.d.ts +51 -0
  103. package/dist/multi-combobox.js +258 -0
  104. package/dist/multi-combobox.js.map +1 -0
  105. package/dist/navigation-menu.d.ts +23 -0
  106. package/dist/navigation-menu.js +108 -0
  107. package/dist/navigation-menu.js.map +1 -0
  108. package/dist/pagination.d.ts +40 -0
  109. package/dist/pagination.js +195 -0
  110. package/dist/pagination.js.map +1 -0
  111. package/dist/popover.d.ts +13 -0
  112. package/dist/popover.js +35 -0
  113. package/dist/popover.js.map +1 -0
  114. package/dist/progress.d.ts +10 -0
  115. package/dist/progress.js +38 -0
  116. package/dist/progress.js.map +1 -0
  117. package/dist/radio-group.d.ts +9 -0
  118. package/dist/radio-group.js +44 -0
  119. package/dist/radio-group.js.map +1 -0
  120. package/dist/resizable.d.ts +28 -0
  121. package/dist/resizable.js +66 -0
  122. package/dist/resizable.js.map +1 -0
  123. package/dist/schemas.d.ts +121 -0
  124. package/dist/schemas.js +4643 -0
  125. package/dist/schemas.js.map +1 -0
  126. package/dist/scroll-area.d.ts +18 -0
  127. package/dist/scroll-area.js +55 -0
  128. package/dist/scroll-area.js.map +1 -0
  129. package/dist/select.d.ts +21 -0
  130. package/dist/select.js +136 -0
  131. package/dist/select.js.map +1 -0
  132. package/dist/separator.d.ts +11 -0
  133. package/dist/separator.js +29 -0
  134. package/dist/separator.js.map +1 -0
  135. package/dist/sheet.d.ts +39 -0
  136. package/dist/sheet.js +140 -0
  137. package/dist/sheet.js.map +1 -0
  138. package/dist/sidebar.d.ts +75 -0
  139. package/dist/sidebar.js +201 -0
  140. package/dist/sidebar.js.map +1 -0
  141. package/dist/skeleton.d.ts +11 -0
  142. package/dist/skeleton.js +21 -0
  143. package/dist/skeleton.js.map +1 -0
  144. package/dist/slider.d.ts +20 -0
  145. package/dist/slider.js +55 -0
  146. package/dist/slider.js.map +1 -0
  147. package/dist/sonner.d.ts +14 -0
  148. package/dist/sonner.js +27 -0
  149. package/dist/sonner.js.map +1 -0
  150. package/dist/spacer.d.ts +38 -0
  151. package/dist/spacer.js +43 -0
  152. package/dist/spacer.js.map +1 -0
  153. package/dist/stack.d.ts +34 -0
  154. package/dist/stack.js +49 -0
  155. package/dist/stack.js.map +1 -0
  156. package/dist/stepper.d.ts +48 -0
  157. package/dist/stepper.js +226 -0
  158. package/dist/stepper.js.map +1 -0
  159. package/dist/switch.d.ts +11 -0
  160. package/dist/switch.js +47 -0
  161. package/dist/switch.js.map +1 -0
  162. package/dist/table.d.ts +24 -0
  163. package/dist/table.js +85 -0
  164. package/dist/table.js.map +1 -0
  165. package/dist/tabs.d.ts +13 -0
  166. package/dist/tabs.js +57 -0
  167. package/dist/tabs.js.map +1 -0
  168. package/dist/textarea.d.ts +10 -0
  169. package/dist/textarea.js +36 -0
  170. package/dist/textarea.js.map +1 -0
  171. package/dist/time-picker.d.ts +34 -0
  172. package/dist/time-picker.js +50 -0
  173. package/dist/time-picker.js.map +1 -0
  174. package/dist/timeline.d.ts +42 -0
  175. package/dist/timeline.js +84 -0
  176. package/dist/timeline.js.map +1 -0
  177. package/dist/toggle-group.d.ts +17 -0
  178. package/dist/toggle-group.js +83 -0
  179. package/dist/toggle-group.js.map +1 -0
  180. package/dist/toggle.d.ts +19 -0
  181. package/dist/toggle.js +49 -0
  182. package/dist/toggle.js.map +1 -0
  183. package/dist/tooltip.d.ts +13 -0
  184. package/dist/tooltip.js +33 -0
  185. package/dist/tooltip.js.map +1 -0
  186. package/package.json +68 -16
@@ -0,0 +1,48 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import * as React from 'react';
3
+
4
+ type StepStatus = "complete" | "current" | "upcoming" | "error";
5
+ interface StepperStep {
6
+ /** Stable unique id used as the React key. */
7
+ id: string;
8
+ /** Step name shown next to the indicator. */
9
+ label: string;
10
+ /** Optional secondary text under the label. */
11
+ description?: string;
12
+ /** Disable the step (only applies when onStepClick is provided). */
13
+ disabled?: boolean;
14
+ /**
15
+ * Override the index-derived status. Use `"error"` to mark a failed step
16
+ * (e.g. validation failure in a form wizard); `"complete"` / `"current"` /
17
+ * `"upcoming"` are derived from `current` by default.
18
+ */
19
+ status?: StepStatus;
20
+ }
21
+ interface StepperProps extends Omit<React.HTMLAttributes<HTMLOListElement>, "aria-label" | "onClick"> {
22
+ /** Ordered list of steps. */
23
+ steps: StepperStep[];
24
+ /** Index of the current step (controlled). */
25
+ current: number;
26
+ /** Layout direction. */
27
+ orientation?: "horizontal" | "vertical";
28
+ /** Indicator size. */
29
+ size?: "sm" | "md";
30
+ /** When provided, each step is rendered as a clickable button. */
31
+ onStepClick?: (index: number) => void;
32
+ /** Required accessible name for the ordered list. */
33
+ "aria-label": string;
34
+ }
35
+ /**
36
+ * Linear progress indicator for multi-step flows (form wizards, onboarding,
37
+ * checkout). Pure semantic HTML — `<ol>` of `<li>` with `aria-current="step"`
38
+ * on the current item; per-step `status` overrides allow marking "error".
39
+ *
40
+ * Pass `onStepClick` to make completed/non-disabled steps interactive.
41
+ * @returns An accessible ordered step list.
42
+ */
43
+ declare function Stepper({ steps, current, orientation, size, onStepClick, "aria-label": ariaLabel, className, ...rest }: StepperProps): react_jsx_runtime.JSX.Element;
44
+ declare namespace Stepper {
45
+ var displayName: string;
46
+ }
47
+
48
+ export { type StepStatus, Stepper, type StepperProps, type StepperStep };
@@ -0,0 +1,226 @@
1
+ "use client";
2
+ import { cva } from 'class-variance-authority';
3
+ import { clsx } from 'clsx';
4
+ import { twMerge } from 'tailwind-merge';
5
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
6
+
7
+ function cn(...inputs) {
8
+ return twMerge(clsx(inputs));
9
+ }
10
+ var stepperRoot = cva(
11
+ "flex w-full gap-[var(--gap-md,1rem)] list-none p-0 m-0",
12
+ {
13
+ variants: {
14
+ orientation: {
15
+ horizontal: "flex-row items-start",
16
+ vertical: "flex-col items-stretch"
17
+ }
18
+ },
19
+ defaultVariants: { orientation: "horizontal" }
20
+ }
21
+ );
22
+ var stepItem = cva("flex gap-[var(--space-3,0.75rem)]", {
23
+ variants: {
24
+ orientation: {
25
+ horizontal: "flex-row items-center",
26
+ vertical: "flex-row items-start w-full"
27
+ }
28
+ },
29
+ defaultVariants: { orientation: "horizontal" }
30
+ });
31
+ var stepIndicator = cva(
32
+ "inline-flex shrink-0 items-center justify-center rounded-full border-2 font-medium transition-colors duration-[var(--duration-normal,200ms)] ease-out",
33
+ {
34
+ variants: {
35
+ size: {
36
+ sm: "h-7 w-7 text-xs",
37
+ md: "h-[var(--control-height-sm,2.25rem)] w-[var(--control-height-sm,2.25rem)] text-sm"
38
+ },
39
+ status: {
40
+ complete: "bg-primary border-primary text-primary-foreground",
41
+ current: "bg-background border-primary text-primary",
42
+ upcoming: "bg-background border-input text-muted-foreground",
43
+ error: "bg-destructive border-destructive text-destructive-foreground"
44
+ }
45
+ },
46
+ defaultVariants: { size: "md", status: "upcoming" }
47
+ }
48
+ );
49
+ var stepConnector = cva("bg-input transition-colors", {
50
+ variants: {
51
+ orientation: {
52
+ horizontal: "h-px flex-1 min-w-[var(--space-6,1.5rem)] mx-[var(--space-2,0.5rem)]",
53
+ vertical: "w-px self-stretch ml-[1.0625rem] my-[var(--space-1,0.25rem)] min-h-[var(--space-6,1.5rem)]"
54
+ },
55
+ complete: {
56
+ true: "bg-primary",
57
+ false: ""
58
+ }
59
+ },
60
+ defaultVariants: { orientation: "horizontal", complete: false }
61
+ });
62
+ function deriveStatus(index, current) {
63
+ if (index < current) return "complete";
64
+ if (index === current) return "current";
65
+ return "upcoming";
66
+ }
67
+ function StepCheck() {
68
+ return /* @__PURE__ */ jsx(
69
+ "svg",
70
+ {
71
+ xmlns: "http://www.w3.org/2000/svg",
72
+ viewBox: "0 0 24 24",
73
+ fill: "none",
74
+ stroke: "currentColor",
75
+ strokeWidth: "3",
76
+ strokeLinecap: "round",
77
+ strokeLinejoin: "round",
78
+ className: "h-4 w-4",
79
+ "aria-hidden": "true",
80
+ children: /* @__PURE__ */ jsx("polyline", { points: "20 6 9 17 4 12" })
81
+ }
82
+ );
83
+ }
84
+ function StepError() {
85
+ return /* @__PURE__ */ jsxs(
86
+ "svg",
87
+ {
88
+ xmlns: "http://www.w3.org/2000/svg",
89
+ viewBox: "0 0 24 24",
90
+ fill: "none",
91
+ stroke: "currentColor",
92
+ strokeWidth: "3",
93
+ strokeLinecap: "round",
94
+ strokeLinejoin: "round",
95
+ className: "h-4 w-4",
96
+ "aria-hidden": "true",
97
+ children: [
98
+ /* @__PURE__ */ jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" }),
99
+ /* @__PURE__ */ jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" })
100
+ ]
101
+ }
102
+ );
103
+ }
104
+ function StepIndicator({ index, status, size }) {
105
+ return /* @__PURE__ */ jsx(
106
+ "span",
107
+ {
108
+ className: stepIndicator({ size, status }),
109
+ "aria-invalid": status === "error" ? true : void 0,
110
+ children: status === "complete" ? /* @__PURE__ */ jsx(StepCheck, {}) : status === "error" ? /* @__PURE__ */ jsx(StepError, {}) : index + 1
111
+ }
112
+ );
113
+ }
114
+ function Stepper({
115
+ steps,
116
+ current,
117
+ orientation = "horizontal",
118
+ size = "md",
119
+ onStepClick,
120
+ "aria-label": ariaLabel,
121
+ className,
122
+ ...rest
123
+ }) {
124
+ const interactive = typeof onStepClick === "function";
125
+ return /* @__PURE__ */ jsx(
126
+ "ol",
127
+ {
128
+ "aria-label": ariaLabel,
129
+ className: cn(stepperRoot({ orientation }), className),
130
+ ...rest,
131
+ children: steps.map((step, index) => {
132
+ const status = step.status ?? deriveStatus(index, current);
133
+ const isCurrent = status === "current";
134
+ const isLast = index === steps.length - 1;
135
+ const labelNode = /* @__PURE__ */ jsxs("span", { className: "flex flex-col gap-[var(--space-1,0.25rem)]", children: [
136
+ /* @__PURE__ */ jsxs(
137
+ "span",
138
+ {
139
+ className: cn(
140
+ "text-sm font-medium whitespace-nowrap",
141
+ isCurrent && "text-foreground",
142
+ status === "complete" && "text-foreground",
143
+ status === "upcoming" && "text-muted-foreground",
144
+ status === "error" && "text-destructive"
145
+ ),
146
+ children: [
147
+ status === "complete" && /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Completed: " }),
148
+ status === "error" && /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Error: " }),
149
+ step.label
150
+ ]
151
+ }
152
+ ),
153
+ step.description ? /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: step.description }) : null
154
+ ] });
155
+ const innerContent = /* @__PURE__ */ jsxs(Fragment, { children: [
156
+ /* @__PURE__ */ jsx(StepIndicator, { index, status, size }),
157
+ labelNode
158
+ ] });
159
+ return (
160
+ /*
161
+ * `aria-current="step"` lives on the <li> itself so screen
162
+ * readers announce it as part of the listitem's intro
163
+ * (per WAI guidance for "step" lists), not buried on an
164
+ * interior span/button.
165
+ */
166
+ /* @__PURE__ */ jsxs(
167
+ "li",
168
+ {
169
+ "aria-current": isCurrent ? "step" : void 0,
170
+ className: cn(
171
+ stepItem({ orientation }),
172
+ /*
173
+ * Grow only when there's a connector after this step.
174
+ * The connector inside takes the extra space via
175
+ * `flex-1` so the line spans to the next step.
176
+ */
177
+ !isLast && orientation === "horizontal" && "flex-1",
178
+ !isLast && orientation === "vertical" && "flex-col"
179
+ ),
180
+ children: [
181
+ interactive ? /* @__PURE__ */ jsx(
182
+ "button",
183
+ {
184
+ type: "button",
185
+ disabled: step.disabled,
186
+ onClick: () => onStepClick?.(index),
187
+ className: cn(
188
+ "flex items-center gap-[var(--space-3,0.75rem)] text-left rounded-md transition-colors duration-[var(--duration-normal,200ms)] ease-out",
189
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
190
+ "disabled:opacity-50 disabled:pointer-events-none"
191
+ ),
192
+ children: innerContent
193
+ }
194
+ ) : /* @__PURE__ */ jsx("span", { className: "flex items-center gap-[var(--space-3,0.75rem)]", children: innerContent }),
195
+ !isLast ? (
196
+ /*
197
+ * Connector "complete" iff THIS step is finished. An
198
+ * explicit "error" status on the current step never
199
+ * fills the gap to the next step — the user hasn't
200
+ * cleared this milestone.
201
+ */
202
+ /* @__PURE__ */ jsx(
203
+ "span",
204
+ {
205
+ "aria-hidden": "true",
206
+ className: stepConnector({
207
+ orientation,
208
+ complete: index < current && step.status !== "error"
209
+ })
210
+ }
211
+ )
212
+ ) : null
213
+ ]
214
+ },
215
+ step.id
216
+ )
217
+ );
218
+ })
219
+ }
220
+ );
221
+ }
222
+ Stepper.displayName = "Stepper";
223
+
224
+ export { Stepper };
225
+ //# sourceMappingURL=stepper.js.map
226
+ //# sourceMappingURL=stepper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/utils.ts","../src/components/stepper/stepper.tsx"],"names":[],"mappings":"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","file":"stepper.js","sourcesContent":["import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/**\n * Merge class names with Tailwind CSS conflict resolution.\n * @param inputs - Class values (strings, arrays, objects) to merge\n * @returns A single merged class string with Tailwind conflicts resolved\n */\nexport function cn(...inputs: ClassValue[]) {\n\treturn twMerge(clsx(inputs));\n}\n","\"use client\";\n\nimport { cva } from \"class-variance-authority\";\nimport * as React from \"react\";\nimport { cn } from \"../../lib/utils.js\";\n\ntype StepStatus = \"complete\" | \"current\" | \"upcoming\" | \"error\";\n\ninterface StepperStep {\n\t/** Stable unique id used as the React key. */\n\tid: string;\n\t/** Step name shown next to the indicator. */\n\tlabel: string;\n\t/** Optional secondary text under the label. */\n\tdescription?: string;\n\t/** Disable the step (only applies when onStepClick is provided). */\n\tdisabled?: boolean;\n\t/**\n\t * Override the index-derived status. Use `\"error\"` to mark a failed step\n\t * (e.g. validation failure in a form wizard); `\"complete\"` / `\"current\"` /\n\t * `\"upcoming\"` are derived from `current` by default.\n\t */\n\tstatus?: StepStatus;\n}\n\nconst stepperRoot = cva(\n\t\"flex w-full gap-[var(--gap-md,1rem)] list-none p-0 m-0\",\n\t{\n\t\tvariants: {\n\t\t\torientation: {\n\t\t\t\thorizontal: \"flex-row items-start\",\n\t\t\t\tvertical: \"flex-col items-stretch\",\n\t\t\t},\n\t\t},\n\t\tdefaultVariants: { orientation: \"horizontal\" },\n\t},\n);\n\n/*\n * Horizontal: each step sizes to its content; the connector (`flex-1`) fills\n * the gap between steps. Going `flex-1` on the step item itself would shrink\n * labels to the point of `text-overflow: ellipsis` (\"Account\" → \"A...\").\n * Vertical: items take the full width so multi-line descriptions wrap\n * naturally below the indicator.\n */\nconst stepItem = cva(\"flex gap-[var(--space-3,0.75rem)]\", {\n\tvariants: {\n\t\torientation: {\n\t\t\thorizontal: \"flex-row items-center\",\n\t\t\tvertical: \"flex-row items-start w-full\",\n\t\t},\n\t},\n\tdefaultVariants: { orientation: \"horizontal\" },\n});\n\nconst stepIndicator = cva(\n\t\"inline-flex shrink-0 items-center justify-center rounded-full border-2 font-medium transition-colors duration-[var(--duration-normal,200ms)] ease-out\",\n\t{\n\t\tvariants: {\n\t\t\tsize: {\n\t\t\t\tsm: \"h-7 w-7 text-xs\",\n\t\t\t\tmd: \"h-[var(--control-height-sm,2.25rem)] w-[var(--control-height-sm,2.25rem)] text-sm\",\n\t\t\t},\n\t\t\tstatus: {\n\t\t\t\tcomplete: \"bg-primary border-primary text-primary-foreground\",\n\t\t\t\tcurrent: \"bg-background border-primary text-primary\",\n\t\t\t\tupcoming: \"bg-background border-input text-muted-foreground\",\n\t\t\t\terror:\n\t\t\t\t\t\"bg-destructive border-destructive text-destructive-foreground\",\n\t\t\t},\n\t\t},\n\t\tdefaultVariants: { size: \"md\", status: \"upcoming\" },\n\t},\n);\n\nconst stepConnector = cva(\"bg-input transition-colors\", {\n\tvariants: {\n\t\torientation: {\n\t\t\thorizontal: \"h-px flex-1 min-w-[var(--space-6,1.5rem)] mx-[var(--space-2,0.5rem)]\",\n\t\t\tvertical: \"w-px self-stretch ml-[1.0625rem] my-[var(--space-1,0.25rem)] min-h-[var(--space-6,1.5rem)]\",\n\t\t},\n\t\tcomplete: {\n\t\t\ttrue: \"bg-primary\",\n\t\t\tfalse: \"\",\n\t\t},\n\t},\n\tdefaultVariants: { orientation: \"horizontal\", complete: false },\n});\n\ninterface StepperProps\n\textends Omit<\n\t\tReact.HTMLAttributes<HTMLOListElement>,\n\t\t\"aria-label\" | \"onClick\"\n\t> {\n\t/** Ordered list of steps. */\n\tsteps: StepperStep[];\n\t/** Index of the current step (controlled). */\n\tcurrent: number;\n\t/** Layout direction. */\n\torientation?: \"horizontal\" | \"vertical\";\n\t/** Indicator size. */\n\tsize?: \"sm\" | \"md\";\n\t/** When provided, each step is rendered as a clickable button. */\n\tonStepClick?: (index: number) => void;\n\t/** Required accessible name for the ordered list. */\n\t\"aria-label\": string;\n}\n\n/** Map a step index against the current pointer to a `StepStatus`. */\nfunction deriveStatus(index: number, current: number): StepStatus {\n\tif (index < current) return \"complete\";\n\tif (index === current) return \"current\";\n\treturn \"upcoming\";\n}\n\n/** Checkmark glyph rendered inside the indicator for completed steps. */\nfunction StepCheck() {\n\treturn (\n\t\t<svg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tstrokeWidth=\"3\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\tclassName=\"h-4 w-4\"\n\t\t\taria-hidden=\"true\"\n\t\t>\n\t\t\t<polyline points=\"20 6 9 17 4 12\" />\n\t\t</svg>\n\t);\n}\n\n/** Cross glyph rendered inside the indicator for steps with status=\"error\". */\nfunction StepError() {\n\treturn (\n\t\t<svg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tstrokeWidth=\"3\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\tclassName=\"h-4 w-4\"\n\t\t\taria-hidden=\"true\"\n\t\t>\n\t\t\t<line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n\t\t\t<line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n\t\t</svg>\n\t);\n}\n\ninterface StepIndicatorProps {\n\tindex: number;\n\tstatus: StepStatus;\n\tsize: \"sm\" | \"md\";\n}\n\n/** Circular indicator that flips between number, check, and cross by `status`. */\nfunction StepIndicator({ index, status, size }: StepIndicatorProps) {\n\treturn (\n\t\t<span\n\t\t\tclassName={stepIndicator({ size, status })}\n\t\t\taria-invalid={status === \"error\" ? true : undefined}\n\t\t>\n\t\t\t{status === \"complete\" ? (\n\t\t\t\t<StepCheck />\n\t\t\t) : status === \"error\" ? (\n\t\t\t\t<StepError />\n\t\t\t) : (\n\t\t\t\tindex + 1\n\t\t\t)}\n\t\t</span>\n\t);\n}\n\n/**\n * Linear progress indicator for multi-step flows (form wizards, onboarding,\n * checkout). Pure semantic HTML — `<ol>` of `<li>` with `aria-current=\"step\"`\n * on the current item; per-step `status` overrides allow marking \"error\".\n *\n * Pass `onStepClick` to make completed/non-disabled steps interactive.\n * @returns An accessible ordered step list.\n */\nfunction Stepper({\n\tsteps,\n\tcurrent,\n\torientation = \"horizontal\",\n\tsize = \"md\",\n\tonStepClick,\n\t\"aria-label\": ariaLabel,\n\tclassName,\n\t...rest\n}: StepperProps) {\n\tconst interactive = typeof onStepClick === \"function\";\n\treturn (\n\t\t<ol\n\t\t\taria-label={ariaLabel}\n\t\t\tclassName={cn(stepperRoot({ orientation }), className)}\n\t\t\t{...rest}\n\t\t>\n\t\t\t{steps.map((step, index) => {\n\t\t\t\tconst status = step.status ?? deriveStatus(index, current);\n\t\t\t\tconst isCurrent = status === \"current\";\n\t\t\t\tconst isLast = index === steps.length - 1;\n\t\t\t\tconst labelNode = (\n\t\t\t\t\t<span className=\"flex flex-col gap-[var(--space-1,0.25rem)]\">\n\t\t\t\t\t\t<span\n\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\"text-sm font-medium whitespace-nowrap\",\n\t\t\t\t\t\t\t\tisCurrent && \"text-foreground\",\n\t\t\t\t\t\t\t\tstatus === \"complete\" && \"text-foreground\",\n\t\t\t\t\t\t\t\tstatus === \"upcoming\" && \"text-muted-foreground\",\n\t\t\t\t\t\t\t\tstatus === \"error\" && \"text-destructive\",\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{status === \"complete\" && (\n\t\t\t\t\t\t\t\t<span className=\"sr-only\">Completed: </span>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t{status === \"error\" && (\n\t\t\t\t\t\t\t\t<span className=\"sr-only\">Error: </span>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t{step.label}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t{step.description ? (\n\t\t\t\t\t\t\t<span className=\"text-xs text-muted-foreground\">\n\t\t\t\t\t\t\t\t{step.description}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t) : null}\n\t\t\t\t\t</span>\n\t\t\t\t);\n\n\t\t\t\tconst innerContent = (\n\t\t\t\t\t<>\n\t\t\t\t\t\t<StepIndicator index={index} status={status} size={size} />\n\t\t\t\t\t\t{labelNode}\n\t\t\t\t\t</>\n\t\t\t\t);\n\n\t\t\t\treturn (\n\t\t\t\t\t/*\n\t\t\t\t\t * `aria-current=\"step\"` lives on the <li> itself so screen\n\t\t\t\t\t * readers announce it as part of the listitem's intro\n\t\t\t\t\t * (per WAI guidance for \"step\" lists), not buried on an\n\t\t\t\t\t * interior span/button.\n\t\t\t\t\t */\n\t\t\t\t\t<li\n\t\t\t\t\t\tkey={step.id}\n\t\t\t\t\t\taria-current={isCurrent ? \"step\" : undefined}\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\tstepItem({ orientation }),\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t * Grow only when there's a connector after this step.\n\t\t\t\t\t\t\t * The connector inside takes the extra space via\n\t\t\t\t\t\t\t * `flex-1` so the line spans to the next step.\n\t\t\t\t\t\t\t */\n\t\t\t\t\t\t\t!isLast && orientation === \"horizontal\" && \"flex-1\",\n\t\t\t\t\t\t\t!isLast && orientation === \"vertical\" && \"flex-col\",\n\t\t\t\t\t\t)}\n\t\t\t\t\t>\n\t\t\t\t\t\t{interactive ? (\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tdisabled={step.disabled}\n\t\t\t\t\t\t\t\tonClick={() => onStepClick?.(index)}\n\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\"flex items-center gap-[var(--space-3,0.75rem)] text-left rounded-md transition-colors duration-[var(--duration-normal,200ms)] ease-out\",\n\t\t\t\t\t\t\t\t\t\"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\",\n\t\t\t\t\t\t\t\t\t\"disabled:opacity-50 disabled:pointer-events-none\",\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{innerContent}\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<span className=\"flex items-center gap-[var(--space-3,0.75rem)]\">\n\t\t\t\t\t\t\t\t{innerContent}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t{!isLast ? (\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t * Connector \"complete\" iff THIS step is finished. An\n\t\t\t\t\t\t\t * explicit \"error\" status on the current step never\n\t\t\t\t\t\t\t * fills the gap to the next step — the user hasn't\n\t\t\t\t\t\t\t * cleared this milestone.\n\t\t\t\t\t\t\t */\n\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t\t\tclassName={stepConnector({\n\t\t\t\t\t\t\t\t\torientation,\n\t\t\t\t\t\t\t\t\tcomplete: index < current && step.status !== \"error\",\n\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t) : null}\n\t\t\t\t\t</li>\n\t\t\t\t);\n\t\t\t})}\n\t\t</ol>\n\t);\n}\nStepper.displayName = \"Stepper\";\n\nexport { Stepper };\nexport type { StepperProps, StepperStep, StepStatus };\n"]}
@@ -0,0 +1,11 @@
1
+ import * as React from 'react';
2
+ import * as SwitchPrimitive from '@radix-ui/react-switch';
3
+
4
+ /**
5
+ * An accessible toggle switch built on Radix UI.
6
+ * Use for instant on/off settings that take effect immediately.
7
+ */
8
+ type SwitchProps = React.ComponentPropsWithoutRef<typeof SwitchPrimitive.Root>;
9
+ declare const Switch: React.ForwardRefExoticComponent<Omit<SwitchPrimitive.SwitchProps & React.RefAttributes<HTMLButtonElement>, "ref"> & React.RefAttributes<HTMLButtonElement>>;
10
+
11
+ export { Switch, type SwitchProps };
package/dist/switch.js ADDED
@@ -0,0 +1,47 @@
1
+ "use client";
2
+ import * as React from 'react';
3
+ import * as SwitchPrimitive from '@radix-ui/react-switch';
4
+ import { clsx } from 'clsx';
5
+ import { twMerge } from 'tailwind-merge';
6
+ import { jsx } from 'react/jsx-runtime';
7
+
8
+ function cn(...inputs) {
9
+ return twMerge(clsx(inputs));
10
+ }
11
+ var Switch = React.forwardRef(
12
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsx(
13
+ SwitchPrimitive.Root,
14
+ {
15
+ className: cn(
16
+ "peer inline-flex h-6 w-[var(--control-height-lg,2.75rem)] shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent",
17
+ "transition-all duration-[var(--duration-normal,200ms)] ease-out",
18
+ "shadow-sm",
19
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
20
+ "disabled:cursor-not-allowed disabled:opacity-50",
21
+ "data-[state=checked]:bg-primary data-[state=unchecked]:bg-input",
22
+ // Unchecked track shares --color-input with form borders (~1.27:1 vs white) so
23
+ // add an inset ring to make the track visible on flat surfaces.
24
+ "data-[state=unchecked]:inset-ring-1 data-[state=unchecked]:inset-ring-foreground/[0.08]",
25
+ "hover:shadow-md",
26
+ className
27
+ ),
28
+ ...props,
29
+ ref,
30
+ children: /* @__PURE__ */ jsx(
31
+ SwitchPrimitive.Thumb,
32
+ {
33
+ className: cn(
34
+ "pointer-events-none block h-5 w-5 rounded-full bg-background shadow-lg ring-0",
35
+ "transition-transform duration-[var(--duration-normal,200ms)] ease-out",
36
+ "data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0"
37
+ )
38
+ }
39
+ )
40
+ }
41
+ )
42
+ );
43
+ Switch.displayName = "Switch";
44
+
45
+ export { Switch };
46
+ //# sourceMappingURL=switch.js.map
47
+ //# sourceMappingURL=switch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/utils.ts","../src/primitives/switch/switch.tsx"],"names":[],"mappings":";;;;;;AAQO,SAAS,MAAM,MAAA,EAAsB;AAC3C,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAC,CAAA;AAC5B;ACEA,IAAM,MAAA,GAAe,KAAA,CAAA,UAAA;AAAA,EACpB,CAAC,EAAE,SAAA,EAAW,GAAG,KAAA,IAAS,GAAA,qBACzB,GAAA;AAAA,IAAiB,eAAA,CAAA,IAAA;AAAA,IAAhB;AAAA,MACA,SAAA,EAAW,EAAA;AAAA,QACV,yIAAA;AAAA,QACA,iEAAA;AAAA,QACA,WAAA;AAAA,QACA,0IAAA;AAAA,QACA,iDAAA;AAAA,QACA,iEAAA;AAAA;AAAA;AAAA,QAGA,yFAAA;AAAA,QACA,iBAAA;AAAA,QACA;AAAA,OACD;AAAA,MACC,GAAG,KAAA;AAAA,MACJ,GAAA;AAAA,MAEA,QAAA,kBAAA,GAAA;AAAA,QAAiB,eAAA,CAAA,KAAA;AAAA,QAAhB;AAAA,UACA,SAAA,EAAW,EAAA;AAAA,YACV,+EAAA;AAAA,YACA,uEAAA;AAAA,YACA;AAAA;AACD;AAAA;AACD;AAAA;AAGH;AACA,MAAA,CAAO,WAAA,GAAc,QAAA","file":"switch.js","sourcesContent":["import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/**\n * Merge class names with Tailwind CSS conflict resolution.\n * @param inputs - Class values (strings, arrays, objects) to merge\n * @returns A single merged class string with Tailwind conflicts resolved\n */\nexport function cn(...inputs: ClassValue[]) {\n\treturn twMerge(clsx(inputs));\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport * as SwitchPrimitive from \"@radix-ui/react-switch\";\nimport { cn } from \"../../lib/utils.js\";\n\n/**\n * An accessible toggle switch built on Radix UI.\n * Use for instant on/off settings that take effect immediately.\n */\nexport type SwitchProps = React.ComponentPropsWithoutRef<typeof SwitchPrimitive.Root>;\n\nconst Switch = React.forwardRef<React.ComponentRef<typeof SwitchPrimitive.Root>, SwitchProps>(\n\t({ className, ...props }, ref) => (\n\t\t<SwitchPrimitive.Root\n\t\t\tclassName={cn(\n\t\t\t\t\"peer inline-flex h-6 w-[var(--control-height-lg,2.75rem)] shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent\",\n\t\t\t\t\"transition-all duration-[var(--duration-normal,200ms)] ease-out\",\n\t\t\t\t\"shadow-sm\",\n\t\t\t\t\"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background\",\n\t\t\t\t\"disabled:cursor-not-allowed disabled:opacity-50\",\n\t\t\t\t\"data-[state=checked]:bg-primary data-[state=unchecked]:bg-input\",\n\t\t\t\t// Unchecked track shares --color-input with form borders (~1.27:1 vs white) so\n\t\t\t\t// add an inset ring to make the track visible on flat surfaces.\n\t\t\t\t\"data-[state=unchecked]:inset-ring-1 data-[state=unchecked]:inset-ring-foreground/[0.08]\",\n\t\t\t\t\"hover:shadow-md\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t\tref={ref}\n\t\t>\n\t\t\t<SwitchPrimitive.Thumb\n\t\t\t\tclassName={cn(\n\t\t\t\t\t\"pointer-events-none block h-5 w-5 rounded-full bg-background shadow-lg ring-0\",\n\t\t\t\t\t\"transition-transform duration-[var(--duration-normal,200ms)] ease-out\",\n\t\t\t\t\t\"data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0\",\n\t\t\t\t)}\n\t\t\t/>\n\t\t</SwitchPrimitive.Root>\n\t),\n);\nSwitch.displayName = \"Switch\";\n\nexport { Switch };\n"]}
@@ -0,0 +1,24 @@
1
+ import * as React from 'react';
2
+
3
+ /** A responsive container + styled HTML table. */
4
+ declare const Table: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLTableElement> & React.RefAttributes<HTMLTableElement>>;
5
+ /** `<thead>` wrapper with bottom border. */
6
+ declare const TableHeader: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLTableSectionElement> & React.RefAttributes<HTMLTableSectionElement>>;
7
+ /** `<tbody>` wrapper removing bottom border on last row. */
8
+ declare const TableBody: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLTableSectionElement> & React.RefAttributes<HTMLTableSectionElement>>;
9
+ /** `<tfoot>` wrapper with muted background. */
10
+ declare const TableFooter: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLTableSectionElement> & React.RefAttributes<HTMLTableSectionElement>>;
11
+ /** `<tr>` with hover + selected states. */
12
+ declare const TableRow: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLTableRowElement> & React.RefAttributes<HTMLTableRowElement>>;
13
+ /** `<th>` with left-aligned muted text. */
14
+ declare const TableHead: React.ForwardRefExoticComponent<React.ThHTMLAttributes<HTMLTableCellElement> & React.RefAttributes<HTMLTableCellElement>>;
15
+ /** `<td>` with consistent padding. */
16
+ declare const TableCell: React.ForwardRefExoticComponent<React.TdHTMLAttributes<HTMLTableCellElement> & React.RefAttributes<HTMLTableCellElement>>;
17
+ /**
18
+ * Visible `<caption>` rendered below the table. The parent `<Table>` sets
19
+ * `caption-bottom`, so the caption is announced first by screen readers when
20
+ * entering the table, then visually placed below the rows.
21
+ */
22
+ declare const TableCaption: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLTableCaptionElement> & React.RefAttributes<HTMLTableCaptionElement>>;
23
+
24
+ export { Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow };
package/dist/table.js ADDED
@@ -0,0 +1,85 @@
1
+ import * as React from 'react';
2
+ import { clsx } from 'clsx';
3
+ import { twMerge } from 'tailwind-merge';
4
+ import { jsx } from 'react/jsx-runtime';
5
+
6
+ // src/components/table/table.tsx
7
+ function cn(...inputs) {
8
+ return twMerge(clsx(inputs));
9
+ }
10
+ var Table = React.forwardRef(
11
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { className: "relative w-full overflow-auto", children: /* @__PURE__ */ jsx(
12
+ "table",
13
+ {
14
+ ref,
15
+ className: cn("w-full caption-bottom text-sm", className),
16
+ ...props
17
+ }
18
+ ) })
19
+ );
20
+ Table.displayName = "Table";
21
+ var TableHeader = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("thead", { ref, className: cn("[&_tr]:border-b [&_tr]:border-b-foreground/[0.08]", className), ...props }));
22
+ TableHeader.displayName = "TableHeader";
23
+ var TableBody = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("tbody", { ref, className: cn("[&_tr:last-child]:border-0", className), ...props }));
24
+ TableBody.displayName = "TableBody";
25
+ var TableFooter = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
26
+ "tfoot",
27
+ {
28
+ ref,
29
+ className: cn(
30
+ "border-t border-t-foreground/[0.08] bg-muted/50 font-medium [&>tr]:last:border-b-0",
31
+ className
32
+ ),
33
+ ...props
34
+ }
35
+ ));
36
+ TableFooter.displayName = "TableFooter";
37
+ var TableRow = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
38
+ "tr",
39
+ {
40
+ ref,
41
+ className: cn(
42
+ "border-b border-b-foreground/[0.08] transition-all duration-[var(--duration-normal,200ms)] ease-out hover:bg-muted/50 data-[state=selected]:bg-muted",
43
+ className
44
+ ),
45
+ ...props
46
+ }
47
+ ));
48
+ TableRow.displayName = "TableRow";
49
+ var TableHead = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
50
+ "th",
51
+ {
52
+ ref,
53
+ className: cn(
54
+ "h-[var(--control-height-md,2.5rem)] px-[var(--space-4,1rem)] text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0",
55
+ className
56
+ ),
57
+ ...props
58
+ }
59
+ ));
60
+ TableHead.displayName = "TableHead";
61
+ var TableCell = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
62
+ "td",
63
+ {
64
+ ref,
65
+ className: cn("p-[var(--space-4,1rem)] align-middle [&:has([role=checkbox])]:pr-0", className),
66
+ ...props
67
+ }
68
+ ));
69
+ TableCell.displayName = "TableCell";
70
+ var TableCaption = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
71
+ "caption",
72
+ {
73
+ ref,
74
+ className: cn(
75
+ "caption-bottom mt-[var(--space-4,1rem)] text-sm text-muted-foreground",
76
+ className
77
+ ),
78
+ ...props
79
+ }
80
+ ));
81
+ TableCaption.displayName = "TableCaption";
82
+
83
+ export { Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow };
84
+ //# sourceMappingURL=table.js.map
85
+ //# sourceMappingURL=table.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/utils.ts","../src/components/table/table.tsx"],"names":[],"mappings":";;;;;;AAQO,SAAS,MAAM,MAAA,EAAsB;AAC3C,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAC,CAAA;AAC5B;ACNA,IAAM,KAAA,GAAc,KAAA,CAAA,UAAA;AAAA,EACnB,CAAC,EAAE,SAAA,EAAW,GAAG,KAAA,IAAS,GAAA,qBACzB,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,+BAAA,EACd,QAAA,kBAAA,GAAA;AAAA,IAAC,OAAA;AAAA,IAAA;AAAA,MACA,GAAA;AAAA,MACA,SAAA,EAAW,EAAA,CAAG,+BAAA,EAAiC,SAAS,CAAA;AAAA,MACvD,GAAG;AAAA;AAAA,GACL,EACD;AAEF;AACA,KAAA,CAAM,WAAA,GAAc,OAAA;AAGpB,IAAM,cAAoB,KAAA,CAAA,UAAA,CAGxB,CAAC,EAAE,SAAA,EAAW,GAAG,OAAM,EAAG,GAAA,yBAC1B,OAAA,EAAA,EAAM,GAAA,EAAU,WAAW,EAAA,CAAG,mDAAA,EAAqD,SAAS,CAAA,EAAI,GAAG,OAAO,CAC3G;AACD,WAAA,CAAY,WAAA,GAAc,aAAA;AAG1B,IAAM,YAAkB,KAAA,CAAA,UAAA,CAGtB,CAAC,EAAE,SAAA,EAAW,GAAG,OAAM,EAAG,GAAA,yBAC1B,OAAA,EAAA,EAAM,GAAA,EAAU,WAAW,EAAA,CAAG,4BAAA,EAA8B,SAAS,CAAA,EAAI,GAAG,OAAO,CACpF;AACD,SAAA,CAAU,WAAA,GAAc,WAAA;AAGxB,IAAM,WAAA,GAAoB,iBAGxB,CAAC,EAAE,WAAW,GAAG,KAAA,IAAS,GAAA,qBAC3B,GAAA;AAAA,EAAC,OAAA;AAAA,EAAA;AAAA,IACA,GAAA;AAAA,IACA,SAAA,EAAW,EAAA;AAAA,MACV,oFAAA;AAAA,MACA;AAAA,KACD;AAAA,IACC,GAAG;AAAA;AACL,CACA;AACD,WAAA,CAAY,WAAA,GAAc,aAAA;AAG1B,IAAM,QAAA,GAAiB,iBAGrB,CAAC,EAAE,WAAW,GAAG,KAAA,IAAS,GAAA,qBAC3B,GAAA;AAAA,EAAC,IAAA;AAAA,EAAA;AAAA,IACA,GAAA;AAAA,IACA,SAAA,EAAW,EAAA;AAAA,MACV,sJAAA;AAAA,MACA;AAAA,KACD;AAAA,IACC,GAAG;AAAA;AACL,CACA;AACD,QAAA,CAAS,WAAA,GAAc,UAAA;AAGvB,IAAM,SAAA,GAAkB,iBAGtB,CAAC,EAAE,WAAW,GAAG,KAAA,IAAS,GAAA,qBAC3B,GAAA;AAAA,EAAC,IAAA;AAAA,EAAA;AAAA,IACA,GAAA;AAAA,IACA,SAAA,EAAW,EAAA;AAAA,MACV,qJAAA;AAAA,MACA;AAAA,KACD;AAAA,IACC,GAAG;AAAA;AACL,CACA;AACD,SAAA,CAAU,WAAA,GAAc,WAAA;AAGxB,IAAM,SAAA,GAAkB,iBAGtB,CAAC,EAAE,WAAW,GAAG,KAAA,IAAS,GAAA,qBAC3B,GAAA;AAAA,EAAC,IAAA;AAAA,EAAA;AAAA,IACA,GAAA;AAAA,IACA,SAAA,EAAW,EAAA,CAAG,oEAAA,EAAsE,SAAS,CAAA;AAAA,IAC5F,GAAG;AAAA;AACL,CACA;AACD,SAAA,CAAU,WAAA,GAAc,WAAA;AAOxB,IAAM,YAAA,GAAqB,iBAGzB,CAAC,EAAE,WAAW,GAAG,KAAA,IAAS,GAAA,qBAC3B,GAAA;AAAA,EAAC,SAAA;AAAA,EAAA;AAAA,IACA,GAAA;AAAA,IACA,SAAA,EAAW,EAAA;AAAA,MACV,uEAAA;AAAA,MACA;AAAA,KACD;AAAA,IACC,GAAG;AAAA;AACL,CACA;AACD,YAAA,CAAa,WAAA,GAAc,cAAA","file":"table.js","sourcesContent":["import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/**\n * Merge class names with Tailwind CSS conflict resolution.\n * @param inputs - Class values (strings, arrays, objects) to merge\n * @returns A single merged class string with Tailwind conflicts resolved\n */\nexport function cn(...inputs: ClassValue[]) {\n\treturn twMerge(clsx(inputs));\n}\n","import * as React from \"react\";\nimport { cn } from \"../../lib/utils.js\";\n\n/** A responsive container + styled HTML table. */\nconst Table = React.forwardRef<HTMLTableElement, React.HTMLAttributes<HTMLTableElement>>(\n\t({ className, ...props }, ref) => (\n\t\t<div className=\"relative w-full overflow-auto\">\n\t\t\t<table\n\t\t\t\tref={ref}\n\t\t\t\tclassName={cn(\"w-full caption-bottom text-sm\", className)}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t</div>\n\t),\n);\nTable.displayName = \"Table\";\n\n/** `<thead>` wrapper with bottom border. */\nconst TableHeader = React.forwardRef<\n\tHTMLTableSectionElement,\n\tReact.HTMLAttributes<HTMLTableSectionElement>\n>(({ className, ...props }, ref) => (\n\t<thead ref={ref} className={cn(\"[&_tr]:border-b [&_tr]:border-b-foreground/[0.08]\", className)} {...props} />\n));\nTableHeader.displayName = \"TableHeader\";\n\n/** `<tbody>` wrapper removing bottom border on last row. */\nconst TableBody = React.forwardRef<\n\tHTMLTableSectionElement,\n\tReact.HTMLAttributes<HTMLTableSectionElement>\n>(({ className, ...props }, ref) => (\n\t<tbody ref={ref} className={cn(\"[&_tr:last-child]:border-0\", className)} {...props} />\n));\nTableBody.displayName = \"TableBody\";\n\n/** `<tfoot>` wrapper with muted background. */\nconst TableFooter = React.forwardRef<\n\tHTMLTableSectionElement,\n\tReact.HTMLAttributes<HTMLTableSectionElement>\n>(({ className, ...props }, ref) => (\n\t<tfoot\n\t\tref={ref}\n\t\tclassName={cn(\n\t\t\t\"border-t border-t-foreground/[0.08] bg-muted/50 font-medium [&>tr]:last:border-b-0\",\n\t\t\tclassName,\n\t\t)}\n\t\t{...props}\n\t/>\n));\nTableFooter.displayName = \"TableFooter\";\n\n/** `<tr>` with hover + selected states. */\nconst TableRow = React.forwardRef<\n\tHTMLTableRowElement,\n\tReact.HTMLAttributes<HTMLTableRowElement>\n>(({ className, ...props }, ref) => (\n\t<tr\n\t\tref={ref}\n\t\tclassName={cn(\n\t\t\t\"border-b border-b-foreground/[0.08] transition-all duration-[var(--duration-normal,200ms)] ease-out hover:bg-muted/50 data-[state=selected]:bg-muted\",\n\t\t\tclassName,\n\t\t)}\n\t\t{...props}\n\t/>\n));\nTableRow.displayName = \"TableRow\";\n\n/** `<th>` with left-aligned muted text. */\nconst TableHead = React.forwardRef<\n\tHTMLTableCellElement,\n\tReact.ThHTMLAttributes<HTMLTableCellElement>\n>(({ className, ...props }, ref) => (\n\t<th\n\t\tref={ref}\n\t\tclassName={cn(\n\t\t\t\"h-[var(--control-height-md,2.5rem)] px-[var(--space-4,1rem)] text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0\",\n\t\t\tclassName,\n\t\t)}\n\t\t{...props}\n\t/>\n));\nTableHead.displayName = \"TableHead\";\n\n/** `<td>` with consistent padding. */\nconst TableCell = React.forwardRef<\n\tHTMLTableCellElement,\n\tReact.TdHTMLAttributes<HTMLTableCellElement>\n>(({ className, ...props }, ref) => (\n\t<td\n\t\tref={ref}\n\t\tclassName={cn(\"p-[var(--space-4,1rem)] align-middle [&:has([role=checkbox])]:pr-0\", className)}\n\t\t{...props}\n\t/>\n));\nTableCell.displayName = \"TableCell\";\n\n/**\n * Visible `<caption>` rendered below the table. The parent `<Table>` sets\n * `caption-bottom`, so the caption is announced first by screen readers when\n * entering the table, then visually placed below the rows.\n */\nconst TableCaption = React.forwardRef<\n\tHTMLTableCaptionElement,\n\tReact.HTMLAttributes<HTMLTableCaptionElement>\n>(({ className, ...props }, ref) => (\n\t<caption\n\t\tref={ref}\n\t\tclassName={cn(\n\t\t\t\"caption-bottom mt-[var(--space-4,1rem)] text-sm text-muted-foreground\",\n\t\t\tclassName,\n\t\t)}\n\t\t{...props}\n\t/>\n));\nTableCaption.displayName = \"TableCaption\";\n\nexport {\n\tTable,\n\tTableHeader,\n\tTableBody,\n\tTableFooter,\n\tTableHead,\n\tTableRow,\n\tTableCell,\n\tTableCaption,\n};\n"]}
package/dist/tabs.d.ts ADDED
@@ -0,0 +1,13 @@
1
+ import * as React from 'react';
2
+ import * as TabsPrimitive from '@radix-ui/react-tabs';
3
+
4
+ /** Root container for a tabbed interface. */
5
+ declare const Tabs: React.ForwardRefExoticComponent<TabsPrimitive.TabsProps & React.RefAttributes<HTMLDivElement>>;
6
+ /** A horizontal list of tab triggers. */
7
+ declare const TabsList: React.ForwardRefExoticComponent<Omit<TabsPrimitive.TabsListProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
8
+ /** A clickable tab trigger that activates its associated content panel. */
9
+ declare const TabsTrigger: React.ForwardRefExoticComponent<Omit<TabsPrimitive.TabsTriggerProps & React.RefAttributes<HTMLButtonElement>, "ref"> & React.RefAttributes<HTMLButtonElement>>;
10
+ /** The content panel associated with a tab trigger. */
11
+ declare const TabsContent: React.ForwardRefExoticComponent<Omit<TabsPrimitive.TabsContentProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
12
+
13
+ export { Tabs, TabsContent, TabsList, TabsTrigger };
package/dist/tabs.js ADDED
@@ -0,0 +1,57 @@
1
+ "use client";
2
+ import * as React from 'react';
3
+ import * as TabsPrimitive from '@radix-ui/react-tabs';
4
+ import { clsx } from 'clsx';
5
+ import { twMerge } from 'tailwind-merge';
6
+ import { jsx } from 'react/jsx-runtime';
7
+
8
+ function cn(...inputs) {
9
+ return twMerge(clsx(inputs));
10
+ }
11
+ var Tabs = TabsPrimitive.Root;
12
+ var TabsList = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
13
+ TabsPrimitive.List,
14
+ {
15
+ ref,
16
+ className: cn(
17
+ "inline-flex h-[var(--control-height-md,2.5rem)] items-center justify-center rounded-md border border-foreground/[0.06] bg-muted p-[var(--space-1,0.25rem)] text-muted-foreground",
18
+ className
19
+ ),
20
+ ...props
21
+ }
22
+ ));
23
+ TabsList.displayName = "TabsList";
24
+ var TabsTrigger = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
25
+ TabsPrimitive.Trigger,
26
+ {
27
+ ref,
28
+ className: cn(
29
+ "inline-flex items-center justify-center whitespace-nowrap rounded-sm px-[var(--space-3,0.75rem)] py-1.5 text-sm font-medium",
30
+ "transition-all duration-[var(--duration-normal,200ms)] ease-out",
31
+ "ring-offset-background hover:text-foreground",
32
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
33
+ "disabled:pointer-events-none disabled:opacity-50",
34
+ "data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm",
35
+ className
36
+ ),
37
+ ...props
38
+ }
39
+ ));
40
+ TabsTrigger.displayName = "TabsTrigger";
41
+ var TabsContent = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
42
+ TabsPrimitive.Content,
43
+ {
44
+ ref,
45
+ className: cn(
46
+ "mt-[var(--space-2,0.5rem)] ring-offset-background",
47
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
48
+ className
49
+ ),
50
+ ...props
51
+ }
52
+ ));
53
+ TabsContent.displayName = "TabsContent";
54
+
55
+ export { Tabs, TabsContent, TabsList, TabsTrigger };
56
+ //# sourceMappingURL=tabs.js.map
57
+ //# sourceMappingURL=tabs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/utils.ts","../src/components/tabs/tabs.tsx"],"names":[],"mappings":";;;;;;AAQO,SAAS,MAAM,MAAA,EAAsB;AAC3C,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAC,CAAA;AAC5B;ACHA,IAAM,IAAA,GAAqB,aAAA,CAAA;AAG3B,IAAM,QAAA,GAAiB,iBAGrB,CAAC,EAAE,WAAW,GAAG,KAAA,IAAS,GAAA,qBAC3B,GAAA;AAAA,EAAe,aAAA,CAAA,IAAA;AAAA,EAAd;AAAA,IACA,GAAA;AAAA,IACA,SAAA,EAAW,EAAA;AAAA,MACV,kLAAA;AAAA,MACA;AAAA,KACD;AAAA,IACC,GAAG;AAAA;AACL,CACA;AACD,QAAA,CAAS,WAAA,GAAc,UAAA;AAGvB,IAAM,WAAA,GAAoB,iBAGxB,CAAC,EAAE,WAAW,GAAG,KAAA,IAAS,GAAA,qBAC3B,GAAA;AAAA,EAAe,aAAA,CAAA,OAAA;AAAA,EAAd;AAAA,IACA,GAAA;AAAA,IACA,SAAA,EAAW,EAAA;AAAA,MACV,6HAAA;AAAA,MACA,iEAAA;AAAA,MACA,8CAAA;AAAA,MACA,qGAAA;AAAA,MACA,kDAAA;AAAA,MACA,qGAAA;AAAA,MACA;AAAA,KACD;AAAA,IACC,GAAG;AAAA;AACL,CACA;AACD,WAAA,CAAY,WAAA,GAAc,aAAA;AAG1B,IAAM,WAAA,GAAoB,iBAGxB,CAAC,EAAE,WAAW,GAAG,KAAA,IAAS,GAAA,qBAC3B,GAAA;AAAA,EAAe,aAAA,CAAA,OAAA;AAAA,EAAd;AAAA,IACA,GAAA;AAAA,IACA,SAAA,EAAW,EAAA;AAAA,MACV,mDAAA;AAAA,MACA,qGAAA;AAAA,MACA;AAAA,KACD;AAAA,IACC,GAAG;AAAA;AACL,CACA;AACD,WAAA,CAAY,WAAA,GAAc,aAAA","file":"tabs.js","sourcesContent":["import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/**\n * Merge class names with Tailwind CSS conflict resolution.\n * @param inputs - Class values (strings, arrays, objects) to merge\n * @returns A single merged class string with Tailwind conflicts resolved\n */\nexport function cn(...inputs: ClassValue[]) {\n\treturn twMerge(clsx(inputs));\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport * as TabsPrimitive from \"@radix-ui/react-tabs\";\nimport { cn } from \"../../lib/utils.js\";\n\n/** Root container for a tabbed interface. */\nconst Tabs = TabsPrimitive.Root;\n\n/** A horizontal list of tab triggers. */\nconst TabsList = React.forwardRef<\n\tReact.ComponentRef<typeof TabsPrimitive.List>,\n\tReact.ComponentPropsWithoutRef<typeof TabsPrimitive.List>\n>(({ className, ...props }, ref) => (\n\t<TabsPrimitive.List\n\t\tref={ref}\n\t\tclassName={cn(\n\t\t\t\"inline-flex h-[var(--control-height-md,2.5rem)] items-center justify-center rounded-md border border-foreground/[0.06] bg-muted p-[var(--space-1,0.25rem)] text-muted-foreground\",\n\t\t\tclassName,\n\t\t)}\n\t\t{...props}\n\t/>\n));\nTabsList.displayName = \"TabsList\";\n\n/** A clickable tab trigger that activates its associated content panel. */\nconst TabsTrigger = React.forwardRef<\n\tReact.ComponentRef<typeof TabsPrimitive.Trigger>,\n\tReact.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>\n>(({ className, ...props }, ref) => (\n\t<TabsPrimitive.Trigger\n\t\tref={ref}\n\t\tclassName={cn(\n\t\t\t\"inline-flex items-center justify-center whitespace-nowrap rounded-sm px-[var(--space-3,0.75rem)] py-1.5 text-sm font-medium\",\n\t\t\t\"transition-all duration-[var(--duration-normal,200ms)] ease-out\",\n\t\t\t\"ring-offset-background hover:text-foreground\",\n\t\t\t\"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\",\n\t\t\t\"disabled:pointer-events-none disabled:opacity-50\",\n\t\t\t\"data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm\",\n\t\t\tclassName,\n\t\t)}\n\t\t{...props}\n\t/>\n));\nTabsTrigger.displayName = \"TabsTrigger\";\n\n/** The content panel associated with a tab trigger. */\nconst TabsContent = React.forwardRef<\n\tReact.ComponentRef<typeof TabsPrimitive.Content>,\n\tReact.ComponentPropsWithoutRef<typeof TabsPrimitive.Content>\n>(({ className, ...props }, ref) => (\n\t<TabsPrimitive.Content\n\t\tref={ref}\n\t\tclassName={cn(\n\t\t\t\"mt-[var(--space-2,0.5rem)] ring-offset-background\",\n\t\t\t\"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\",\n\t\t\tclassName,\n\t\t)}\n\t\t{...props}\n\t/>\n));\nTabsContent.displayName = \"TabsContent\";\n\nexport { Tabs, TabsList, TabsTrigger, TabsContent };\n"]}
@@ -0,0 +1,10 @@
1
+ import * as React from 'react';
2
+
3
+ /**
4
+ * A styled multi-line text input with smooth focus transitions and shadow effects.
5
+ * Extends the native HTML textarea element with Hex UI styling.
6
+ */
7
+ type TextareaProps = React.TextareaHTMLAttributes<HTMLTextAreaElement>;
8
+ declare const Textarea: React.ForwardRefExoticComponent<TextareaProps & React.RefAttributes<HTMLTextAreaElement>>;
9
+
10
+ export { Textarea, type TextareaProps };
@@ -0,0 +1,36 @@
1
+ import * as React from 'react';
2
+ import { clsx } from 'clsx';
3
+ import { twMerge } from 'tailwind-merge';
4
+ import { jsx } from 'react/jsx-runtime';
5
+
6
+ // src/primitives/textarea/textarea.tsx
7
+ function cn(...inputs) {
8
+ return twMerge(clsx(inputs));
9
+ }
10
+ var Textarea = React.forwardRef(
11
+ ({ className, ...props }, ref) => {
12
+ return /* @__PURE__ */ jsx(
13
+ "textarea",
14
+ {
15
+ className: cn(
16
+ "flex min-h-[80px] w-full rounded-md border border-input bg-background px-[var(--space-3,0.75rem)] py-[var(--space-2,0.5rem)] text-sm",
17
+ "transition-all duration-[var(--duration-normal,200ms)] ease-out",
18
+ "shadow-sm inset-ring-1 inset-ring-foreground/[0.06]",
19
+ "placeholder:text-muted-foreground",
20
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
21
+ "focus-visible:shadow-md focus-visible:border-ring/50",
22
+ "hover:border-ring/30 hover:shadow-md",
23
+ "disabled:cursor-not-allowed disabled:opacity-50",
24
+ className
25
+ ),
26
+ ref,
27
+ ...props
28
+ }
29
+ );
30
+ }
31
+ );
32
+ Textarea.displayName = "Textarea";
33
+
34
+ export { Textarea };
35
+ //# sourceMappingURL=textarea.js.map
36
+ //# sourceMappingURL=textarea.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/utils.ts","../src/primitives/textarea/textarea.tsx"],"names":[],"mappings":";;;;;;AAQO,SAAS,MAAM,MAAA,EAAsB;AAC3C,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAC,CAAA;AAC5B;ACDA,IAAM,QAAA,GAAiB,KAAA,CAAA,UAAA;AAAA,EACtB,CAAC,EAAE,SAAA,EAAW,GAAG,KAAA,IAAS,GAAA,KAAQ;AACjC,IAAA,uBACC,GAAA;AAAA,MAAC,UAAA;AAAA,MAAA;AAAA,QACA,SAAA,EAAW,EAAA;AAAA,UACV,sIAAA;AAAA,UACA,iEAAA;AAAA,UACA,qDAAA;AAAA,UACA,mCAAA;AAAA,UACA,qGAAA;AAAA,UACA,sDAAA;AAAA,UACA,sCAAA;AAAA,UACA,iDAAA;AAAA,UACA;AAAA,SACD;AAAA,QACA,GAAA;AAAA,QACC,GAAG;AAAA;AAAA,KACL;AAAA,EAEF;AACD;AACA,QAAA,CAAS,WAAA,GAAc,UAAA","file":"textarea.js","sourcesContent":["import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/**\n * Merge class names with Tailwind CSS conflict resolution.\n * @param inputs - Class values (strings, arrays, objects) to merge\n * @returns A single merged class string with Tailwind conflicts resolved\n */\nexport function cn(...inputs: ClassValue[]) {\n\treturn twMerge(clsx(inputs));\n}\n","import * as React from \"react\";\nimport { cn } from \"../../lib/utils.js\";\n\n/**\n * A styled multi-line text input with smooth focus transitions and shadow effects.\n * Extends the native HTML textarea element with Hex UI styling.\n */\nexport type TextareaProps = React.TextareaHTMLAttributes<HTMLTextAreaElement>;\n\nconst Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(\n\t({ className, ...props }, ref) => {\n\t\treturn (\n\t\t\t<textarea\n\t\t\t\tclassName={cn(\n\t\t\t\t\t\"flex min-h-[80px] w-full rounded-md border border-input bg-background px-[var(--space-3,0.75rem)] py-[var(--space-2,0.5rem)] text-sm\",\n\t\t\t\t\t\"transition-all duration-[var(--duration-normal,200ms)] ease-out\",\n\t\t\t\t\t\"shadow-sm inset-ring-1 inset-ring-foreground/[0.06]\",\n\t\t\t\t\t\"placeholder:text-muted-foreground\",\n\t\t\t\t\t\"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\",\n\t\t\t\t\t\"focus-visible:shadow-md focus-visible:border-ring/50\",\n\t\t\t\t\t\"hover:border-ring/30 hover:shadow-md\",\n\t\t\t\t\t\"disabled:cursor-not-allowed disabled:opacity-50\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\tref={ref}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t);\n\t},\n);\nTextarea.displayName = \"Textarea\";\n\nexport { Textarea };\n"]}