@7onic-ui/react 0.3.9 → 0.3.11

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 (170) hide show
  1. package/README.md +2 -2
  2. package/dist/chart.mjs +3 -9
  3. package/dist/chart.mjs.map +1 -1
  4. package/dist/chunk-2WIIXHOV.mjs +148 -0
  5. package/dist/chunk-2WIIXHOV.mjs.map +1 -0
  6. package/dist/chunk-53MIUPSY.mjs +13 -0
  7. package/dist/chunk-53MIUPSY.mjs.map +1 -0
  8. package/dist/chunk-BN5BEA3V.mjs +195 -0
  9. package/dist/chunk-BN5BEA3V.mjs.map +1 -0
  10. package/dist/chunk-C5D3VRNJ.mjs +504 -0
  11. package/dist/chunk-C5D3VRNJ.mjs.map +1 -0
  12. package/dist/chunk-COW3B62M.mjs +214 -0
  13. package/dist/chunk-COW3B62M.mjs.map +1 -0
  14. package/dist/chunk-CTH6SN5Y.mjs +114 -0
  15. package/dist/chunk-CTH6SN5Y.mjs.map +1 -0
  16. package/dist/chunk-D3NTQNDW.mjs +440 -0
  17. package/dist/chunk-D3NTQNDW.mjs.map +1 -0
  18. package/dist/chunk-DDRYEJBJ.mjs +164 -0
  19. package/dist/chunk-DDRYEJBJ.mjs.map +1 -0
  20. package/dist/chunk-DJAEXCRU.mjs +190 -0
  21. package/dist/chunk-DJAEXCRU.mjs.map +1 -0
  22. package/dist/chunk-DYYQOHQR.mjs +214 -0
  23. package/dist/chunk-DYYQOHQR.mjs.map +1 -0
  24. package/dist/chunk-EG2GTK65.mjs +443 -0
  25. package/dist/chunk-EG2GTK65.mjs.map +1 -0
  26. package/dist/chunk-FHUAH6AJ.mjs +93 -0
  27. package/dist/chunk-FHUAH6AJ.mjs.map +1 -0
  28. package/dist/chunk-GD4YE5AE.mjs +209 -0
  29. package/dist/chunk-GD4YE5AE.mjs.map +1 -0
  30. package/dist/chunk-HHX4GABH.mjs +129 -0
  31. package/dist/chunk-HHX4GABH.mjs.map +1 -0
  32. package/dist/chunk-HS2VRYSX.mjs +148 -0
  33. package/dist/chunk-HS2VRYSX.mjs.map +1 -0
  34. package/dist/chunk-IHHI3LIN.mjs +155 -0
  35. package/dist/chunk-IHHI3LIN.mjs.map +1 -0
  36. package/dist/chunk-IJ2FZ3L5.mjs +159 -0
  37. package/dist/chunk-IJ2FZ3L5.mjs.map +1 -0
  38. package/dist/chunk-IPCIC2BI.mjs +148 -0
  39. package/dist/chunk-IPCIC2BI.mjs.map +1 -0
  40. package/dist/chunk-JCJEVXER.mjs +170 -0
  41. package/dist/chunk-JCJEVXER.mjs.map +1 -0
  42. package/dist/chunk-KBPYAMGS.mjs +157 -0
  43. package/dist/chunk-KBPYAMGS.mjs.map +1 -0
  44. package/dist/chunk-L55ABE4H.mjs +283 -0
  45. package/dist/chunk-L55ABE4H.mjs.map +1 -0
  46. package/dist/chunk-LJJ6K4IU.mjs +318 -0
  47. package/dist/chunk-LJJ6K4IU.mjs.map +1 -0
  48. package/dist/chunk-ND6TUVP2.mjs +148 -0
  49. package/dist/chunk-ND6TUVP2.mjs.map +1 -0
  50. package/dist/chunk-NWFMJWGX.mjs +165 -0
  51. package/dist/chunk-NWFMJWGX.mjs.map +1 -0
  52. package/dist/chunk-PTAPPOKU.mjs +117 -0
  53. package/dist/chunk-PTAPPOKU.mjs.map +1 -0
  54. package/dist/chunk-PVTBM7V7.mjs +316 -0
  55. package/dist/chunk-PVTBM7V7.mjs.map +1 -0
  56. package/dist/chunk-Q5WVLK2L.mjs +77 -0
  57. package/dist/chunk-Q5WVLK2L.mjs.map +1 -0
  58. package/dist/chunk-R7FJEO4K.mjs +252 -0
  59. package/dist/chunk-R7FJEO4K.mjs.map +1 -0
  60. package/dist/chunk-RKSB2N5L.mjs +206 -0
  61. package/dist/chunk-RKSB2N5L.mjs.map +1 -0
  62. package/dist/chunk-S4DGVKBK.mjs +151 -0
  63. package/dist/chunk-S4DGVKBK.mjs.map +1 -0
  64. package/dist/chunk-S4T4PU7F.mjs +114 -0
  65. package/dist/chunk-S4T4PU7F.mjs.map +1 -0
  66. package/dist/chunk-SDDAGZWA.mjs +224 -0
  67. package/dist/chunk-SDDAGZWA.mjs.map +1 -0
  68. package/dist/chunk-SZPZOGPC.mjs +394 -0
  69. package/dist/chunk-SZPZOGPC.mjs.map +1 -0
  70. package/dist/chunk-T5A4APEL.mjs +140 -0
  71. package/dist/chunk-T5A4APEL.mjs.map +1 -0
  72. package/dist/chunk-V5UFWYFI.mjs +255 -0
  73. package/dist/chunk-V5UFWYFI.mjs.map +1 -0
  74. package/dist/chunk-W6YNEU53.mjs +175 -0
  75. package/dist/chunk-W6YNEU53.mjs.map +1 -0
  76. package/dist/chunk-XK52LYR4.mjs +182 -0
  77. package/dist/chunk-XK52LYR4.mjs.map +1 -0
  78. package/dist/chunk-YIAH6KHV.mjs +164 -0
  79. package/dist/chunk-YIAH6KHV.mjs.map +1 -0
  80. package/dist/chunk-YZ7HHFKA.mjs +375 -0
  81. package/dist/chunk-YZ7HHFKA.mjs.map +1 -0
  82. package/dist/chunk-ZDRUTJ4T.mjs +119 -0
  83. package/dist/chunk-ZDRUTJ4T.mjs.map +1 -0
  84. package/dist/components/accordion.mjs +19 -0
  85. package/dist/components/accordion.mjs.map +1 -0
  86. package/dist/components/alert.mjs +15 -0
  87. package/dist/components/alert.mjs.map +1 -0
  88. package/dist/components/avatar.mjs +23 -0
  89. package/dist/components/avatar.mjs.map +1 -0
  90. package/dist/components/badge.mjs +11 -0
  91. package/dist/components/badge.mjs.map +1 -0
  92. package/dist/components/breadcrumb.mjs +23 -0
  93. package/dist/components/breadcrumb.mjs.map +1 -0
  94. package/dist/components/button-group.mjs +11 -0
  95. package/dist/components/button-group.mjs.map +1 -0
  96. package/dist/components/button.mjs +12 -0
  97. package/dist/components/button.mjs.map +1 -0
  98. package/dist/components/card.mjs +25 -0
  99. package/dist/components/card.mjs.map +1 -0
  100. package/dist/components/chat-input.mjs +15 -0
  101. package/dist/components/chat-input.mjs.map +1 -0
  102. package/dist/components/chat-message.mjs +17 -0
  103. package/dist/components/chat-message.mjs.map +1 -0
  104. package/dist/components/checkbox.mjs +12 -0
  105. package/dist/components/checkbox.mjs.map +1 -0
  106. package/dist/components/divider.mjs +11 -0
  107. package/dist/components/divider.mjs.map +1 -0
  108. package/dist/components/drawer.mjs +33 -0
  109. package/dist/components/drawer.mjs.map +1 -0
  110. package/dist/components/dropdown.mjs +35 -0
  111. package/dist/components/dropdown.mjs.map +1 -0
  112. package/dist/components/field.mjs +19 -0
  113. package/dist/components/field.mjs.map +1 -0
  114. package/dist/components/icon-button.mjs +12 -0
  115. package/dist/components/icon-button.mjs.map +1 -0
  116. package/dist/components/input.mjs +12 -0
  117. package/dist/components/input.mjs.map +1 -0
  118. package/dist/components/metric-card.mjs +23 -0
  119. package/dist/components/metric-card.mjs.map +1 -0
  120. package/dist/components/modal.mjs +57 -0
  121. package/dist/components/modal.mjs.map +1 -0
  122. package/dist/components/navigation-menu.mjs +27 -0
  123. package/dist/components/navigation-menu.mjs.map +1 -0
  124. package/dist/components/pagination.mjs +33 -0
  125. package/dist/components/pagination.mjs.map +1 -0
  126. package/dist/components/popover.mjs +23 -0
  127. package/dist/components/popover.mjs.map +1 -0
  128. package/dist/components/progress.mjs +11 -0
  129. package/dist/components/progress.mjs.map +1 -0
  130. package/dist/components/quick-reply.mjs +15 -0
  131. package/dist/components/quick-reply.mjs.map +1 -0
  132. package/dist/components/radio-group.mjs +16 -0
  133. package/dist/components/radio-group.mjs.map +1 -0
  134. package/dist/components/segmented.mjs +15 -0
  135. package/dist/components/segmented.mjs.map +1 -0
  136. package/dist/components/select.mjs +24 -0
  137. package/dist/components/select.mjs.map +1 -0
  138. package/dist/components/skeleton.mjs +11 -0
  139. package/dist/components/skeleton.mjs.map +1 -0
  140. package/dist/components/slider.mjs +12 -0
  141. package/dist/components/slider.mjs.map +1 -0
  142. package/dist/components/spinner.mjs +11 -0
  143. package/dist/components/spinner.mjs.map +1 -0
  144. package/dist/components/switch.mjs +12 -0
  145. package/dist/components/switch.mjs.map +1 -0
  146. package/dist/components/table.mjs +23 -0
  147. package/dist/components/table.mjs.map +1 -0
  148. package/dist/components/tabs.mjs +19 -0
  149. package/dist/components/tabs.mjs.map +1 -0
  150. package/dist/components/textarea.mjs +12 -0
  151. package/dist/components/textarea.mjs.map +1 -0
  152. package/dist/components/toast.mjs +13 -0
  153. package/dist/components/toast.mjs.map +1 -0
  154. package/dist/components/toggle-group.mjs +15 -0
  155. package/dist/components/toggle-group.mjs.map +1 -0
  156. package/dist/components/toggle.mjs +11 -0
  157. package/dist/components/toggle.mjs.map +1 -0
  158. package/dist/components/tooltip.mjs +21 -0
  159. package/dist/components/tooltip.mjs.map +1 -0
  160. package/dist/components/typing-indicator.mjs +11 -0
  161. package/dist/components/typing-indicator.mjs.map +1 -0
  162. package/dist/index.d.ts +11 -2
  163. package/dist/index.js +95 -21
  164. package/dist/index.js.map +1 -1
  165. package/dist/index.mjs +296 -7536
  166. package/dist/index.mjs.map +1 -1
  167. package/llms.txt +50 -32
  168. package/package.json +14 -14
  169. package/dist/chart.d.mts +0 -147
  170. package/dist/index.d.mts +0 -1535
@@ -0,0 +1,155 @@
1
+ "use client";
2
+ import {
3
+ useFieldContext,
4
+ useFieldControl
5
+ } from "./chunk-T5A4APEL.mjs";
6
+ import {
7
+ cn
8
+ } from "./chunk-53MIUPSY.mjs";
9
+
10
+ // src/components/ui/textarea.tsx
11
+ import * as React from "react";
12
+ import { cva } from "class-variance-authority";
13
+ var textareaVariants = cva(
14
+ [
15
+ "flex w-full bg-background text-foreground placeholder:text-foreground/30",
16
+ "border transition-colors duration-micro outline-transparent",
17
+ "focus:[outline:2px_solid_transparent]",
18
+ "disabled:cursor-not-allowed disabled:opacity-50 disabled:bg-background-muted"
19
+ ].join(" "),
20
+ {
21
+ variants: {
22
+ variant: {
23
+ default: "border-border hover:border-border-strong",
24
+ filled: "border-transparent bg-background-muted"
25
+ },
26
+ focusRing: {
27
+ true: "",
28
+ false: ""
29
+ },
30
+ size: {
31
+ compact: "px-3 py-2 text-md",
32
+ // 12px padding / 14px font - compact spaces
33
+ default: "px-4 py-3 text-base"
34
+ // 16px padding / 16px font - standard
35
+ },
36
+ radius: {
37
+ none: "rounded-none",
38
+ sm: "rounded-sm",
39
+ base: "rounded",
40
+ default: "rounded-md",
41
+ lg: "rounded-lg",
42
+ xl: "rounded-xl",
43
+ "2xl": "rounded-2xl",
44
+ "3xl": "rounded-3xl",
45
+ full: "rounded-3xl"
46
+ // rounded-full looks unnatural on textarea, using 3xl instead
47
+ },
48
+ resize: {
49
+ none: "resize-none",
50
+ vertical: "resize-y",
51
+ horizontal: "resize-x",
52
+ both: "resize"
53
+ },
54
+ state: {
55
+ default: "",
56
+ error: "border-error hover:border-error focus:border-error shadow-[0_0_0_2px_var(--color-focus-ring-error)]"
57
+ }
58
+ },
59
+ compoundVariants: [
60
+ // focusRing: true → show custom focus ring
61
+ { focusRing: true, className: "focus-visible:shadow-[0_0_0_2px_var(--color-focus-ring)]" },
62
+ // focusRing: false → keep same state as hover
63
+ { variant: "default", focusRing: false, className: "focus:border-border-strong" },
64
+ // filled + error
65
+ {
66
+ variant: "filled",
67
+ state: "error",
68
+ className: "border-transparent hover:border-transparent focus:border-transparent bg-[var(--color-error-bg)] hover:bg-[var(--color-error-bg)] focus:bg-[var(--color-error-bg)] shadow-none"
69
+ }
70
+ ],
71
+ defaultVariants: {
72
+ variant: "default",
73
+ size: "default",
74
+ radius: "default",
75
+ resize: "vertical",
76
+ state: "default",
77
+ focusRing: false
78
+ }
79
+ }
80
+ );
81
+ var Textarea = React.forwardRef(
82
+ ({ className, variant, size, radius, resize, state, error, focusRing, id, rows = 4, onPointerDown, onFocus, onBlur, ...props }, ref) => {
83
+ const fieldContext = useFieldContext();
84
+ const resolvedError = error ?? fieldContext?.error;
85
+ const resolvedState = resolvedError ? "error" : state;
86
+ const textareaId = id ?? fieldContext?.id;
87
+ useFieldControl("single", Boolean(fieldContext) && !id);
88
+ const isDisabled = props.disabled ?? fieldContext?.disabled;
89
+ const pointerRef = React.useRef(false);
90
+ const windowBlurredRef = React.useRef(false);
91
+ const [keyboardFocus, setKeyboardFocus] = React.useState(false);
92
+ React.useEffect(() => {
93
+ const onBlur2 = () => {
94
+ windowBlurredRef.current = true;
95
+ };
96
+ const onFocus2 = () => {
97
+ requestAnimationFrame(() => {
98
+ windowBlurredRef.current = false;
99
+ });
100
+ };
101
+ window.addEventListener("blur", onBlur2);
102
+ window.addEventListener("focus", onFocus2);
103
+ return () => {
104
+ window.removeEventListener("blur", onBlur2);
105
+ window.removeEventListener("focus", onFocus2);
106
+ };
107
+ }, []);
108
+ const handlePointerDown = React.useCallback((e) => {
109
+ pointerRef.current = true;
110
+ onPointerDown?.(e);
111
+ }, [onPointerDown]);
112
+ const handleFocus = React.useCallback((e) => {
113
+ if (!pointerRef.current && !focusRing && !windowBlurredRef.current) {
114
+ setKeyboardFocus(true);
115
+ }
116
+ pointerRef.current = false;
117
+ onFocus?.(e);
118
+ }, [focusRing, onFocus]);
119
+ const handleBlur = React.useCallback((e) => {
120
+ setKeyboardFocus(false);
121
+ pointerRef.current = false;
122
+ onBlur?.(e);
123
+ }, [onBlur]);
124
+ const ariaDescribedBy = fieldContext ? [
125
+ resolvedError ? `${fieldContext.id}-error` : null
126
+ ].filter(Boolean).join(" ") || void 0 : void 0;
127
+ return /* @__PURE__ */ React.createElement(
128
+ "textarea",
129
+ {
130
+ id: textareaId,
131
+ rows,
132
+ className: cn(
133
+ textareaVariants({ variant, size, radius, resize, state: resolvedState, focusRing }),
134
+ keyboardFocus && "shadow-[0_0_0_2px_var(--color-focus-ring)]",
135
+ className
136
+ ),
137
+ "aria-invalid": resolvedError || void 0,
138
+ "aria-describedby": ariaDescribedBy,
139
+ disabled: isDisabled,
140
+ ref,
141
+ onPointerDown: handlePointerDown,
142
+ onFocus: handleFocus,
143
+ onBlur: handleBlur,
144
+ ...props
145
+ }
146
+ );
147
+ }
148
+ );
149
+ Textarea.displayName = "Textarea";
150
+
151
+ export {
152
+ textareaVariants,
153
+ Textarea
154
+ };
155
+ //# sourceMappingURL=chunk-IHHI3LIN.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/ui/textarea.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from '@/lib/utils'\nimport { useFieldContext, useFieldControl } from './field'\n\nconst textareaVariants = cva(\n [\n 'flex w-full bg-background text-foreground placeholder:text-foreground/30',\n 'border transition-colors duration-micro outline-transparent',\n 'focus:[outline:2px_solid_transparent]',\n 'disabled:cursor-not-allowed disabled:opacity-50 disabled:bg-background-muted',\n ].join(' '),\n {\n variants: {\n variant: {\n default: 'border-border hover:border-border-strong',\n filled: 'border-transparent bg-background-muted',\n },\n focusRing: {\n true: '',\n false: '',\n },\n size: {\n compact: 'px-3 py-2 text-md', // 12px padding / 14px font - compact spaces\n default: 'px-4 py-3 text-base', // 16px padding / 16px font - standard\n },\n radius: {\n none: 'rounded-none',\n sm: 'rounded-sm',\n base: 'rounded',\n default: 'rounded-md',\n lg: 'rounded-lg',\n xl: 'rounded-xl',\n '2xl': 'rounded-2xl',\n '3xl': 'rounded-3xl',\n full: 'rounded-3xl', // rounded-full looks unnatural on textarea, using 3xl instead\n },\n resize: {\n none: 'resize-none',\n vertical: 'resize-y',\n horizontal: 'resize-x',\n both: 'resize',\n },\n state: {\n default: '',\n error: 'border-error hover:border-error focus:border-error shadow-[0_0_0_2px_var(--color-focus-ring-error)]',\n },\n },\n compoundVariants: [\n // focusRing: true → show custom focus ring\n { focusRing: true, className: 'focus-visible:shadow-[0_0_0_2px_var(--color-focus-ring)]' },\n // focusRing: false → keep same state as hover\n { variant: 'default', focusRing: false, className: 'focus:border-border-strong' },\n // filled + error\n {\n variant: 'filled',\n state: 'error',\n className: 'border-transparent hover:border-transparent focus:border-transparent bg-[var(--color-error-bg)] hover:bg-[var(--color-error-bg)] focus:bg-[var(--color-error-bg)] shadow-none',\n },\n ],\n defaultVariants: {\n variant: 'default',\n size: 'default',\n radius: 'default',\n resize: 'vertical',\n state: 'default',\n focusRing: false,\n },\n }\n)\n\nexport interface TextareaProps\n extends Omit<React.TextareaHTMLAttributes<HTMLTextAreaElement>, 'size'>,\n VariantProps<typeof textareaVariants> {\n error?: boolean\n focusRing?: boolean\n}\n\nconst Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(\n ({ className, variant, size, radius, resize, state, error, focusRing, id, rows = 4, onPointerDown, onFocus, onBlur, ...props }, ref) => {\n const fieldContext = useFieldContext()\n const resolvedError = error ?? fieldContext?.error\n const resolvedState = resolvedError ? 'error' : state\n const textareaId = id ?? fieldContext?.id\n useFieldControl('single', Boolean(fieldContext) && !id)\n const isDisabled = props.disabled ?? fieldContext?.disabled\n\n // Keyboard focus detection (when focusRing: false, auto-show ring on Tab navigation)\n const pointerRef = React.useRef(false)\n const windowBlurredRef = React.useRef(false)\n const [keyboardFocus, setKeyboardFocus] = React.useState(false)\n\n // Track window blur/focus to distinguish Tab navigation from window re-activation\n React.useEffect(() => {\n const onBlur = () => { windowBlurredRef.current = true }\n const onFocus = () => { requestAnimationFrame(() => { windowBlurredRef.current = false }) }\n window.addEventListener('blur', onBlur)\n window.addEventListener('focus', onFocus)\n return () => { window.removeEventListener('blur', onBlur); window.removeEventListener('focus', onFocus) }\n }, [])\n\n const handlePointerDown = React.useCallback((e: React.PointerEvent<HTMLTextAreaElement>) => {\n pointerRef.current = true\n onPointerDown?.(e)\n }, [onPointerDown])\n\n const handleFocus = React.useCallback((e: React.FocusEvent<HTMLTextAreaElement>) => {\n if (!pointerRef.current && !focusRing && !windowBlurredRef.current) {\n setKeyboardFocus(true)\n }\n pointerRef.current = false\n onFocus?.(e)\n }, [focusRing, onFocus])\n\n const handleBlur = React.useCallback((e: React.FocusEvent<HTMLTextAreaElement>) => {\n setKeyboardFocus(false)\n pointerRef.current = false\n onBlur?.(e)\n }, [onBlur])\n\n // Build aria-describedby from context\n const ariaDescribedBy = fieldContext\n ? [\n resolvedError ? `${fieldContext.id}-error` : null,\n ]\n .filter(Boolean)\n .join(' ') || undefined\n : undefined\n\n return (\n <textarea\n id={textareaId}\n rows={rows}\n className={cn(\n textareaVariants({ variant, size, radius, resize, state: resolvedState, focusRing }),\n keyboardFocus && 'shadow-[0_0_0_2px_var(--color-focus-ring)]',\n className\n )}\n aria-invalid={resolvedError || undefined}\n aria-describedby={ariaDescribedBy}\n disabled={isDisabled}\n ref={ref}\n onPointerDown={handlePointerDown}\n onFocus={handleFocus}\n onBlur={handleBlur}\n {...props}\n />\n )\n }\n)\nTextarea.displayName = 'Textarea'\n\nexport { Textarea, textareaVariants }\n"],"mappings":"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","names":["onBlur","onFocus"]}
@@ -0,0 +1,159 @@
1
+ "use client";
2
+ import {
3
+ useFieldContext,
4
+ useFieldControl
5
+ } from "./chunk-T5A4APEL.mjs";
6
+ import {
7
+ cn
8
+ } from "./chunk-53MIUPSY.mjs";
9
+
10
+ // src/components/ui/slider.tsx
11
+ import * as React from "react";
12
+ import * as SliderPrimitive from "@radix-ui/react-slider";
13
+ import { cva } from "class-variance-authority";
14
+ var sliderVariants = cva(
15
+ "relative flex touch-none select-none",
16
+ {
17
+ variants: {
18
+ size: {
19
+ sm: "",
20
+ default: "",
21
+ lg: ""
22
+ }
23
+ },
24
+ defaultVariants: {
25
+ size: "default"
26
+ }
27
+ }
28
+ );
29
+ var trackSizes = {
30
+ sm: "h-1 data-[orientation=vertical]:h-auto data-[orientation=vertical]:w-1",
31
+ default: "h-1.5 data-[orientation=vertical]:h-auto data-[orientation=vertical]:w-1.5",
32
+ lg: "h-2 data-[orientation=vertical]:h-auto data-[orientation=vertical]:w-2"
33
+ };
34
+ var thumbSizes = {
35
+ sm: "w-[var(--component-slider-thumb-sm)] h-[var(--component-slider-thumb-sm)]",
36
+ default: "w-[var(--component-slider-thumb-default)] h-[var(--component-slider-thumb-default)]",
37
+ lg: "w-[var(--component-slider-thumb-lg)] h-[var(--component-slider-thumb-lg)]"
38
+ };
39
+ var contentSizes = {
40
+ sm: "text-xs",
41
+ default: "text-sm",
42
+ lg: "text-base"
43
+ };
44
+ var sliderColorMap = {
45
+ default: {
46
+ range: "bg-foreground",
47
+ thumb: "bg-background border-foreground",
48
+ thumbHover: "hover:shadow-[0_0_0_4px_color-mix(in_srgb,var(--color-text)_16%,transparent)] hover:border-foreground",
49
+ thumbActive: "active:shadow-[0_0_0_6px_color-mix(in_srgb,var(--color-text)_16%,transparent)]"
50
+ },
51
+ primary: {
52
+ range: "bg-primary",
53
+ thumb: "bg-primary-foreground border-primary",
54
+ thumbHover: "hover:shadow-primary-glow hover:border-primary-hover",
55
+ thumbActive: "active:shadow-[0_0_0_6px_color-mix(in_srgb,var(--color-primary)_16%,transparent)]"
56
+ }
57
+ };
58
+ var Slider = React.forwardRef(({ className, size, color = "default", value, defaultValue, onValueChange, showTooltip = "never", formatLabel, startContent, endContent, orientation, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, ...props }, ref) => {
59
+ const resolvedSize = size || "default";
60
+ const fieldContext = useFieldContext();
61
+ useFieldControl("labelled", Boolean(fieldContext));
62
+ const thumbLabelledBy = ariaLabelledBy ?? (!ariaLabel && fieldContext?.hasLabel ? fieldContext.labelId : void 0);
63
+ const thumbCount = value?.length ?? defaultValue?.length ?? 1;
64
+ const hasTooltip = showTooltip !== "never";
65
+ const hasWrapper = !!(startContent || endContent);
66
+ const isVertical = orientation === "vertical";
67
+ const [internalValue, setInternalValue] = React.useState(
68
+ () => value ?? defaultValue ?? Array(thumbCount).fill(props.min ?? 0)
69
+ );
70
+ const displayValues = value ?? internalValue;
71
+ const handleValueChange = React.useCallback((newValue) => {
72
+ setInternalValue(newValue);
73
+ onValueChange?.(newValue);
74
+ }, [onValueChange]);
75
+ const sliderRoot = /* @__PURE__ */ React.createElement(
76
+ SliderPrimitive.Root,
77
+ {
78
+ ref,
79
+ className: cn(
80
+ sliderVariants({ size }),
81
+ isVertical ? "h-full w-auto flex-col items-center" : "w-full items-center",
82
+ hasWrapper && (isVertical ? "flex-1 min-h-0" : "flex-1 min-w-0"),
83
+ !hasWrapper && className
84
+ ),
85
+ value,
86
+ defaultValue,
87
+ onValueChange: hasTooltip ? handleValueChange : onValueChange,
88
+ orientation,
89
+ ...props
90
+ },
91
+ /* @__PURE__ */ React.createElement(
92
+ SliderPrimitive.Track,
93
+ {
94
+ className: cn(
95
+ "relative grow overflow-hidden rounded-full bg-border",
96
+ isVertical ? "h-full" : "w-full",
97
+ trackSizes[resolvedSize]
98
+ )
99
+ },
100
+ /* @__PURE__ */ React.createElement(
101
+ SliderPrimitive.Range,
102
+ {
103
+ className: cn(
104
+ "absolute rounded-full",
105
+ sliderColorMap[color].range,
106
+ isVertical ? "w-full transition-[top,bottom] duration-fast ease-out" : "h-full transition-[left,right] duration-fast ease-out"
107
+ )
108
+ }
109
+ )
110
+ ),
111
+ Array.from({ length: thumbCount }).map((_, i) => /* @__PURE__ */ React.createElement(
112
+ SliderPrimitive.Thumb,
113
+ {
114
+ key: i,
115
+ "aria-label": ariaLabel,
116
+ "aria-labelledby": thumbLabelledBy,
117
+ className: cn(
118
+ "group/thumb block rounded-full border-2 shadow-sm",
119
+ sliderColorMap[color].thumb,
120
+ isVertical ? "transition-[top,box-shadow,border-color] duration-fast ease-out" : "transition-[left,box-shadow,border-color] duration-fast ease-out",
121
+ sliderColorMap[color].thumbHover,
122
+ sliderColorMap[color].thumbActive,
123
+ "focus-visible:focus-ring",
124
+ "disabled:pointer-events-none disabled:opacity-50",
125
+ thumbSizes[resolvedSize]
126
+ )
127
+ },
128
+ hasTooltip && /* @__PURE__ */ React.createElement(
129
+ "div",
130
+ {
131
+ className: cn(
132
+ "absolute pointer-events-none",
133
+ "transition-all duration-fast ease-out",
134
+ isVertical ? "right-full top-1/2 -translate-y-1/2 mr-2 origin-right" : "bottom-full left-1/2 -translate-x-1/2 mb-2 origin-bottom",
135
+ showTooltip === "always" ? "opacity-100 scale-100" : [
136
+ "opacity-0 scale-95",
137
+ "group-hover/thumb:opacity-100 group-hover/thumb:scale-100",
138
+ "group-active/thumb:opacity-100 group-active/thumb:scale-100",
139
+ "group-focus-visible/thumb:opacity-100 group-focus-visible/thumb:scale-100"
140
+ ]
141
+ )
142
+ },
143
+ /* @__PURE__ */ React.createElement("div", { className: "relative bg-foreground text-background text-xs font-semibold font-mono tabular-nums px-2.5 py-1 rounded-md shadow-lg whitespace-nowrap" }, formatLabel ? formatLabel(displayValues[i]) : displayValues[i], isVertical ? /* @__PURE__ */ React.createElement("div", { className: "absolute left-full top-1/2 -translate-y-1/2 border-4 border-transparent border-l-foreground" }) : /* @__PURE__ */ React.createElement("div", { className: "absolute top-full left-1/2 -translate-x-1/2 border-4 border-transparent border-t-foreground" }))
144
+ )
145
+ ))
146
+ );
147
+ if (!hasWrapper) return sliderRoot;
148
+ return /* @__PURE__ */ React.createElement("div", { className: cn(
149
+ isVertical ? "inline-flex flex-col items-center gap-2 h-full" : "flex items-center gap-3",
150
+ className
151
+ ) }, startContent && /* @__PURE__ */ React.createElement("span", { className: cn("shrink-0 text-text-muted select-none", contentSizes[resolvedSize], props.disabled && "opacity-50") }, startContent), sliderRoot, endContent && /* @__PURE__ */ React.createElement("span", { className: cn("shrink-0 text-text-muted select-none", contentSizes[resolvedSize], props.disabled && "opacity-50") }, endContent));
152
+ });
153
+ Slider.displayName = "Slider";
154
+
155
+ export {
156
+ sliderVariants,
157
+ Slider
158
+ };
159
+ //# sourceMappingURL=chunk-IJ2FZ3L5.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/ui/slider.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport * as SliderPrimitive from '@radix-ui/react-slider'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from '@/lib/utils'\nimport { useFieldContext, useFieldControl } from './field'\n\n// Slider root variants\nconst sliderVariants = cva(\n 'relative flex touch-none select-none',\n {\n variants: {\n size: {\n sm: '',\n default: '',\n lg: '',\n },\n },\n defaultVariants: {\n size: 'default',\n },\n }\n)\n\n// Track sizes per orientation\nconst trackSizes = {\n sm: 'h-1 data-[orientation=vertical]:h-auto data-[orientation=vertical]:w-1',\n default: 'h-1.5 data-[orientation=vertical]:h-auto data-[orientation=vertical]:w-1.5',\n lg: 'h-2 data-[orientation=vertical]:h-auto data-[orientation=vertical]:w-2',\n}\n\n// Thumb sizes\nconst thumbSizes = {\n sm: 'w-[var(--component-slider-thumb-sm)] h-[var(--component-slider-thumb-sm)]',\n default: 'w-[var(--component-slider-thumb-default)] h-[var(--component-slider-thumb-default)]',\n lg: 'w-[var(--component-slider-thumb-lg)] h-[var(--component-slider-thumb-lg)]',\n}\n\n// Content font sizes (for startContent / endContent)\nconst contentSizes = {\n sm: 'text-xs',\n default: 'text-sm',\n lg: 'text-base',\n}\n\n// Color maps for range and thumb\nconst sliderColorMap = {\n default: {\n range: 'bg-foreground',\n thumb: 'bg-background border-foreground',\n thumbHover: 'hover:shadow-[0_0_0_4px_color-mix(in_srgb,var(--color-text)_16%,transparent)] hover:border-foreground',\n thumbActive: 'active:shadow-[0_0_0_6px_color-mix(in_srgb,var(--color-text)_16%,transparent)]',\n },\n primary: {\n range: 'bg-primary',\n thumb: 'bg-primary-foreground border-primary',\n thumbHover: 'hover:shadow-primary-glow hover:border-primary-hover',\n thumbActive: 'active:shadow-[0_0_0_6px_color-mix(in_srgb,var(--color-primary)_16%,transparent)]',\n },\n} as const\n\nexport type SliderColor = keyof typeof sliderColorMap\n\nexport interface SliderProps\n extends React.ComponentPropsWithoutRef<typeof SliderPrimitive.Root>,\n VariantProps<typeof sliderVariants> {\n /** Track and thumb color */\n color?: SliderColor\n /** Tooltip display mode: auto (hover/drag), always, never */\n showTooltip?: 'auto' | 'always' | 'never'\n /** Custom formatter for tooltip value */\n formatLabel?: (value: number) => string\n /** Content to display before the slider (icon, label, etc.) */\n startContent?: React.ReactNode\n /** Content to display after the slider */\n endContent?: React.ReactNode\n}\n\nconst Slider = React.forwardRef<\n React.ElementRef<typeof SliderPrimitive.Root>,\n SliderProps\n>(({ className, size, color = 'default', value, defaultValue, onValueChange, showTooltip = 'never', formatLabel, startContent, endContent, orientation, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, ...props }, ref) => {\n const resolvedSize = size || 'default'\n // The thumbs carry role=\"slider\", so the accessible name goes on them, not on the\n // Root. Inside a Field the FieldLabel names the slider unless a name is given.\n const fieldContext = useFieldContext()\n useFieldControl('labelled', Boolean(fieldContext))\n const thumbLabelledBy = ariaLabelledBy ?? (!ariaLabel && fieldContext?.hasLabel ? fieldContext.labelId : undefined)\n const thumbCount = value?.length ?? defaultValue?.length ?? 1\n const hasTooltip = showTooltip !== 'never'\n const hasWrapper = !!(startContent || endContent)\n const isVertical = orientation === 'vertical'\n\n // Track value internally for tooltip display\n const [internalValue, setInternalValue] = React.useState(\n () => value ?? defaultValue ?? Array(thumbCount).fill(props.min ?? 0)\n )\n const displayValues = value ?? internalValue\n\n const handleValueChange = React.useCallback((newValue: number[]) => {\n setInternalValue(newValue)\n onValueChange?.(newValue)\n }, [onValueChange])\n\n const sliderRoot = (\n <SliderPrimitive.Root\n ref={ref}\n className={cn(\n sliderVariants({ size }),\n isVertical\n ? 'h-full w-auto flex-col items-center'\n : 'w-full items-center',\n hasWrapper && (isVertical ? 'flex-1 min-h-0' : 'flex-1 min-w-0'),\n !hasWrapper && className\n )}\n value={value}\n defaultValue={defaultValue}\n onValueChange={hasTooltip ? handleValueChange : onValueChange}\n orientation={orientation}\n {...props}\n >\n <SliderPrimitive.Track\n className={cn(\n 'relative grow overflow-hidden rounded-full bg-border',\n isVertical ? 'h-full' : 'w-full',\n trackSizes[resolvedSize]\n )}\n >\n <SliderPrimitive.Range\n className={cn(\n 'absolute rounded-full', sliderColorMap[color].range,\n isVertical\n ? 'w-full transition-[top,bottom] duration-fast ease-out'\n : 'h-full transition-[left,right] duration-fast ease-out'\n )}\n />\n </SliderPrimitive.Track>\n {Array.from({ length: thumbCount }).map((_, i) => (\n <SliderPrimitive.Thumb\n key={i}\n aria-label={ariaLabel}\n aria-labelledby={thumbLabelledBy}\n className={cn(\n 'group/thumb block rounded-full border-2 shadow-sm', sliderColorMap[color].thumb,\n isVertical\n ? 'transition-[top,box-shadow,border-color] duration-fast ease-out'\n : 'transition-[left,box-shadow,border-color] duration-fast ease-out',\n sliderColorMap[color].thumbHover,\n sliderColorMap[color].thumbActive,\n 'focus-visible:focus-ring',\n 'disabled:pointer-events-none disabled:opacity-50',\n thumbSizes[resolvedSize]\n )}\n >\n {hasTooltip && (\n <div\n className={cn(\n 'absolute pointer-events-none',\n 'transition-all duration-fast ease-out',\n isVertical\n ? 'right-full top-1/2 -translate-y-1/2 mr-2 origin-right'\n : 'bottom-full left-1/2 -translate-x-1/2 mb-2 origin-bottom',\n showTooltip === 'always'\n ? 'opacity-100 scale-100'\n : [\n 'opacity-0 scale-95',\n 'group-hover/thumb:opacity-100 group-hover/thumb:scale-100',\n 'group-active/thumb:opacity-100 group-active/thumb:scale-100',\n 'group-focus-visible/thumb:opacity-100 group-focus-visible/thumb:scale-100',\n ]\n )}\n >\n <div className=\"relative bg-foreground text-background text-xs font-semibold font-mono tabular-nums px-2.5 py-1 rounded-md shadow-lg whitespace-nowrap\">\n {formatLabel ? formatLabel(displayValues[i]) : displayValues[i]}\n {/* Arrow */}\n {isVertical ? (\n <div className=\"absolute left-full top-1/2 -translate-y-1/2 border-4 border-transparent border-l-foreground\" />\n ) : (\n <div className=\"absolute top-full left-1/2 -translate-x-1/2 border-4 border-transparent border-t-foreground\" />\n )}\n </div>\n </div>\n )}\n </SliderPrimitive.Thumb>\n ))}\n </SliderPrimitive.Root>\n )\n\n if (!hasWrapper) return sliderRoot\n\n return (\n <div className={cn(\n isVertical ? 'inline-flex flex-col items-center gap-2 h-full' : 'flex items-center gap-3',\n className\n )}>\n {startContent && (\n <span className={cn('shrink-0 text-text-muted select-none', contentSizes[resolvedSize], props.disabled && 'opacity-50')}>\n {startContent}\n </span>\n )}\n {sliderRoot}\n {endContent && (\n <span className={cn('shrink-0 text-text-muted select-none', contentSizes[resolvedSize], props.disabled && 'opacity-50')}>\n {endContent}\n </span>\n )}\n </div>\n )\n})\nSlider.displayName = 'Slider'\n\nexport { Slider, sliderVariants }\n"],"mappings":";;;;;;;;;;AAEA,YAAY,WAAW;AACvB,YAAY,qBAAqB;AACjC,SAAS,WAA8B;AAKvC,IAAM,iBAAiB;AAAA,EACrB;AAAA,EACA;AAAA,IACE,UAAU;AAAA,MACR,MAAM;AAAA,QACJ,IAAI;AAAA,QACJ,SAAS;AAAA,QACT,IAAI;AAAA,MACN;AAAA,IACF;AAAA,IACA,iBAAiB;AAAA,MACf,MAAM;AAAA,IACR;AAAA,EACF;AACF;AAGA,IAAM,aAAa;AAAA,EACjB,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,IAAI;AACN;AAGA,IAAM,aAAa;AAAA,EACjB,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,IAAI;AACN;AAGA,IAAM,eAAe;AAAA,EACnB,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,IAAI;AACN;AAGA,IAAM,iBAAiB;AAAA,EACrB,SAAS;AAAA,IACP,OAAO;AAAA,IACP,OAAO;AAAA,IACP,YAAY;AAAA,IACZ,aAAa;AAAA,EACf;AAAA,EACA,SAAS;AAAA,IACP,OAAO;AAAA,IACP,OAAO;AAAA,IACP,YAAY;AAAA,IACZ,aAAa;AAAA,EACf;AACF;AAmBA,IAAM,SAAe,iBAGnB,CAAC,EAAE,WAAW,MAAM,QAAQ,WAAW,OAAO,cAAc,eAAe,cAAc,SAAS,aAAa,cAAc,YAAY,aAAa,cAAc,WAAW,mBAAmB,gBAAgB,GAAG,MAAM,GAAG,QAAQ;AACtO,QAAM,eAAe,QAAQ;AAG7B,QAAM,eAAe,gBAAgB;AACrC,kBAAgB,YAAY,QAAQ,YAAY,CAAC;AACjD,QAAM,kBAAkB,mBAAmB,CAAC,aAAa,cAAc,WAAW,aAAa,UAAU;AACzG,QAAM,aAAa,OAAO,UAAU,cAAc,UAAU;AAC5D,QAAM,aAAa,gBAAgB;AACnC,QAAM,aAAa,CAAC,EAAE,gBAAgB;AACtC,QAAM,aAAa,gBAAgB;AAGnC,QAAM,CAAC,eAAe,gBAAgB,IAAU;AAAA,IAC9C,MAAM,SAAS,gBAAgB,MAAM,UAAU,EAAE,KAAK,MAAM,OAAO,CAAC;AAAA,EACtE;AACA,QAAM,gBAAgB,SAAS;AAE/B,QAAM,oBAA0B,kBAAY,CAAC,aAAuB;AAClE,qBAAiB,QAAQ;AACzB,oBAAgB,QAAQ;AAAA,EAC1B,GAAG,CAAC,aAAa,CAAC;AAElB,QAAM,aACJ;AAAA,IAAiB;AAAA,IAAhB;AAAA,MACC;AAAA,MACA,WAAW;AAAA,QACT,eAAe,EAAE,KAAK,CAAC;AAAA,QACvB,aACI,wCACA;AAAA,QACJ,eAAe,aAAa,mBAAmB;AAAA,QAC/C,CAAC,cAAc;AAAA,MACjB;AAAA,MACA;AAAA,MACA;AAAA,MACA,eAAe,aAAa,oBAAoB;AAAA,MAChD;AAAA,MACC,GAAG;AAAA;AAAA,IAEJ;AAAA,MAAiB;AAAA,MAAhB;AAAA,QACC,WAAW;AAAA,UACT;AAAA,UACA,aAAa,WAAW;AAAA,UACxB,WAAW,YAAY;AAAA,QACzB;AAAA;AAAA,MAEA;AAAA,QAAiB;AAAA,QAAhB;AAAA,UACC,WAAW;AAAA,YACT;AAAA,YAAyB,eAAe,KAAK,EAAE;AAAA,YAC/C,aACI,0DACA;AAAA,UACN;AAAA;AAAA,MACF;AAAA,IACF;AAAA,IACC,MAAM,KAAK,EAAE,QAAQ,WAAW,CAAC,EAAE,IAAI,CAAC,GAAG,MAC1C;AAAA,MAAiB;AAAA,MAAhB;AAAA,QACC,KAAK;AAAA,QACL,cAAY;AAAA,QACZ,mBAAiB;AAAA,QACjB,WAAW;AAAA,UACT;AAAA,UAAqD,eAAe,KAAK,EAAE;AAAA,UAC3E,aACI,oEACA;AAAA,UACJ,eAAe,KAAK,EAAE;AAAA,UACtB,eAAe,KAAK,EAAE;AAAA,UACtB;AAAA,UACA;AAAA,UACA,WAAW,YAAY;AAAA,QACzB;AAAA;AAAA,MAEC,cACC;AAAA,QAAC;AAAA;AAAA,UACC,WAAW;AAAA,YACT;AAAA,YACA;AAAA,YACA,aACI,0DACA;AAAA,YACJ,gBAAgB,WACZ,0BACA;AAAA,cACE;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,YACF;AAAA,UACN;AAAA;AAAA,QAEA,oCAAC,SAAI,WAAU,4IACZ,cAAc,YAAY,cAAc,CAAC,CAAC,IAAI,cAAc,CAAC,GAE7D,aACC,oCAAC,SAAI,WAAU,+FAA8F,IAE7G,oCAAC,SAAI,WAAU,+FAA8F,CAEjH;AAAA,MACF;AAAA,IAEJ,CACD;AAAA,EACH;AAGF,MAAI,CAAC,WAAY,QAAO;AAExB,SACE,oCAAC,SAAI,WAAW;AAAA,IACd,aAAa,mDAAmD;AAAA,IAChE;AAAA,EACF,KACG,gBACC,oCAAC,UAAK,WAAW,GAAG,wCAAwC,aAAa,YAAY,GAAG,MAAM,YAAY,YAAY,KACnH,YACH,GAED,YACA,cACC,oCAAC,UAAK,WAAW,GAAG,wCAAwC,aAAa,YAAY,GAAG,MAAM,YAAY,YAAY,KACnH,UACH,CAEJ;AAEJ,CAAC;AACD,OAAO,cAAc;","names":[]}
@@ -0,0 +1,148 @@
1
+ "use client";
2
+ import {
3
+ useButtonGroup
4
+ } from "./chunk-Q5WVLK2L.mjs";
5
+ import {
6
+ cn
7
+ } from "./chunk-53MIUPSY.mjs";
8
+
9
+ // src/components/ui/button.tsx
10
+ import * as React from "react";
11
+ import { Slot } from "@radix-ui/react-slot";
12
+ import { cva } from "class-variance-authority";
13
+ var solidColorMap = {
14
+ default: "bg-foreground text-background hover:bg-foreground/90 active:bg-foreground/80",
15
+ primary: "bg-primary text-primary-foreground hover:bg-primary-hover active:bg-primary-active",
16
+ secondary: "bg-secondary text-secondary-foreground hover:bg-secondary-hover active:bg-secondary-active",
17
+ destructive: "bg-error text-error-foreground hover:bg-error-hover active:bg-error-active"
18
+ };
19
+ var buttonVariants = cva(
20
+ "inline-flex items-center justify-center whitespace-nowrap transition-all duration-micro focus-visible:focus-ring disabled:pointer-events-none disabled:opacity-50",
21
+ {
22
+ variants: {
23
+ variant: {
24
+ solid: "font-semibold",
25
+ outline: "border border-border bg-background text-foreground hover:bg-background-muted font-normal",
26
+ ghost: "text-foreground hover:bg-background-muted font-normal",
27
+ link: "text-text-link underline-offset-4 hover:underline font-normal"
28
+ },
29
+ size: {
30
+ xs: "h-7 px-2.5 text-xs gap-1",
31
+ // 28px height, 10px paddingX, 12px font
32
+ sm: "h-8 px-3 text-sm gap-2",
33
+ // 32px height, 12px paddingX, 13px font
34
+ md: "h-9 px-3.5 text-md gap-2",
35
+ // 36px height, 14px paddingX, 14px font
36
+ default: "h-10 px-4 text-md gap-2",
37
+ // 40px height, 16px paddingX, 14px font
38
+ lg: "h-12 px-6 text-base gap-2",
39
+ // 48px height, 24px paddingX, 16px font
40
+ icon: "h-10 w-10"
41
+ },
42
+ radius: {
43
+ none: "rounded-none",
44
+ // 0px - primitive.borderRadius.none
45
+ sm: "rounded-sm",
46
+ // 2px - primitive.borderRadius.sm
47
+ base: "rounded",
48
+ // 4px - primitive.borderRadius.base
49
+ default: "rounded-md",
50
+ // 6px - primitive.borderRadius.md (Figma button default)
51
+ lg: "rounded-lg",
52
+ // 8px - primitive.borderRadius.lg
53
+ xl: "rounded-xl",
54
+ // 12px - primitive.borderRadius.xl
55
+ "2xl": "rounded-2xl",
56
+ // 16px - primitive.borderRadius.2xl
57
+ "3xl": "rounded-3xl",
58
+ // 24px - primitive.borderRadius.3xl
59
+ full: "rounded-full"
60
+ // 9999px - primitive.borderRadius.full
61
+ },
62
+ fullWidth: {
63
+ true: "w-full",
64
+ false: "w-auto"
65
+ }
66
+ },
67
+ defaultVariants: {
68
+ variant: "solid",
69
+ size: "default",
70
+ radius: "default",
71
+ fullWidth: false
72
+ }
73
+ }
74
+ );
75
+ var Button = React.forwardRef(
76
+ ({
77
+ className,
78
+ variant: variantProp,
79
+ color: colorProp,
80
+ size: sizeProp,
81
+ radius: radiusProp,
82
+ fullWidth,
83
+ asChild = false,
84
+ loading = false,
85
+ disabled: disabledProp,
86
+ leftIcon,
87
+ rightIcon,
88
+ selected = false,
89
+ fontWeight: fontWeightProp,
90
+ pressEffect,
91
+ children,
92
+ ...props
93
+ }, ref) => {
94
+ const Comp = asChild ? Slot : "button";
95
+ const groupContext = useButtonGroup();
96
+ const variant = variantProp ?? groupContext?.variant ?? "solid";
97
+ const color = colorProp ?? "default";
98
+ const size = sizeProp ?? groupContext?.size;
99
+ const radius = radiusProp ?? groupContext?.radius;
100
+ const disabled = disabledProp ?? groupContext?.disabled;
101
+ const fontWeight = fontWeightProp ?? groupContext?.fontWeight;
102
+ const fontWeightClass = fontWeight === "normal" ? "font-normal" : fontWeight === "semibold" ? "font-semibold" : "";
103
+ const iconSizeClass = {
104
+ xs: "icon-xs",
105
+ // 14px
106
+ sm: "icon-xs",
107
+ // 14px
108
+ md: "icon-sm",
109
+ // 16px
110
+ default: "icon-sm",
111
+ // 16px
112
+ lg: "icon-sm",
113
+ // 16px
114
+ icon: "icon-md"
115
+ // icon-only → 20px
116
+ }[size || "default"];
117
+ const selectedStyles = selected ? variant === "outline" ? "bg-background-muted" : variant === "ghost" ? "font-semibold" : "" : "";
118
+ return /* @__PURE__ */ React.createElement(
119
+ Comp,
120
+ {
121
+ className: cn(buttonVariants({ variant, size, radius, fullWidth }), variant === "solid" && solidColorMap[color], pressEffect !== false && "active:scale-pressed", fontWeightClass, selectedStyles, className),
122
+ ref,
123
+ disabled: disabled || loading,
124
+ "aria-busy": loading || void 0,
125
+ "aria-pressed": selected || void 0,
126
+ ...props
127
+ },
128
+ loading ? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(
129
+ "svg",
130
+ {
131
+ className: cn(iconSizeClass, "animate-spin"),
132
+ fill: "none",
133
+ viewBox: "0 0 24 24",
134
+ "aria-hidden": "true"
135
+ },
136
+ /* @__PURE__ */ React.createElement("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
137
+ /* @__PURE__ */ React.createElement("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" })
138
+ ), /* @__PURE__ */ React.createElement("span", null, children)) : /* @__PURE__ */ React.createElement(React.Fragment, null, leftIcon && /* @__PURE__ */ React.createElement("span", { className: cn(iconSizeClass, "[&>svg]:w-full [&>svg]:h-full"), "aria-hidden": "true" }, leftIcon), children, rightIcon && /* @__PURE__ */ React.createElement("span", { className: cn(iconSizeClass, "[&>svg]:w-full [&>svg]:h-full"), "aria-hidden": "true" }, rightIcon))
139
+ );
140
+ }
141
+ );
142
+ Button.displayName = "Button";
143
+
144
+ export {
145
+ buttonVariants,
146
+ Button
147
+ };
148
+ //# sourceMappingURL=chunk-IPCIC2BI.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/ui/button.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { Slot } from '@radix-ui/react-slot'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from '@/lib/utils'\nimport { useButtonGroup } from './button-group'\n\n// Solid color maps (applied when variant=\"solid\")\nconst solidColorMap = {\n default: 'bg-foreground text-background hover:bg-foreground/90 active:bg-foreground/80',\n primary: 'bg-primary text-primary-foreground hover:bg-primary-hover active:bg-primary-active',\n secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary-hover active:bg-secondary-active',\n destructive: 'bg-error text-error-foreground hover:bg-error-hover active:bg-error-active',\n} as const\n\nexport type ButtonColor = keyof typeof solidColorMap\n\nconst buttonVariants = cva(\n 'inline-flex items-center justify-center whitespace-nowrap transition-all duration-micro focus-visible:focus-ring disabled:pointer-events-none disabled:opacity-50',\n {\n variants: {\n variant: {\n solid: 'font-semibold',\n outline: 'border border-border bg-background text-foreground hover:bg-background-muted font-normal',\n ghost: 'text-foreground hover:bg-background-muted font-normal',\n link: 'text-text-link underline-offset-4 hover:underline font-normal',\n },\n size: {\n xs: 'h-7 px-2.5 text-xs gap-1', // 28px height, 10px paddingX, 12px font\n sm: 'h-8 px-3 text-sm gap-2', // 32px height, 12px paddingX, 13px font\n md: 'h-9 px-3.5 text-md gap-2', // 36px height, 14px paddingX, 14px font\n default: 'h-10 px-4 text-md gap-2', // 40px height, 16px paddingX, 14px font\n lg: 'h-12 px-6 text-base gap-2', // 48px height, 24px paddingX, 16px font\n icon: 'h-10 w-10',\n },\n radius: {\n none: 'rounded-none', // 0px - primitive.borderRadius.none\n sm: 'rounded-sm', // 2px - primitive.borderRadius.sm\n base: 'rounded', // 4px - primitive.borderRadius.base\n default: 'rounded-md', // 6px - primitive.borderRadius.md (Figma button default)\n lg: 'rounded-lg', // 8px - primitive.borderRadius.lg\n xl: 'rounded-xl', // 12px - primitive.borderRadius.xl\n '2xl': 'rounded-2xl', // 16px - primitive.borderRadius.2xl\n '3xl': 'rounded-3xl', // 24px - primitive.borderRadius.3xl\n full: 'rounded-full', // 9999px - primitive.borderRadius.full\n },\n fullWidth: {\n true: 'w-full',\n false: 'w-auto',\n },\n },\n defaultVariants: {\n variant: 'solid',\n size: 'default',\n radius: 'default',\n fullWidth: false,\n },\n }\n)\n\nexport interface ButtonProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement>,\n VariantProps<typeof buttonVariants> {\n /** Solid variant color */\n color?: ButtonColor\n asChild?: boolean\n loading?: boolean\n leftIcon?: React.ReactNode\n rightIcon?: React.ReactNode\n selected?: boolean\n fontWeight?: 'normal' | 'semibold'\n pressEffect?: boolean\n}\n\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n ({\n className,\n variant: variantProp,\n color: colorProp,\n size: sizeProp,\n radius: radiusProp,\n fullWidth,\n asChild = false,\n loading = false,\n disabled: disabledProp,\n leftIcon,\n rightIcon,\n selected = false,\n fontWeight: fontWeightProp,\n pressEffect,\n children,\n ...props\n }, ref) => {\n const Comp = asChild ? Slot : 'button'\n const groupContext = useButtonGroup()\n\n // Use context values as fallback, individual props take precedence\n const variant = variantProp ?? groupContext?.variant ?? 'solid'\n const color = colorProp ?? 'default'\n const size = sizeProp ?? groupContext?.size\n const radius = radiusProp ?? groupContext?.radius\n const disabled = disabledProp ?? groupContext?.disabled\n\n // Priority: direct prop > ButtonGroup context > variant default (no class)\n const fontWeight = fontWeightProp ?? groupContext?.fontWeight\n\n // FontWeight class (overrides variant default)\n const fontWeightClass = fontWeight === 'normal' ? 'font-normal' : fontWeight === 'semibold' ? 'font-semibold' : ''\n\n // Icon size for button with text (5-step scale)\n // xs~sm: 14px, md~default~lg: 16px\n const iconSizeClass = {\n xs: 'icon-xs', // 14px\n sm: 'icon-xs', // 14px\n md: 'icon-sm', // 16px\n default: 'icon-sm', // 16px\n lg: 'icon-sm', // 16px\n icon: 'icon-md', // icon-only → 20px\n }[size || 'default']\n\n // Selected styles by variant (used in ButtonGroup)\n const selectedStyles = selected ? (\n variant === 'outline' ? 'bg-background-muted' :\n variant === 'ghost' ? 'font-semibold' : ''\n ) : ''\n\n return (\n <Comp\n className={cn(buttonVariants({ variant, size, radius, fullWidth }), variant === 'solid' && solidColorMap[color], pressEffect !== false && 'active:scale-pressed', fontWeightClass, selectedStyles, className)}\n ref={ref}\n disabled={disabled || loading}\n aria-busy={loading || undefined}\n aria-pressed={selected || undefined}\n {...props}\n >\n {loading ? (\n <>\n <svg\n className={cn(iconSizeClass, 'animate-spin')}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n aria-hidden=\"true\"\n >\n <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"4\" />\n <path className=\"opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\" />\n </svg>\n <span>{children}</span>\n </>\n ) : (\n <>\n {leftIcon && <span className={cn(iconSizeClass, '[&>svg]:w-full [&>svg]:h-full')} aria-hidden=\"true\">{leftIcon}</span>}\n {children}\n {rightIcon && <span className={cn(iconSizeClass, '[&>svg]:w-full [&>svg]:h-full')} aria-hidden=\"true\">{rightIcon}</span>}\n </>\n )}\n </Comp>\n )\n }\n)\nButton.displayName = 'Button'\n\nexport { Button, buttonVariants }\n"],"mappings":"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","names":[]}