@7onic-ui/react 0.3.10 → 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 (54) hide show
  1. package/README.md +2 -2
  2. package/dist/{chunk-GRCJ35DX.mjs → chunk-2WIIXHOV.mjs} +7 -3
  3. package/dist/chunk-2WIIXHOV.mjs.map +1 -0
  4. package/dist/{chunk-DTLNWOTR.mjs → chunk-C5D3VRNJ.mjs} +29 -7
  5. package/dist/chunk-C5D3VRNJ.mjs.map +1 -0
  6. package/dist/{chunk-T546XBQG.mjs → chunk-EG2GTK65.mjs} +3 -3
  7. package/dist/{chunk-T546XBQG.mjs.map → chunk-EG2GTK65.mjs.map} +1 -1
  8. package/dist/{chunk-UWTT5AE6.mjs → chunk-HS2VRYSX.mjs} +7 -4
  9. package/dist/chunk-HS2VRYSX.mjs.map +1 -0
  10. package/dist/{chunk-N4K2BDGM.mjs → chunk-IHHI3LIN.mjs} +5 -3
  11. package/dist/chunk-IHHI3LIN.mjs.map +1 -0
  12. package/dist/{chunk-VUPGBB5X.mjs → chunk-IJ2FZ3L5.mjs} +11 -2
  13. package/dist/chunk-IJ2FZ3L5.mjs.map +1 -0
  14. package/dist/{chunk-IY3R2VGB.mjs → chunk-L55ABE4H.mjs} +14 -3
  15. package/dist/chunk-L55ABE4H.mjs.map +1 -0
  16. package/dist/{chunk-DRVHHEAY.mjs → chunk-ND6TUVP2.mjs} +7 -4
  17. package/dist/chunk-ND6TUVP2.mjs.map +1 -0
  18. package/dist/{chunk-234NAXGV.mjs → chunk-R7FJEO4K.mjs} +1 -1
  19. package/dist/chunk-R7FJEO4K.mjs.map +1 -0
  20. package/dist/{chunk-WWSN5YME.mjs → chunk-SDDAGZWA.mjs} +5 -3
  21. package/dist/chunk-SDDAGZWA.mjs.map +1 -0
  22. package/dist/{chunk-Z6JWWCNL.mjs → chunk-T5A4APEL.mjs} +35 -3
  23. package/dist/chunk-T5A4APEL.mjs.map +1 -0
  24. package/dist/{chunk-MRUVGHGP.mjs → chunk-YZ7HHFKA.mjs} +7 -7
  25. package/dist/chunk-YZ7HHFKA.mjs.map +1 -0
  26. package/dist/components/chat-input.mjs +1 -1
  27. package/dist/components/chat-message.mjs +1 -1
  28. package/dist/components/checkbox.mjs +2 -2
  29. package/dist/components/field.mjs +5 -3
  30. package/dist/components/input.mjs +2 -2
  31. package/dist/components/navigation-menu.mjs +1 -1
  32. package/dist/components/pagination.mjs +1 -1
  33. package/dist/components/radio-group.mjs +2 -2
  34. package/dist/components/select.mjs +2 -1
  35. package/dist/components/slider.mjs +2 -1
  36. package/dist/components/switch.mjs +2 -2
  37. package/dist/components/textarea.mjs +2 -2
  38. package/dist/index.d.ts +11 -2
  39. package/dist/index.js +95 -21
  40. package/dist/index.js.map +1 -1
  41. package/dist/index.mjs +12 -12
  42. package/llms.txt +27 -9
  43. package/package.json +11 -12
  44. package/dist/chunk-234NAXGV.mjs.map +0 -1
  45. package/dist/chunk-DRVHHEAY.mjs.map +0 -1
  46. package/dist/chunk-DTLNWOTR.mjs.map +0 -1
  47. package/dist/chunk-GRCJ35DX.mjs.map +0 -1
  48. package/dist/chunk-IY3R2VGB.mjs.map +0 -1
  49. package/dist/chunk-MRUVGHGP.mjs.map +0 -1
  50. package/dist/chunk-N4K2BDGM.mjs.map +0 -1
  51. package/dist/chunk-UWTT5AE6.mjs.map +0 -1
  52. package/dist/chunk-VUPGBB5X.mjs.map +0 -1
  53. package/dist/chunk-WWSN5YME.mjs.map +0 -1
  54. package/dist/chunk-Z6JWWCNL.mjs.map +0 -1
package/dist/index.mjs CHANGED
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  Switch,
4
4
  switchVariants
5
- } from "./chunk-DRVHHEAY.mjs";
5
+ } from "./chunk-ND6TUVP2.mjs";
6
6
  import {
7
7
  Table,
8
8
  TableBody,
@@ -24,7 +24,7 @@ import {
24
24
  import {
25
25
  Textarea,
26
26
  textareaVariants
27
- } from "./chunk-N4K2BDGM.mjs";
27
+ } from "./chunk-IHHI3LIN.mjs";
28
28
  import {
29
29
  Toaster,
30
30
  toast,
@@ -64,7 +64,7 @@ import {
64
64
  RadioGroupItem,
65
65
  radioGroupVariants,
66
66
  radioItemVariants
67
- } from "./chunk-GRCJ35DX.mjs";
67
+ } from "./chunk-2WIIXHOV.mjs";
68
68
  import {
69
69
  Segmented,
70
70
  SegmentedItem,
@@ -80,7 +80,7 @@ import {
80
80
  SelectSeparator,
81
81
  SelectTrigger,
82
82
  SelectValue
83
- } from "./chunk-IY3R2VGB.mjs";
83
+ } from "./chunk-L55ABE4H.mjs";
84
84
  import {
85
85
  Skeleton,
86
86
  skeletonVariants
@@ -88,7 +88,7 @@ import {
88
88
  import {
89
89
  Slider,
90
90
  sliderVariants
91
- } from "./chunk-VUPGBB5X.mjs";
91
+ } from "./chunk-IJ2FZ3L5.mjs";
92
92
  import {
93
93
  Spinner,
94
94
  spinnerVariants
@@ -100,7 +100,7 @@ import {
100
100
  import {
101
101
  Input,
102
102
  inputVariants
103
- } from "./chunk-WWSN5YME.mjs";
103
+ } from "./chunk-SDDAGZWA.mjs";
104
104
  import {
105
105
  MetricCard,
106
106
  MetricCardDescription,
@@ -149,7 +149,7 @@ import {
149
149
  NavigationMenuTrigger,
150
150
  NavigationMenuViewport,
151
151
  navigationMenuSizeMap
152
- } from "./chunk-DTLNWOTR.mjs";
152
+ } from "./chunk-C5D3VRNJ.mjs";
153
153
  import {
154
154
  Pagination,
155
155
  PaginationContent,
@@ -164,7 +164,7 @@ import {
164
164
  paginationItemVariants,
165
165
  paginationSizeMap,
166
166
  usePagination
167
- } from "./chunk-T546XBQG.mjs";
167
+ } from "./chunk-EG2GTK65.mjs";
168
168
  import {
169
169
  Popover,
170
170
  PopoverAnchor,
@@ -195,13 +195,13 @@ import {
195
195
  ChatInputField,
196
196
  ChatInputSubmit,
197
197
  chatInputVariants
198
- } from "./chunk-MRUVGHGP.mjs";
198
+ } from "./chunk-YZ7HHFKA.mjs";
199
199
  import {
200
200
  ChatMessage,
201
201
  ChatMessageAvatar,
202
202
  ChatMessageContent,
203
203
  ChatMessageFooter
204
- } from "./chunk-234NAXGV.mjs";
204
+ } from "./chunk-R7FJEO4K.mjs";
205
205
  import {
206
206
  TypingIndicator,
207
207
  typingIndicatorVariants
@@ -209,14 +209,14 @@ import {
209
209
  import {
210
210
  Checkbox,
211
211
  checkboxVariants
212
- } from "./chunk-UWTT5AE6.mjs";
212
+ } from "./chunk-HS2VRYSX.mjs";
213
213
  import {
214
214
  Field,
215
215
  FieldCharCount,
216
216
  FieldError,
217
217
  FieldLabel,
218
218
  useFieldContext
219
- } from "./chunk-Z6JWWCNL.mjs";
219
+ } from "./chunk-T5A4APEL.mjs";
220
220
  import {
221
221
  Divider,
222
222
  dividerVariants
package/llms.txt CHANGED
@@ -725,10 +725,12 @@ import { Segmented, SegmentedItem } from '@7onic-ui/react'
725
725
  ```tsx
726
726
  import { Slider } from '@7onic-ui/react'
727
727
 
728
- <Slider defaultValue={[50]} showTooltip="auto" />
729
- <Slider defaultValue={[20, 80]} color="primary" />
728
+ <Slider defaultValue={[50]} showTooltip="auto" aria-label="Volume" />
729
+ <Slider defaultValue={[20, 80]} color="primary" aria-label="Price range" />
730
730
  ```
731
731
 
732
+ **Accessible name:** `aria-label` / `aria-labelledby` go on the thumb (the element with `role="slider"`). Inside a `Field`, the `FieldLabel` names the slider automatically.
733
+
732
734
  | Prop | Type | Default | Description |
733
735
  |---|---|---|---|
734
736
  | size | `'sm' \| 'default' \| 'lg'` | `'default'` | Track/thumb size |
@@ -1378,7 +1380,7 @@ import { Breadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbP
1378
1380
  ### Pagination
1379
1381
 
1380
1382
  ```tsx
1381
- import { Pagination, PaginationContent, PaginationItems, PaginationNext, PaginationPrevious } from '@7onic-ui/react'
1383
+ import { Pagination, PaginationContent, PaginationItem, PaginationItems, PaginationNext, PaginationPrevious } from '@7onic-ui/react'
1382
1384
 
1383
1385
  {/* Quick mode — withControls (default: true), withEdges (default: false) */}
1384
1386
  <Pagination total={10} defaultValue={1} />
@@ -1388,9 +1390,13 @@ import { Pagination, PaginationContent, PaginationItems, PaginationNext, Paginat
1388
1390
  {/* Compound mode (custom layout) */}
1389
1391
  <Pagination total={20} value={page} onChange={setPage}>
1390
1392
  <PaginationContent>
1391
- <PaginationPrevious />
1393
+ <PaginationItem>
1394
+ <PaginationPrevious />
1395
+ </PaginationItem>
1392
1396
  <PaginationItems />
1393
- <PaginationNext />
1397
+ <PaginationItem>
1398
+ <PaginationNext />
1399
+ </PaginationItem>
1394
1400
  </PaginationContent>
1395
1401
  </Pagination>
1396
1402
  ```
@@ -2060,10 +2066,22 @@ import { Field, FieldCharCount, FieldError, FieldLabel, Input, Textarea } from '
2060
2066
  </Field>
2061
2067
  ```
2062
2068
 
2063
- **Field context auto-connects** to Input, Textarea, Select, Checkbox, RadioGroup:
2064
- - Passes `error` state
2065
- - Passes `disabled` state
2066
- - Auto-generates matching `id` / `htmlFor` / `aria-describedby`
2069
+ **Field context auto-connects** to Input, Textarea, Select, Checkbox, Switch, RadioGroup, Slider:
2070
+ - Passes `disabled` state (and `error` to Input / Textarea)
2071
+ - One control (Input, Textarea, SelectTrigger, a Checkbox / Switch without its own `label`): `FieldLabel` targets it via matching `id` / `htmlFor`; Input / Textarea also get `aria-describedby` for FieldError / FieldCharCount
2072
+ - A group (several Checkbox / Switch each with their own `label`): every item keeps a unique id, and the Field becomes `role="group"` named by `FieldLabel` — clicking an item label toggles that item
2073
+ - RadioGroup and Slider: named by `FieldLabel` via `aria-labelledby`
2074
+
2075
+ ```tsx
2076
+ <Field>
2077
+ <FieldLabel>Notifications</FieldLabel>
2078
+ <div className="flex flex-col gap-2">
2079
+ <Checkbox defaultChecked label="Email" />
2080
+ <Checkbox label="Push" />
2081
+ <Checkbox label="SMS" />
2082
+ </div>
2083
+ </Field>
2084
+ ```
2067
2085
 
2068
2086
  ---
2069
2087
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@7onic-ui/react",
3
- "version": "0.3.10",
3
+ "version": "0.3.11",
4
4
  "private": false,
5
5
  "sideEffects": [
6
6
  "*.css"
@@ -40,8 +40,8 @@
40
40
  "build:clean": "rm -rf .next && next build",
41
41
  "build:lib": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\" && tsup",
42
42
  "start": "next start",
43
- "lint": "eslint . --ext .ts,.tsx",
44
- "lint:fix": "eslint . --ext .ts,.tsx --fix",
43
+ "lint": "eslint .",
44
+ "lint:fix": "eslint . --fix",
45
45
  "format": "prettier --write \"src/**/*.{ts,tsx}\"",
46
46
  "typecheck": "tsc --noEmit",
47
47
  "sync-tokens": "tsx scripts/run-sync.ts",
@@ -49,6 +49,7 @@
49
49
  "build:7onic": "node scripts/build-7onic-cli.js",
50
50
  "generate:registry": "tsx scripts/generate-registry.ts",
51
51
  "verify:registry": "tsx scripts/generate-registry.ts && git diff --exit-code cli/src/registry/index.ts",
52
+ "verify:page-intl": "tsx scripts/verify-page-intl.ts",
52
53
  "verify:components": "tsx scripts/verify-components.ts",
53
54
  "verify:framework-compat": "tsx scripts/verify-framework-compat.ts",
54
55
  "verify:llms-examples": "tsx scripts/verify-llms-examples.ts",
@@ -97,22 +98,20 @@
97
98
  "devDependencies": {
98
99
  "@7onic-ui/tokens": "file:./tokens",
99
100
  "@clack/prompts": "^1.2.0",
100
- "@playwright/test": "^1.59.1",
101
+ "@eslint/js": "^9.39.5",
102
+ "@playwright/test": "^1.64.1",
101
103
  "@types/node": "^20.14.0",
102
104
  "@types/react": "^19.0.0",
103
105
  "@types/react-dom": "^19.0.0",
104
- "@typescript-eslint/eslint-plugin": "^7.0.0",
105
- "@typescript-eslint/parser": "^7.0.0",
106
106
  "autoprefixer": "^10.4.19",
107
107
  "cmdk": "^1.1.1",
108
- "eslint": "^8.57.0",
109
- "eslint-config-next": "^15.5.28",
110
- "eslint-config-prettier": "^9.1.0",
111
- "eslint-plugin-react": "^7.34.0",
112
- "eslint-plugin-react-hooks": "^4.6.0",
108
+ "eslint": "^9.39.5",
109
+ "eslint-config-next": "^16.4.3",
110
+ "eslint-config-prettier": "^10.1.8",
111
+ "eslint-plugin-react": "^7.37.5",
113
112
  "jsonc-parser": "^3.3.1",
114
113
  "lucide-react": "^0.400.0",
115
- "next": "^15.5.28",
114
+ "next": "^16.4.3",
116
115
  "next-intl": "^4.14.9",
117
116
  "picocolors": "^1.1.1",
118
117
  "postcss": "^8.5.31",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/ui/chat-message.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { cn } from '@/lib/utils'\nimport { Avatar, AvatarImage, AvatarFallback } from '@/components/ui/avatar'\nimport { TypingIndicator, type TypingIndicatorProps } from '@/components/ui/typing-indicator'\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type ChatMessageRole = 'user' | 'assistant'\nexport type ChatMessageVariant = 'bubble' | 'flat'\nexport type ChatMessageColor = 'default' | 'muted' | 'primary' | 'dark'\nexport type ChatMessageSize = 'sm' | 'default' | 'lg'\nexport type ChatMessageRadius = 'md' | 'lg' | 'xl' | '2xl'\nexport type ChatMessageAvatarSize = 'sm' | 'md' | 'lg'\n\n/** Built-in status presets (pass as string to Footer.status for auto-rendering) */\nexport type ChatMessageStatus = 'sending' | 'sent' | 'read' | 'error'\n\n// ============================================================================\n// Context — propagates root props to sub-components\n// ============================================================================\n\ninterface ChatMessageContextValue {\n role: ChatMessageRole\n variant: ChatMessageVariant\n color: ChatMessageColor\n size: ChatMessageSize\n radius: ChatMessageRadius\n tail: boolean\n typing: boolean | Omit<TypingIndicatorProps, 'className'>\n actions?: React.ReactNode\n}\n\nconst ChatMessageContext = React.createContext<ChatMessageContextValue>({\n role: 'assistant',\n variant: 'bubble',\n color: 'default',\n size: 'default',\n radius: '2xl',\n tail: true,\n typing: false,\n actions: undefined,\n})\n\n// ============================================================================\n// Size maps\n// ============================================================================\n\n/** Bubble padding per size */\nconst bubblePaddingMap: Record<ChatMessageSize, string> = {\n sm: 'px-3 py-1.5',\n default: 'px-3.5 py-2',\n lg: 'px-4 py-2.5',\n}\n\n/** Bubble text class per size */\nconst bubbleTextMap: Record<ChatMessageSize, string> = {\n sm: 'text-sm',\n default: 'text-md',\n lg: 'text-base',\n}\n\n/** Footer text size per size */\nconst footerTextMap: Record<ChatMessageSize, string> = {\n sm: 'text-2xs',\n default: 'text-2xs',\n lg: 'text-xs',\n}\n\n/** Gap between avatar and content per message size */\nconst rowGapMap: Record<ChatMessageSize, string> = {\n sm: 'gap-2',\n default: 'gap-2.5',\n lg: 'gap-3',\n}\n\n/** Gap override when avatarSize is explicitly set */\nconst avatarGapMap: Record<ChatMessageAvatarSize, string> = {\n sm: 'gap-1.5',\n md: 'gap-2.5',\n lg: 'gap-3',\n}\n\n// ============================================================================\n// Chat avatar sizes (independent from message size)\n// ============================================================================\n\nconst chatAvatarSizeMap: Record<ChatMessageAvatarSize, string> = {\n sm: 'w-6 h-6', // 24px\n md: 'w-7 h-7', // 28px\n lg: 'w-8 h-8', // 32px\n}\n\nconst chatAvatarFontMap: Record<ChatMessageAvatarSize, string> = {\n sm: 'text-2xs',\n md: 'text-2xs',\n lg: 'text-xs',\n}\n\n// ============================================================================\n// Bubble radius — static maps for Tailwind JIT scanner compatibility\n// ============================================================================\n\n/**\n * Asymmetric with tail: tail corner = rounded-none (0px).\n * assistant → tail at bottom-left | user → tail at bottom-right\n */\nconst bubbleRadiusTailMap: Record<ChatMessageRadius, Record<ChatMessageRole, string>> = {\n md: { assistant: 'rounded-tl-md rounded-tr-md rounded-br-md rounded-bl-none', user: 'rounded-tl-md rounded-tr-md rounded-br-none rounded-bl-md' },\n lg: { assistant: 'rounded-tl-lg rounded-tr-lg rounded-br-lg rounded-bl-none', user: 'rounded-tl-lg rounded-tr-lg rounded-br-none rounded-bl-lg' },\n xl: { assistant: 'rounded-tl-xl rounded-tr-xl rounded-br-xl rounded-bl-none', user: 'rounded-tl-xl rounded-tr-xl rounded-br-none rounded-bl-xl' },\n '2xl': { assistant: 'rounded-tl-2xl rounded-tr-2xl rounded-br-2xl rounded-bl-none', user: 'rounded-tl-2xl rounded-tr-2xl rounded-br-none rounded-bl-2xl' },\n}\n\n/** Symmetric: all corners same radius */\nconst bubbleRadiusSymMap: Record<ChatMessageRadius, string> = {\n md: 'rounded-md',\n lg: 'rounded-lg',\n xl: 'rounded-xl',\n '2xl': 'rounded-2xl',\n}\n\n// ============================================================================\n// Bubble color helper — applies to both roles uniformly\n// ============================================================================\n\nfunction getBubbleColors(color: ChatMessageColor, variant: ChatMessageVariant): string {\n if (variant === 'flat') {\n return color === 'muted' ? 'bg-background-muted text-foreground' : 'text-foreground'\n }\n switch (color) {\n case 'default': return 'bg-background-paper border border-border text-foreground'\n case 'muted': return 'bg-background-muted text-foreground'\n case 'primary': return 'bg-primary text-primary-foreground'\n case 'dark': return 'bg-foreground text-background'\n }\n}\n\n// ============================================================================\n// Built-in status labels\n// ============================================================================\n\nconst builtInStatusLabels: Record<string, { label: string; className: string }> = {\n sending: { label: 'Sending...', className: 'text-text-subtle' },\n sent: { label: 'Sent', className: 'text-text-subtle' },\n read: { label: 'Read', className: 'text-text-subtle' },\n error: { label: 'Failed', className: 'text-error' },\n}\n\n// ============================================================================\n// TypingIndicator size mapping (chat sizes → indicator sizes)\n// ============================================================================\n\nconst typingSizeMap: Record<ChatMessageSize, 'sm' | 'default' | 'lg'> = {\n sm: 'sm',\n default: 'sm',\n lg: 'default',\n}\n\n/** Minimum bubble width when typing — accounts for dot size + padding per chat size */\nconst typingMinWidthMap: Record<ChatMessageSize, string> = {\n sm: 'min-w-12',\n default: 'min-w-12',\n lg: 'min-w-16',\n}\n\n// ============================================================================\n// Props interfaces\n// ============================================================================\n\nexport interface ChatMessageRootProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Sender role — controls alignment (left=assistant, right=user) */\n role?: ChatMessageRole\n /** Bubble visual style */\n variant?: ChatMessageVariant\n /** Bubble background color */\n color?: ChatMessageColor\n /** Size scale — affects text and padding */\n size?: ChatMessageSize\n /** Bubble corner radius */\n radius?: ChatMessageRadius\n /** Asymmetric tail corner (radius=0 on the avatar side) */\n tail?: boolean\n /** Show typing indicator inside Content. Pass true for defaults, or TypingIndicatorProps for custom. */\n typing?: boolean | Omit<TypingIndicatorProps, 'className'>\n /** Avatar size — overrides default gap between avatar and bubble */\n avatarSize?: ChatMessageAvatarSize\n /** Action buttons revealed on hover */\n actions?: React.ReactNode\n}\n\nexport interface ChatMessageAvatarProps {\n /** Avatar size: sm(24px), md(28px), lg(32px) */\n size?: ChatMessageAvatarSize\n /** Image URL */\n src?: string\n /** Alt text for avatar image */\n alt?: string\n /** Initials to display when no image (1–2 characters) */\n initials?: string\n /** Custom icon or ReactNode to render inside the avatar */\n icon?: React.ReactNode\n /** Additional CSS classes */\n className?: string\n}\n\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport interface ChatMessageContentProps extends React.HTMLAttributes<HTMLDivElement> {}\n\nexport interface ChatMessageFooterProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Pre-formatted timestamp string (e.g. \"12:34 PM\") */\n timestamp?: string\n /** Status: built-in preset ('sending' | 'sent' | 'read' | 'error') or custom ReactNode */\n status?: React.ReactNode\n /** Size override (defaults to context value from ChatMessage root) */\n size?: ChatMessageSize\n}\n\n// ============================================================================\n// ChatMessage Root\n// ============================================================================\n\nconst ChatMessage = React.forwardRef<HTMLDivElement, ChatMessageRootProps>(\n (\n {\n className,\n role = 'assistant',\n variant = 'bubble',\n color = 'default',\n size = 'default',\n radius = '2xl',\n tail = true,\n typing = false,\n avatarSize,\n actions,\n children,\n ...props\n },\n ref\n ) => {\n const ctx = React.useMemo<ChatMessageContextValue>(\n () => ({ role, variant, color, size, radius, tail, typing, actions }),\n [role, variant, color, size, radius, tail, typing, actions]\n )\n\n const gapClass = avatarSize ? avatarGapMap[avatarSize] : rowGapMap[size]\n\n return (\n <ChatMessageContext.Provider value={ctx}>\n <div\n ref={ref}\n className={cn(\n 'group/message flex items-end',\n gapClass,\n role === 'user' && variant !== 'flat' ? 'flex-row-reverse' : 'flex-row',\n className\n )}\n {...props}\n >\n {children}\n </div>\n </ChatMessageContext.Provider>\n )\n }\n)\nChatMessage.displayName = 'ChatMessage'\n\n// ============================================================================\n// Default AI sparkle icon\n// ============================================================================\n\nfunction DefaultAiIcon() {\n return (\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\" className=\"w-3/5 h-3/5\" aria-hidden=\"true\">\n <path d=\"M12 3l1.8 5.4 5.4 1.8-5.4 1.8L12 17.4l-1.8-5.4L4.8 10.2l5.4-1.8z\" />\n <path d=\"M19.5 3.5l.8 2.4 2.4.8-2.4.8L19.5 10l-.8-2.5-2.4-.8 2.4-.8z\" opacity=\".6\" />\n <path d=\"M4.5 14.5l.7 2 2 .7-2 .7L4.5 20l-.7-2-2-.7 2-.7z\" opacity=\".4\" />\n </svg>\n )\n}\n\n// ============================================================================\n// ChatMessageAvatar — wraps Avatar component with chat-specific sizes\n// ============================================================================\n\nconst ChatMessageAvatar = React.forwardRef<HTMLSpanElement, ChatMessageAvatarProps>(\n ({ className, size: avatarSize = 'md', src, alt = 'Avatar', initials, icon }, ref) => (\n <Avatar\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ref={ref as any}\n aria-hidden=\"true\"\n className={cn(chatAvatarSizeMap[avatarSize], 'shrink-0', className)}\n >\n {src && <AvatarImage src={src} alt={alt} />}\n <AvatarFallback className={cn('font-semibold', chatAvatarFontMap[avatarSize])}>\n {icon ?? (initials || <DefaultAiIcon />)}\n </AvatarFallback>\n </Avatar>\n )\n)\nChatMessageAvatar.displayName = 'ChatMessageAvatar'\n\n// ============================================================================\n// ChatMessageContent\n// ============================================================================\n\nconst ChatMessageContent = React.forwardRef<HTMLDivElement, ChatMessageContentProps>(\n ({ className, children, ...props }, ref) => {\n const { role, variant, color, size, radius, tail, typing, actions } = React.useContext(ChatMessageContext)\n const isTyping = !!typing\n const typingProps = typeof typing === 'object' ? typing : {}\n\n // Dark bubble backgrounds need inverted typing dot colors\n const isDarkBg = color === 'primary' || color === 'dark'\n const invertDots = variant === 'bubble' && isDarkBg\n\n // flat variant never has a tail (asymmetric corner)\n const effectiveTail = variant === 'flat' ? false : tail\n const radiusClasses = effectiveTail\n ? bubbleRadiusTailMap[radius][role]\n : bubbleRadiusSymMap[radius]\n\n const bubble = (\n <div\n ref={ref}\n className={cn(\n bubbleTextMap[size],\n variant === 'bubble' && 'max-w-[75%]',\n isTyping && [typingMinWidthMap[size], 'text-center'],\n getBubbleColors(color, variant),\n (variant === 'bubble' || variant === 'flat') && bubblePaddingMap[size],\n (variant === 'bubble' || (variant === 'flat' && color === 'muted')) && radiusClasses,\n className\n )}\n {...props}\n >\n {isTyping ? (\n <TypingIndicator\n size={typingSizeMap[size]}\n color=\"muted\"\n {...typingProps}\n className={cn('align-middle', invertDots && '[&>div>div]:bg-current')}\n />\n ) : children}\n </div>\n )\n\n if (!actions) return bubble\n\n return (\n <div className={cn('flex items-end gap-1.5', role === 'user' && variant !== 'flat' ? 'flex-row-reverse' : 'flex-row')}>\n {bubble}\n <div className={cn(\n 'shrink-0 flex items-center gap-1 pb-0.5',\n 'opacity-0 group-hover/message:opacity-100',\n 'transition-opacity duration-normal',\n )}>\n {actions}\n </div>\n </div>\n )\n }\n)\nChatMessageContent.displayName = 'ChatMessageContent'\n\n// ============================================================================\n// ChatMessageFooter\n// ============================================================================\n\nconst ChatMessageFooter = React.forwardRef<HTMLDivElement, ChatMessageFooterProps>(\n (\n {\n className,\n timestamp,\n status,\n role: roleProp,\n size: sizeProp,\n children,\n ...props\n },\n ref\n ) => {\n const ctx = React.useContext(ChatMessageContext)\n const role = roleProp ?? ctx.role\n const size = sizeProp ?? ctx.size\n const variant = ctx.variant\n\n // Resolve status: built-in preset string → label, or pass-through ReactNode\n const statusContent = React.useMemo(() => {\n if (status == null) return null\n if (typeof status === 'string' && status in builtInStatusLabels) {\n const { label, className: cls } = builtInStatusLabels[status]\n return <span className={cls}>{label}</span>\n }\n return status\n }, [status])\n\n return (\n <div\n ref={ref}\n className={cn(\n 'flex items-center gap-1 select-none',\n footerTextMap[size],\n 'text-text-subtle',\n role === 'user' && variant !== 'flat' ? 'justify-end' : 'justify-start',\n className\n )}\n {...props}\n >\n {children}\n {statusContent}\n {timestamp && <span>{timestamp}</span>}\n </div>\n )\n }\n)\nChatMessageFooter.displayName = 'ChatMessageFooter'\n\nexport {\n ChatMessage,\n ChatMessageAvatar,\n ChatMessageContent,\n ChatMessageFooter,\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/ui/switch.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport * as SwitchPrimitive from '@radix-ui/react-switch'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from '@/lib/utils'\nimport { useFieldContext } from './field'\n\n// Switch track variants\nconst switchVariants = cva(\n [\n 'group peer inline-flex shrink-0 cursor-pointer items-center rounded-full',\n 'border border-transparent transition-all duration-normal ease-out',\n 'focus-visible:focus-ring',\n 'disabled:cursor-not-allowed disabled:opacity-50',\n 'data-[state=unchecked]:bg-border',\n ].join(' '),\n {\n variants: {\n size: {\n sm: 'w-[var(--component-switch-track-sm-width)] h-[var(--component-switch-track-sm-height)]',\n default: 'w-[var(--component-switch-track-default-width)] h-[var(--component-switch-track-default-height)]',\n lg: 'w-[var(--component-switch-track-lg-width)] h-[var(--component-switch-track-lg-height)]',\n },\n },\n defaultVariants: {\n size: 'default',\n },\n }\n)\n\n// Thumb sizes\nconst thumbSizes = {\n sm: 'w-[var(--component-switch-thumb-sm)] h-[var(--component-switch-thumb-sm)]',\n default: 'w-[var(--component-switch-thumb-default)] h-[var(--component-switch-thumb-default)]',\n lg: 'w-[var(--component-switch-thumb-lg)] h-[var(--component-switch-thumb-lg)]',\n}\n\n// Thumb translate when checked: track_width - thumb_size - 2px (border 1px × 2)\nconst thumbTranslate = {\n sm: 'data-[state=checked]:translate-x-[calc(var(--component-switch-track-sm-width)_-_var(--component-switch-thumb-sm)_-_2px)]',\n default: 'data-[state=checked]:translate-x-[calc(var(--component-switch-track-default-width)_-_var(--component-switch-thumb-default)_-_2px)]',\n lg: 'data-[state=checked]:translate-x-[calc(var(--component-switch-track-lg-width)_-_var(--component-switch-thumb-lg)_-_2px)]',\n}\n\n// Gap between switch and label\nconst gapSizes = {\n sm: 'gap-2', // 8px\n default: 'gap-2.5', // 10px\n lg: 'gap-3', // 12px\n}\n\n// Label font sizes\nconst labelSizes = {\n sm: 'text-xs', // 12px\n default: 'text-md', // 14px\n lg: 'text-base', // 16px\n}\n\nexport type SwitchLabelPosition = 'start' | 'end' | 'top' | 'bottom'\nexport type SwitchColor = 'default' | 'primary' | 'success' | 'warning' | 'error'\n\n// Checked track color per color variant\nconst checkedTrackColors: Record<SwitchColor, string> = {\n default: 'data-[state=checked]:bg-foreground',\n primary: 'data-[state=checked]:bg-primary',\n success: 'data-[state=checked]:bg-success',\n warning: 'data-[state=checked]:bg-warning',\n error: 'data-[state=checked]:bg-error',\n}\n\n// Checked icon color per color variant\nconst checkedIconColors: Record<SwitchColor, string> = {\n default: 'text-foreground',\n primary: 'text-primary',\n success: 'text-success',\n warning: 'text-warning',\n error: 'text-error',\n}\n\n// Icon sizes per thumb size\nconst iconSizes = {\n sm: 'hidden', // 12px thumb — too small for icons\n default: 'w-2.5 h-2.5', // 10px icon in 16px thumb\n lg: 'w-3.5 h-3.5', // 14px icon in 20px thumb\n}\n\nexport interface SwitchProps\n extends React.ComponentPropsWithoutRef<typeof SwitchPrimitive.Root>,\n VariantProps<typeof switchVariants> {\n label?: string\n labelPosition?: SwitchLabelPosition\n startLabel?: string\n endLabel?: string\n checkedIcon?: React.ReactNode\n uncheckedIcon?: React.ReactNode\n color?: SwitchColor\n}\n\nconst Switch = React.forwardRef<\n React.ElementRef<typeof SwitchPrimitive.Root>,\n SwitchProps\n>(({ className, size, label, labelPosition = 'end', startLabel, endLabel, checkedIcon, uncheckedIcon, color = 'default', disabled, id, ...props }, ref) => {\n const fieldContext = useFieldContext()\n const resolvedSize = size || 'default'\n const resolvedDisabled = disabled ?? fieldContext?.disabled\n const generatedId = React.useId()\n const switchId = id ?? fieldContext?.id ?? generatedId\n\n const switchEl = (\n <SwitchPrimitive.Root\n ref={ref}\n id={switchId}\n disabled={resolvedDisabled}\n className={cn(switchVariants({ size }), checkedTrackColors[color], className)}\n {...props}\n >\n <SwitchPrimitive.Thumb\n className={cn(\n 'group/thumb pointer-events-none flex items-center justify-center rounded-full shadow-sm ring-0',\n color === 'default' ? 'bg-background' : 'bg-primary-foreground',\n 'transition-transform duration-normal ease-out',\n 'data-[state=unchecked]:translate-x-0',\n thumbSizes[resolvedSize],\n thumbTranslate[resolvedSize]\n )}\n >\n {(checkedIcon || uncheckedIcon) && resolvedSize !== 'sm' && (\n <>\n {checkedIcon && (\n <span className={cn(\n iconSizes[resolvedSize],\n checkedIconColors[color],\n 'hidden group-data-[state=checked]/thumb:block',\n )}>\n {checkedIcon}\n </span>\n )}\n {uncheckedIcon && (\n <span className={cn(\n iconSizes[resolvedSize],\n 'text-text-muted',\n 'hidden group-data-[state=unchecked]/thumb:block',\n )}>\n {uncheckedIcon}\n </span>\n )}\n </>\n )}\n </SwitchPrimitive.Thumb>\n </SwitchPrimitive.Root>\n )\n\n const labelClassName = cn(\n labelSizes[resolvedSize],\n 'text-text-muted cursor-pointer select-none transition-colors duration-micro',\n 'group-hover/switch:text-foreground',\n resolvedDisabled && 'opacity-50 cursor-not-allowed'\n )\n\n // Sides mode: startLabel / endLabel\n if (startLabel || endLabel) {\n return (\n <div className={cn('group/switch flex items-center', gapSizes[resolvedSize])}>\n {startLabel && (\n <label htmlFor={switchId} className={labelClassName}>\n {startLabel}\n </label>\n )}\n <div className=\"flex items-center\">\n {switchEl}\n </div>\n {endLabel && (\n <label htmlFor={switchId} className={labelClassName}>\n {endLabel}\n </label>\n )}\n </div>\n )\n }\n\n if (!label) return switchEl\n\n const isVertical = labelPosition === 'top' || labelPosition === 'bottom'\n const isReversed = labelPosition === 'start' || labelPosition === 'top'\n\n return (\n <div className={cn(\n 'group/switch flex',\n isVertical ? 'flex-col items-start gap-1.5' : 'items-center',\n isReversed && (isVertical ? 'flex-col-reverse' : 'flex-row-reverse'),\n !isVertical && gapSizes[resolvedSize],\n )}>\n <div className=\"flex items-center\">\n {switchEl}\n </div>\n <label htmlFor={switchId} className={labelClassName}>\n {label}\n </label>\n </div>\n )\n})\nSwitch.displayName = 'Switch'\n\nexport { Switch, switchVariants }\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/ui/navigation-menu.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport * as NavigationMenuPrimitive from '@radix-ui/react-navigation-menu'\nimport * as CollapsiblePrimitive from '@radix-ui/react-collapsible'\nimport { Slot } from '@radix-ui/react-slot'\nimport { cn } from '@/lib/utils'\n\n// ─── Built-in Icons ───────────────────────────────────────\n\nfunction ChevronDownIcon({ className }: { className?: string }) {\n return (\n <svg className={className} fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2} aria-hidden=\"true\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M19 9l-7 7-7-7\" />\n </svg>\n )\n}\n\nfunction ChevronRightIcon({ className }: { className?: string }) {\n return (\n <svg className={className} fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2} aria-hidden=\"true\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M9 5l7 7-7 7\" />\n </svg>\n )\n}\n\n// ─── Radius Configuration ─────────────────────────────────\n\ntype NavigationMenuRadius = 'sm' | 'md' | 'lg' | 'xl'\n\nconst contentRadiusMap: Record<NavigationMenuRadius, string> = {\n sm: 'rounded', // 4px\n md: 'rounded-md', // 6px\n lg: 'rounded-lg', // 8px\n xl: 'rounded-xl', // 12px\n}\n\nconst itemRadiusMap: Record<NavigationMenuRadius, string> = {\n sm: 'rounded-sm', // 2px\n md: 'rounded', // 4px\n lg: 'rounded-md', // 6px\n xl: 'rounded-lg', // 8px\n}\n\n// ─── Contexts ─────────────────────────────────────────────\n\ntype NavigationMenuContextValue = {\n orientation: 'horizontal' | 'vertical'\n size: 'sm' | 'md' | 'default' | 'lg'\n collapsed: boolean\n radius: NavigationMenuRadius\n fontWeight: 'normal' | 'semibold'\n}\n\nconst NavigationMenuContext = React.createContext<NavigationMenuContextValue>({\n orientation: 'horizontal',\n size: 'default',\n collapsed: false,\n radius: 'lg',\n fontWeight: 'normal',\n})\nconst useNavigationMenuContext = () => React.useContext(NavigationMenuContext)\n\n// Whether we're inside NavigationMenuContent (affects link styling)\nconst ContentLevelContext = React.createContext(false)\n\n// ─── Size Configuration ───────────────────────────────────\n\nconst navigationMenuSizeMap = {\n sm: {\n trigger: 'h-8 text-sm px-3 gap-2',\n link: 'h-8 text-sm px-3 gap-2',\n icon: 'icon-xs',\n collapsedSquare: 'size-8', collapsedWidth: 56,\n dropdownLink: 'px-3 py-1.5 text-sm gap-2',\n subLink: 'h-8 text-sm pl-8 pr-3 gap-2',\n groupLabel: 'text-2xs px-3 mb-1', groupMargin: 'mt-4 first:mt-0',\n },\n md: {\n trigger: 'h-9 text-md px-3.5 gap-2',\n link: 'h-9 text-md px-3.5 gap-2',\n icon: 'icon-sm',\n collapsedSquare: 'size-9', collapsedWidth: 60,\n dropdownLink: 'px-3 py-1.5 text-md gap-2',\n subLink: 'h-9 text-md pl-9 pr-3.5 gap-2',\n groupLabel: 'text-xs px-3.5 mb-1', groupMargin: 'mt-4 first:mt-0',\n },\n default: {\n trigger: 'h-10 text-md px-4 gap-2',\n link: 'h-10 text-md px-4 gap-2',\n icon: 'icon-sm',\n collapsedSquare: 'size-10', collapsedWidth: 64,\n dropdownLink: 'px-3 py-2 text-md gap-2',\n subLink: 'h-10 text-md pl-10 pr-4 gap-2',\n groupLabel: 'text-xs px-4 mb-1.5', groupMargin: 'mt-5 first:mt-0',\n },\n lg: {\n trigger: 'h-12 text-base px-6 gap-2',\n link: 'h-12 text-base px-6 gap-2',\n icon: 'icon-sm',\n collapsedSquare: 'size-12', collapsedWidth: 72,\n dropdownLink: 'px-3 py-2.5 text-base gap-2',\n subLink: 'h-12 text-base pl-12 pr-6 gap-2',\n groupLabel: 'text-xs px-4 mb-2', groupMargin: 'mt-6 first:mt-0',\n },\n} as const\n\n// ─── NavigationMenu (Root) ────────────────────────────────\n\nexport interface NavigationMenuProps extends React.HTMLAttributes<HTMLElement> {\n /** Layout orientation */\n orientation?: 'horizontal' | 'vertical'\n /** Size of the menu items */\n size?: 'sm' | 'md' | 'default' | 'lg'\n /** Vertical only: show icons only (collapsed sidebar) */\n collapsed?: boolean\n /** Vertical only: sidebar width (default: 256px / 16rem) */\n width?: number | string\n /** Vertical only: collapsed sidebar width (default: 64px / 4rem) */\n collapsedWidth?: number | string\n /** Border radius for dropdown content and items */\n radius?: NavigationMenuRadius\n /** Font weight for menu items (default: normal, active items always use semibold) */\n fontWeight?: 'normal' | 'semibold'\n /** Horizontal only: delay before hover opens in ms */\n delayDuration?: number\n /** Horizontal only: skip delay when moving between triggers */\n skipDelayDuration?: number\n /** Controlled active menu item value */\n value?: string\n /** Default active menu item value (uncontrolled) */\n defaultValue?: string\n /** Callback when active item changes */\n onValueChange?: (value: string) => void\n}\n\nconst NavigationMenu = React.forwardRef<HTMLElement, NavigationMenuProps>(\n ({\n className,\n orientation = 'horizontal',\n size = 'default',\n collapsed = false,\n width,\n collapsedWidth,\n radius = 'lg',\n fontWeight = 'normal',\n delayDuration = 200,\n skipDelayDuration = 300,\n value,\n defaultValue,\n onValueChange,\n children,\n style,\n ...props\n }, ref) => {\n const contextValue = React.useMemo(\n () => ({ orientation, size, collapsed: orientation === 'vertical' ? collapsed : false, radius, fontWeight }),\n [orientation, size, collapsed, radius, fontWeight]\n )\n\n if (orientation === 'horizontal') {\n return (\n <NavigationMenuContext.Provider value={contextValue}>\n <NavigationMenuPrimitive.Root\n ref={ref as React.Ref<HTMLDivElement>}\n className={cn('relative', className)}\n delayDuration={delayDuration}\n skipDelayDuration={skipDelayDuration}\n value={value}\n defaultValue={defaultValue ?? ''}\n onValueChange={onValueChange}\n >\n {children}\n </NavigationMenuPrimitive.Root>\n </NavigationMenuContext.Provider>\n )\n }\n\n // Vertical mode\n const resolvedWidth = collapsed\n ? (collapsedWidth ?? navigationMenuSizeMap[size].collapsedWidth)\n : (width ?? 256)\n const widthValue = typeof resolvedWidth === 'number' ? `${resolvedWidth}px` : resolvedWidth\n\n return (\n <NavigationMenuContext.Provider value={contextValue}>\n <nav\n ref={ref}\n aria-label=\"navigation\"\n className={cn(\n 'flex flex-col',\n 'transition-[width] duration-normal ease-out',\n className\n )}\n style={{ width: widthValue, ...style }}\n {...props}\n >\n {children}\n </nav>\n </NavigationMenuContext.Provider>\n )\n }\n)\nNavigationMenu.displayName = 'NavigationMenu'\n\n// ─── NavigationMenuList ───────────────────────────────────\n\nexport interface NavigationMenuListProps extends React.HTMLAttributes<HTMLUListElement> {}\n\nconst NavigationMenuList = React.forwardRef<HTMLUListElement, NavigationMenuListProps>(\n ({ className, children, ...props }, ref) => {\n const { orientation } = useNavigationMenuContext()\n\n if (orientation === 'horizontal') {\n return (\n <NavigationMenuPrimitive.List\n ref={ref}\n className={cn('flex items-center gap-1', className)}\n {...props}\n >\n {children}\n </NavigationMenuPrimitive.List>\n )\n }\n\n return (\n <ul\n ref={ref}\n className={cn('flex flex-col gap-0.5', className)}\n {...props}\n >\n {children}\n </ul>\n )\n }\n)\nNavigationMenuList.displayName = 'NavigationMenuList'\n\n// ─── NavigationMenuItem ───────────────────────────────────\n\nexport interface NavigationMenuItemProps extends React.HTMLAttributes<HTMLLIElement> {\n /** Value identifier for Radix (horizontal mode) */\n value?: string\n /** Vertical only: default open state for sub-menu */\n defaultOpen?: boolean\n}\n\nconst NavigationMenuItem = React.forwardRef<HTMLLIElement, NavigationMenuItemProps>(\n ({ className, value, defaultOpen = false, children, ...props }, ref) => {\n const { orientation, collapsed } = useNavigationMenuContext()\n const [open, setOpen] = React.useState(defaultOpen)\n\n // Auto-close sub-menus when collapsed\n React.useEffect(() => {\n if (collapsed) setOpen(false)\n }, [collapsed])\n\n if (orientation === 'horizontal') {\n return (\n <NavigationMenuPrimitive.Item\n ref={ref}\n className={cn('relative', className)}\n value={value}\n {...props}\n >\n {children}\n </NavigationMenuPrimitive.Item>\n )\n }\n\n // Vertical: wrap in Collapsible.Root for sub-menu support\n return (\n <CollapsiblePrimitive.Root\n open={collapsed ? false : open}\n onOpenChange={collapsed ? undefined : setOpen}\n asChild\n >\n <li ref={ref} className={cn('', className)} {...props}>\n {children}\n </li>\n </CollapsiblePrimitive.Root>\n )\n }\n)\nNavigationMenuItem.displayName = 'NavigationMenuItem'\n\n// ─── NavigationMenuTrigger ────────────────────────────────\n\nexport interface NavigationMenuTriggerProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n /** Icon displayed before the label */\n icon?: React.ReactNode\n /** Custom chevron icon (default: built-in ChevronDown for horizontal, ChevronRight for vertical) */\n chevronIcon?: React.ReactNode\n}\n\nconst NavigationMenuTrigger = React.forwardRef<HTMLButtonElement, NavigationMenuTriggerProps>(\n ({ className, children, icon, chevronIcon, ...props }, ref) => {\n const { orientation, size, collapsed, radius, fontWeight: fw } = useNavigationMenuContext()\n const s = navigationMenuSizeMap[size]\n const fwClass = fw === 'semibold' ? 'font-semibold' : 'font-normal'\n\n if (orientation === 'horizontal') {\n return (\n <NavigationMenuPrimitive.Trigger\n ref={ref}\n className={cn(\n 'group inline-flex items-center justify-center',\n s.trigger,\n 'gap-0',\n fwClass, 'text-text-muted',\n 'transition-colors duration-fast',\n 'hover:text-foreground',\n 'data-[state=open]:text-foreground',\n 'focus-visible:focus-ring',\n 'disabled:pointer-events-none disabled:opacity-50',\n className\n )}\n {...props}\n >\n {icon && <span className={cn('shrink-0 mr-2', s.icon)}>{icon}</span>}\n {children}\n <span className={cn('shrink-0 ml-1 text-text-subtle transition-transform duration-fast group-data-[state=open]:rotate-180', s.icon)}>\n {chevronIcon ?? <ChevronDownIcon className=\"size-full\" />}\n </span>\n </NavigationMenuPrimitive.Trigger>\n )\n }\n\n // Vertical: Collapsible trigger\n return (\n <CollapsiblePrimitive.Trigger\n ref={ref}\n className={cn(\n 'group flex items-center cursor-pointer',\n contentRadiusMap[radius],\n collapsed\n ? [s.collapsedSquare, 'justify-center mx-auto']\n : ['w-full', s.trigger],\n fwClass, 'text-text-muted transition-colors duration-fast',\n 'hover:text-foreground hover:bg-background-muted',\n !collapsed && 'data-[state=open]:text-foreground',\n 'focus-visible:focus-ring',\n 'disabled:pointer-events-none disabled:opacity-50',\n className\n )}\n {...(collapsed && typeof children === 'string' ? { title: children } : {})}\n {...props}\n >\n {icon && <span className={cn('shrink-0', s.icon)}>{icon}</span>}\n {!collapsed && (\n <>\n <span className=\"flex-1 text-left truncate\">{children}</span>\n <span\n className={cn(\n 'shrink-0 text-text-subtle transition-transform duration-normal',\n s.icon,\n 'group-data-[state=open]:rotate-90'\n )}\n >\n {chevronIcon ?? <ChevronRightIcon className=\"size-full\" />}\n </span>\n </>\n )}\n </CollapsiblePrimitive.Trigger>\n )\n }\n)\nNavigationMenuTrigger.displayName = 'NavigationMenuTrigger'\n\n// ─── NavigationMenuContent ────────────────────────────────\n\nexport interface NavigationMenuContentProps extends React.HTMLAttributes<HTMLDivElement> {}\n\nconst NavigationMenuContent = React.forwardRef<HTMLDivElement, NavigationMenuContentProps>(\n ({ className, children, ...props }, ref) => {\n const { orientation, collapsed, radius } = useNavigationMenuContext()\n\n if (orientation === 'horizontal') {\n return (\n <ContentLevelContext.Provider value={true}>\n <NavigationMenuPrimitive.Content\n ref={ref}\n className={cn(\n 'absolute left-0 top-full z-dropdown pt-1',\n 'data-[state=open]:animate-fade-in data-[state=closed]:animate-fade-out',\n className\n )}\n {...props}\n >\n <div className={cn('min-w-[180px] border border-border bg-background shadow-lg p-1.5 grid gap-0.5', contentRadiusMap[radius])}>\n {children}\n </div>\n </NavigationMenuPrimitive.Content>\n </ContentLevelContext.Provider>\n )\n }\n\n // Vertical: Collapsible content (hidden when collapsed)\n if (collapsed) return null\n\n return (\n <ContentLevelContext.Provider value={true}>\n <CollapsiblePrimitive.Content\n ref={ref}\n className={cn(\n 'overflow-hidden',\n 'data-[state=open]:animate-collapsible-down data-[state=closed]:animate-collapsible-up',\n )}\n {...props}\n >\n <div className={cn(\n 'flex flex-col gap-0.5 py-1',\n className\n )}>\n {children}\n </div>\n </CollapsiblePrimitive.Content>\n </ContentLevelContext.Provider>\n )\n }\n)\nNavigationMenuContent.displayName = 'NavigationMenuContent'\n\n// ─── NavigationMenuLink ───────────────────────────────────\n\nexport interface NavigationMenuLinkProps extends React.AnchorHTMLAttributes<HTMLAnchorElement> {\n /** Whether the link represents the current page */\n active?: boolean\n /** Compose with custom link component (Radix Slot) */\n asChild?: boolean\n /** Icon displayed before the label */\n icon?: React.ReactNode\n}\n\nconst NavigationMenuLink = React.forwardRef<HTMLAnchorElement, NavigationMenuLinkProps>(\n ({ className, active, asChild, icon, children, ...props }, ref) => {\n const { orientation, size, collapsed, radius, fontWeight: fw } = useNavigationMenuContext()\n const s = navigationMenuSizeMap[size]\n const fwClass = fw === 'semibold' ? 'font-semibold' : 'font-normal'\n const inContent = React.useContext(ContentLevelContext)\n\n if (orientation === 'horizontal') {\n // Exclude onSelect to avoid React vs Radix type conflict\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const { onSelect, ...radixSafeProps } = props as any\n\n // Content-level links (inside dropdown): block style with hover bg\n if (inContent) {\n return (\n <NavigationMenuPrimitive.Link\n ref={ref}\n className={cn(\n 'flex items-center w-full',\n s.dropdownLink,\n itemRadiusMap[radius],\n 'text-text-muted transition-colors duration-fast',\n 'hover:text-foreground hover:bg-background-muted',\n active && 'text-foreground bg-background-muted font-semibold',\n 'focus-visible:focus-ring',\n className\n )}\n active={active}\n asChild={asChild}\n onSelect={onSelect}\n {...radixSafeProps}\n >\n {asChild ? children : (\n <>\n {icon && <span className={cn('shrink-0', s.icon)}>{icon}</span>}\n {children}\n </>\n )}\n </NavigationMenuPrimitive.Link>\n )\n }\n\n // Top-level horizontal links: text only, no hover bg\n return (\n <NavigationMenuPrimitive.Link\n ref={ref}\n className={cn(\n 'inline-flex items-center justify-center',\n s.link,\n fwClass, 'text-text-muted',\n 'transition-colors duration-fast',\n 'hover:text-foreground',\n active && 'text-foreground font-semibold',\n 'focus-visible:focus-ring',\n className\n )}\n active={active}\n asChild={asChild}\n onSelect={onSelect}\n {...radixSafeProps}\n >\n {asChild ? children : (\n <>\n {icon && <span className={cn('shrink-0', s.icon)}>{icon}</span>}\n {children}\n </>\n )}\n </NavigationMenuPrimitive.Link>\n )\n }\n\n // ── Vertical mode ──\n\n const Comp = asChild ? Slot : 'a'\n\n // Content-level links (sub-menu items): compact, indented\n if (inContent) {\n return (\n <Comp\n ref={ref}\n className={cn(\n 'flex items-center w-full cursor-pointer',\n contentRadiusMap[radius],\n s.subLink,\n 'text-text-muted transition-colors duration-fast',\n 'hover:text-foreground hover:bg-background-muted',\n active && 'text-foreground bg-background-muted font-semibold',\n 'focus-visible:focus-ring',\n className\n )}\n {...(active ? { 'aria-current': 'page' as const } : {})}\n {...props}\n >\n {icon && <span className={cn('shrink-0', s.icon)}>{icon}</span>}\n {!collapsed && children}\n </Comp>\n )\n }\n\n // Top-level vertical links\n return (\n <Comp\n ref={ref}\n className={cn(\n 'relative flex items-center cursor-pointer',\n contentRadiusMap[radius],\n collapsed\n ? [s.collapsedSquare, 'justify-center mx-auto']\n : ['w-full', s.link],\n 'text-text-muted transition-colors duration-fast',\n 'hover:text-foreground hover:bg-background-muted',\n active && 'text-foreground bg-background-muted font-semibold',\n 'focus-visible:focus-ring',\n className\n )}\n {...(active ? { 'aria-current': 'page' as const } : {})}\n {...(collapsed && typeof children === 'string' ? { title: children } : {})}\n {...props}\n >\n {icon && <span className={cn('shrink-0', s.icon)}>{icon}</span>}\n {!collapsed && <span className=\"truncate\">{children}</span>}\n </Comp>\n )\n }\n)\nNavigationMenuLink.displayName = 'NavigationMenuLink'\n\n// ─── NavigationMenuGroup (vertical only) ──────────────────\n\nexport interface NavigationMenuGroupProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Group header label */\n label?: string\n}\n\nconst NavigationMenuGroup = React.forwardRef<HTMLDivElement, NavigationMenuGroupProps>(\n ({ className, label, children, ...props }, ref) => {\n const { size, collapsed } = useNavigationMenuContext()\n const s = navigationMenuSizeMap[size]\n\n return (\n <div ref={ref} role=\"group\" className={cn(label && !collapsed && s.groupMargin, className)} {...props}>\n {label && !collapsed && (\n <div className={cn(\n 'font-semibold text-text-subtle uppercase tracking-wider select-none',\n s.groupLabel,\n )}>\n {label}\n </div>\n )}\n <ul className=\"flex flex-col gap-0.5\">\n {children}\n </ul>\n </div>\n )\n }\n)\nNavigationMenuGroup.displayName = 'NavigationMenuGroup'\n\n// ─── NavigationMenuIndicator ──────────────────────────────\n\nexport interface NavigationMenuIndicatorProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Active indicator dot color (default: dark/foreground, primary: brand color) */\n color?: 'default' | 'primary'\n}\n\nconst NavigationMenuIndicator = React.forwardRef<HTMLDivElement, NavigationMenuIndicatorProps>(\n ({ className, color = 'default', ...props }, ref) => {\n const { orientation } = useNavigationMenuContext()\n\n // Vertical: active indicator is built into NavigationMenuLink styling\n if (orientation === 'vertical') return null\n\n return (\n <NavigationMenuPrimitive.Indicator\n ref={ref}\n className={cn(\n 'z-10 flex h-[3px] items-end justify-center overflow-hidden',\n 'transition-[width,transform] duration-normal ease-out',\n 'data-[state=visible]:animate-fade-in data-[state=hidden]:animate-fade-out',\n className\n )}\n {...props}\n >\n <div className={cn(\n 'relative h-full w-full rounded-full',\n color === 'default' ? 'bg-foreground' : 'bg-primary'\n )} />\n </NavigationMenuPrimitive.Indicator>\n )\n }\n)\nNavigationMenuIndicator.displayName = 'NavigationMenuIndicator'\n\n// ─── NavigationMenuViewport ───────────────────────────────\n\nexport interface NavigationMenuViewportProps extends React.HTMLAttributes<HTMLDivElement> {}\n\nconst NavigationMenuViewport = React.forwardRef<HTMLDivElement, NavigationMenuViewportProps>(\n ({ className, ...props }, ref) => {\n const { orientation } = useNavigationMenuContext()\n\n // Vertical mode does not use a viewport\n if (orientation === 'vertical') return null\n\n return (\n <div className=\"absolute left-0 top-full z-dropdown w-auto pt-1\">\n <NavigationMenuPrimitive.Viewport\n ref={ref}\n className={cn(\n 'relative overflow-hidden',\n 'border border-border bg-background rounded-xl shadow-lg',\n 'h-[var(--radix-navigation-menu-viewport-height)]',\n 'w-[var(--radix-navigation-menu-viewport-width)]',\n 'transition-[width,height] duration-fast ease-out',\n 'data-[state=open]:animate-nav-viewport-enter',\n 'data-[state=closed]:animate-nav-viewport-exit',\n className\n )}\n {...props}\n />\n </div>\n )\n }\n)\nNavigationMenuViewport.displayName = 'NavigationMenuViewport'\n\n// ─── Exports ──────────────────────────────────────────────\nexport {\n NavigationMenu,\n NavigationMenuList,\n NavigationMenuItem,\n NavigationMenuTrigger,\n NavigationMenuContent,\n NavigationMenuLink,\n NavigationMenuGroup,\n NavigationMenuIndicator,\n NavigationMenuViewport,\n navigationMenuSizeMap,\n type NavigationMenuRadius,\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/ui/radio-group.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport * as RadioGroupPrimitive from '@radix-ui/react-radio-group'\nimport { cva } from 'class-variance-authority'\nimport { cn } from '@/lib/utils'\nimport { useFieldContext } from './field'\n\n// Color maps for checked state\nconst radioColorMap = {\n default: {\n border: 'data-[state=checked]:border-foreground',\n dot: 'bg-foreground',\n },\n primary: {\n border: 'data-[state=checked]:border-primary',\n dot: 'bg-primary',\n },\n} as const\n\nexport type RadioColor = keyof typeof radioColorMap\n\n// Context to pass size, weight, color from RadioGroup to RadioGroupItem\ntype RadioGroupContextValue = {\n size: 'sm' | 'default' | 'lg'\n weight: 'thin' | 'bold'\n color: RadioColor\n disabled?: boolean\n}\nconst RadioGroupContext = React.createContext<RadioGroupContextValue>({ size: 'default', weight: 'bold', color: 'default' })\n\n// RadioGroup container\nconst radioGroupVariants = cva('grid gap-3', {\n variants: {\n orientation: {\n vertical: 'grid-cols-1',\n horizontal: 'grid-flow-col auto-cols-max gap-4',\n },\n },\n defaultVariants: {\n orientation: 'vertical',\n },\n})\n\nexport interface RadioGroupProps\n extends React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Root> {\n size?: 'sm' | 'default' | 'lg'\n weight?: 'thin' | 'bold'\n /** Checked state color */\n color?: RadioColor\n}\n\nconst RadioGroup = React.forwardRef<\n React.ElementRef<typeof RadioGroupPrimitive.Root>,\n RadioGroupProps\n>(({ className, orientation, size = 'default', weight = 'bold', color = 'default', disabled, ...props }, ref) => {\n const fieldContext = useFieldContext()\n const resolvedDisabled = disabled ?? fieldContext?.disabled\n\n return (\n <RadioGroupContext.Provider value={{ size, weight, color, disabled: resolvedDisabled }}>\n <RadioGroupPrimitive.Root\n ref={ref}\n className={cn(radioGroupVariants({ orientation }), className)}\n orientation={orientation || undefined}\n disabled={resolvedDisabled}\n {...props}\n />\n </RadioGroupContext.Provider>\n )\n})\nRadioGroup.displayName = 'RadioGroup'\n\n// RadioGroupItem circle variants\nconst radioItemVariants = cva(\n [\n 'relative shrink-0 rounded-full border-border hover:border-border-strong transition-all duration-micro ease-out',\n 'focus-visible:focus-ring',\n 'disabled:cursor-not-allowed disabled:opacity-50',\n // Transparent hit area expansion via ::after\n \"after:absolute after:content-['']\",\n ].join(' '),\n {\n variants: {\n size: {\n sm: 'w-3.5 h-3.5 after:-inset-[5px]', // 14px circle → 24px click\n default: 'w-4 h-4 after:-inset-2', // 16px circle → 32px click\n lg: 'w-5 h-5 after:-inset-2', // 20px circle → 36px click\n },\n weight: {\n thin: 'border', // 1px\n bold: 'border-2', // 2px\n },\n },\n defaultVariants: {\n size: 'default',\n weight: 'bold',\n },\n }\n)\n\n// Dot sizes per radio size\nconst dotSizes = {\n sm: 'w-1.5 h-1.5', // 6px\n default: 'w-2 h-2', // 8px\n lg: 'w-2.5 h-2.5', // 10px\n}\n\n// Label font sizes\nconst labelSizes = {\n sm: 'text-xs', // 12px\n default: 'text-md', // 14px\n lg: 'text-base', // 16px\n}\n\n// Gap between radio and label\nconst gapSizes = {\n sm: 'gap-1.5',\n default: 'gap-2',\n lg: 'gap-2.5',\n}\n\nexport interface RadioGroupItemProps\n extends React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Item> {\n label?: string\n}\n\nconst RadioGroupItem = React.forwardRef<\n React.ElementRef<typeof RadioGroupPrimitive.Item>,\n RadioGroupItemProps\n>(({ className, label, disabled, ...props }, ref) => {\n const { size, weight, color, disabled: groupDisabled } = React.useContext(RadioGroupContext)\n const resolvedDisabled = disabled ?? groupDisabled\n const itemId = React.useId()\n\n const radio = (\n <RadioGroupPrimitive.Item\n ref={ref}\n id={label ? itemId : undefined}\n disabled={resolvedDisabled}\n className={cn(\n radioItemVariants({ size, weight }),\n radioColorMap[color].border,\n className\n )}\n {...props}\n >\n <RadioGroupPrimitive.Indicator className=\"flex items-center justify-center animate-radio-enter\">\n <div className={cn('rounded-full', radioColorMap[color].dot, dotSizes[size])} />\n </RadioGroupPrimitive.Indicator>\n </RadioGroupPrimitive.Item>\n )\n\n if (!label) return radio\n\n return (\n <div className={cn('group flex items-center', gapSizes[size])}>\n <div className=\"flex items-center\">\n {radio}\n </div>\n <label\n htmlFor={itemId}\n className={cn(\n labelSizes[size],\n 'text-text-muted cursor-pointer select-none transition-colors duration-micro',\n 'group-hover:text-foreground',\n resolvedDisabled && 'opacity-50 cursor-not-allowed'\n )}\n >\n {label}\n </label>\n </div>\n )\n})\nRadioGroupItem.displayName = 'RadioGroupItem'\n\nexport { RadioGroup, RadioGroupItem, radioGroupVariants, radioItemVariants }\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/ui/select.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport * as SelectPrimitive from '@radix-ui/react-select'\nimport { cn } from '@/lib/utils'\n\n// Radius (matches Input — set at Root, propagates to Trigger and Content)\ntype SelectRadius = 'none' | 'sm' | 'base' | 'default' | 'lg' | 'xl' | '2xl' | '3xl' | 'full'\n\nconst triggerRadiusMap: Record<SelectRadius, string> = {\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-full',\n}\n\n// Auto-mapping: root radius → content radius (3 levels)\ntype SelectContentRadius = 'md' | 'lg' | 'xl'\n\nconst contentRadiusFromRoot: Record<SelectRadius, SelectContentRadius> = {\n none: 'md',\n sm: 'md',\n base: 'md',\n default: 'md',\n lg: 'lg',\n xl: 'xl',\n '2xl': 'xl',\n '3xl': 'xl',\n full: 'xl',\n}\n\nconst contentRadiusMap: Record<SelectContentRadius, string> = {\n md: 'rounded-md', // 6px\n lg: 'rounded-lg', // 8px\n xl: 'rounded-xl', // 12px\n}\n\nconst itemRadiusMap: Record<SelectContentRadius, string> = {\n md: 'rounded', // 4px — perceptual balance (67%)\n lg: 'rounded-md', // 6px — perceptual balance (75%)\n xl: 'rounded-lg', // 8px — perceptual balance (67%)\n}\n\n// Size variants (matches Input component)\ntype SelectSize = 'xs' | 'sm' | 'default' | 'lg' | 'xl'\n\n// Trigger sizes (identical to Input)\nconst triggerSizeMap: Record<SelectSize, string> = {\n xs: 'h-9 px-3 text-sm', // 36px\n sm: 'h-10 px-3 text-md', // 40px\n default: 'h-11 px-4 text-base', // 44px\n lg: 'h-12 px-4 text-base', // 48px\n xl: 'h-14 px-4 text-base', // 56px\n}\n\n// Trigger icon sizes (matches Input icon pattern)\nconst triggerIconSizeMap: Record<SelectSize, string> = {\n xs: 'icon-xs', // 14px\n sm: 'icon-xs', // 14px\n default: 'icon-sm', // 16px\n lg: 'icon-sm', // 16px\n xl: 'icon-sm', // 16px\n}\n\n// Auto-mapping: trigger size → content item size (3 levels)\ntype SelectItemSize = 'sm' | 'md' | 'lg'\n\nconst itemSizeFromTrigger: Record<SelectSize, SelectItemSize> = {\n xs: 'sm',\n sm: 'sm',\n default: 'md',\n lg: 'md',\n xl: 'lg',\n}\n\n// Item sizes (font matches Trigger for seamless selection, padding controls density)\nconst itemSizeMap: Record<SelectItemSize, string> = {\n sm: 'pl-2 pr-6 py-1.5 text-sm',\n md: 'pl-3 pr-8 py-1.5 text-base',\n lg: 'pl-3 pr-10 py-2.5 text-base',\n}\n\n// Item indicator (check mark) — right-aligned\nconst indicatorSizeMap: Record<SelectItemSize, string> = {\n sm: 'right-2 h-3 w-3',\n md: 'right-2 h-3.5 w-3.5',\n lg: 'right-3 h-4 w-4',\n}\n\n// Label sizes\nconst labelSizeMap: Record<SelectItemSize, string> = {\n sm: 'px-2 py-1.5 text-xs',\n md: 'px-2 py-1.5 text-xs',\n lg: 'px-3 py-2.5 text-xs',\n}\n\n// Flush mode — items span full width, no inner radius\nconst flushItemPaddingMap: Record<SelectItemSize, string> = {\n sm: 'pl-3 pr-7',\n md: 'pl-4 pr-9',\n lg: 'pl-4 pr-11',\n}\n\nconst flushIndicatorSizeMap: Record<SelectItemSize, string> = {\n sm: 'right-3 h-3 w-3',\n md: 'right-3 h-3.5 w-3.5',\n lg: 'right-4 h-4 w-4',\n}\n\nconst flushLabelPaddingMap: Record<SelectItemSize, string> = {\n sm: 'px-3',\n md: 'px-3',\n lg: 'px-4',\n}\n\n// Root context — set at Root, consumed by Trigger and Content\nconst SelectRootContext = React.createContext<{\n size: SelectSize\n radius: SelectRadius\n}>({ size: 'default', radius: 'default' })\n\n// Style context — set at Content, consumed by Item/Label\nconst SelectStyleContext = React.createContext<{\n contentRadius: SelectContentRadius\n itemSize: SelectItemSize\n flush: boolean\n}>({ contentRadius: 'xl', itemSize: 'md', flush: false })\n\n// Root — state management + size/radius context\nconst Select = ({\n size = 'default',\n radius = 'default',\n ...props\n}: React.ComponentPropsWithoutRef<typeof SelectPrimitive.Root> & {\n size?: SelectSize\n radius?: SelectRadius\n}) => (\n <SelectRootContext.Provider value={{ size, radius }}>\n <SelectPrimitive.Root {...props} />\n </SelectRootContext.Provider>\n)\n\n// Value — displays selected value or placeholder\nconst SelectValue = SelectPrimitive.Value\n\n// Group — groups related items\nconst SelectGroup = SelectPrimitive.Group\n\n// Trigger — the element that opens the select (reads size + radius from context)\nconst SelectTrigger = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>\n>(({ className, children, ...props }, ref) => {\n const { size, radius } = React.useContext(SelectRootContext)\n return (\n <SelectPrimitive.Trigger\n ref={ref}\n className={cn(\n 'flex w-full items-center justify-between bg-background text-foreground hover:bg-background-muted',\n 'border border-border',\n triggerRadiusMap[radius],\n 'transition-colors duration-micro outline-transparent',\n 'focus-visible:shadow-[0_0_0_2px_var(--color-focus-ring)] focus:[outline:2px_solid_transparent]',\n 'disabled:cursor-not-allowed disabled:opacity-50',\n 'data-[placeholder]:text-foreground/30',\n triggerSizeMap[size],\n className\n )}\n {...props}\n >\n {children}\n <SelectPrimitive.Icon asChild>\n <svg\n className={cn('ml-2 shrink-0 text-text-muted', triggerIconSizeMap[size])}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={2}\n aria-hidden=\"true\"\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M19 9l-7 7-7-7\" />\n </svg>\n </SelectPrimitive.Icon>\n </SelectPrimitive.Trigger>\n )\n})\nSelectTrigger.displayName = SelectPrimitive.Trigger.displayName\n\n// ScrollUpButton — scroll indicator at top\nconst SelectScrollUpButton = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.ScrollUpButton>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.ScrollUpButton\n ref={ref}\n className={cn('flex items-center justify-center py-1 cursor-default', className)}\n {...props}\n >\n <svg className=\"icon-xs\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2} aria-hidden=\"true\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M5 15l7-7 7 7\" />\n </svg>\n </SelectPrimitive.ScrollUpButton>\n))\nSelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName\n\n// ScrollDownButton — scroll indicator at bottom\nconst SelectScrollDownButton = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.ScrollDownButton>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.ScrollDownButton\n ref={ref}\n className={cn('flex items-center justify-center py-1 cursor-default', className)}\n {...props}\n >\n <svg className=\"icon-xs\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2} aria-hidden=\"true\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M19 9l-7 7-7-7\" />\n </svg>\n </SelectPrimitive.ScrollDownButton>\n))\nSelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName\n\n// Content — the floating panel (reads size + radius from context, auto-maps both)\nconst SelectContent = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content> & {\n flush?: boolean\n }\n>(({ className, children, position = 'popper', sideOffset = 1, flush = false, onCloseAutoFocus, ...props }, ref) => {\n const { size, radius } = React.useContext(SelectRootContext)\n const itemSize = itemSizeFromTrigger[size]\n const contentRadius = contentRadiusFromRoot[radius]\n return (\n <SelectPrimitive.Portal>\n <SelectStyleContext.Provider value={{ contentRadius, itemSize, flush }}>\n <SelectPrimitive.Content\n ref={ref}\n onCloseAutoFocus={(e) => {\n e.preventDefault()\n onCloseAutoFocus?.(e)\n }}\n className={cn(\n 'relative z-popover min-w-[var(--radix-select-trigger-width)] overflow-hidden border border-border bg-background text-foreground shadow-lg',\n flush ? 'py-1' : 'p-1',\n contentRadiusMap[contentRadius],\n position === 'popper' &&\n 'max-h-[var(--radix-select-content-available-height)]',\n className\n )}\n position={position}\n sideOffset={sideOffset}\n {...props}\n >\n <SelectScrollUpButton />\n <SelectPrimitive.Viewport\n className={cn(\n position === 'popper' &&\n 'h-[var(--radix-select-content-available-height)] w-full'\n )}\n >\n {children}\n </SelectPrimitive.Viewport>\n <SelectScrollDownButton />\n </SelectPrimitive.Content>\n </SelectStyleContext.Provider>\n </SelectPrimitive.Portal>\n )\n})\nSelectContent.displayName = SelectPrimitive.Content.displayName\n\n// Item — a single selectable item (with right-aligned check indicator)\nconst SelectItem = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>\n>(({ className, children, ...props }, ref) => {\n const { contentRadius, itemSize, flush } = React.useContext(SelectStyleContext)\n return (\n <SelectPrimitive.Item\n ref={ref}\n className={cn(\n 'relative flex w-full cursor-default select-none items-center outline-none',\n itemSizeMap[itemSize],\n !flush && itemRadiusMap[contentRadius],\n flush && flushItemPaddingMap[itemSize],\n 'transition-colors duration-fast',\n 'focus:bg-background-muted',\n 'data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\n className\n )}\n {...props}\n >\n <SelectPrimitive.ItemText className=\"truncate\">{children}</SelectPrimitive.ItemText>\n <span className={cn('absolute flex items-center justify-center', flush ? flushIndicatorSizeMap[itemSize] : indicatorSizeMap[itemSize])}>\n <SelectPrimitive.ItemIndicator>\n <svg className=\"icon-xs\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={3} aria-hidden=\"true\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M5 13l4 4L19 7\" />\n </svg>\n </SelectPrimitive.ItemIndicator>\n </span>\n </SelectPrimitive.Item>\n )\n})\nSelectItem.displayName = SelectPrimitive.Item.displayName\n\n// Label — non-interactive group heading\nconst SelectLabel = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Label>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>\n>(({ className, ...props }, ref) => {\n const { itemSize, flush } = React.useContext(SelectStyleContext)\n return (\n <SelectPrimitive.Label\n ref={ref}\n className={cn(\n 'font-semibold text-text-muted',\n labelSizeMap[itemSize],\n flush && flushLabelPaddingMap[itemSize],\n className\n )}\n {...props}\n />\n )\n})\nSelectLabel.displayName = SelectPrimitive.Label.displayName\n\n// Separator — visual divider between groups\nconst SelectSeparator = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Separator>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>\n>(({ className, ...props }, ref) => {\n const { flush } = React.useContext(SelectStyleContext)\n return (\n <SelectPrimitive.Separator\n ref={ref}\n className={cn('h-px bg-border my-1', !flush && '-mx-1', className)}\n {...props}\n />\n )\n})\nSelectSeparator.displayName = SelectPrimitive.Separator.displayName\n\nexport type { SelectRadius, SelectSize }\n\nexport {\n Select,\n SelectTrigger,\n SelectValue,\n SelectContent,\n SelectItem,\n SelectGroup,\n SelectLabel,\n SelectSeparator,\n}\n"],"mappings":";;;;;;AAEA,YAAY,WAAW;AACvB,YAAY,qBAAqB;AAMjC,IAAM,mBAAiD;AAAA,EACrD,MAAM;AAAA,EACN,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,SAAS;AAAA,EACT,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,OAAO;AAAA,EACP,MAAM;AACR;AAKA,IAAM,wBAAmE;AAAA,EACvE,MAAM;AAAA,EACN,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,SAAS;AAAA,EACT,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,OAAO;AAAA,EACP,MAAM;AACR;AAEA,IAAM,mBAAwD;AAAA,EAC5D,IAAI;AAAA;AAAA,EACJ,IAAI;AAAA;AAAA,EACJ,IAAI;AAAA;AACN;AAEA,IAAM,gBAAqD;AAAA,EACzD,IAAI;AAAA;AAAA,EACJ,IAAI;AAAA;AAAA,EACJ,IAAI;AAAA;AACN;AAMA,IAAM,iBAA6C;AAAA,EACjD,IAAI;AAAA;AAAA,EACJ,IAAI;AAAA;AAAA,EACJ,SAAS;AAAA;AAAA,EACT,IAAI;AAAA;AAAA,EACJ,IAAI;AAAA;AACN;AAGA,IAAM,qBAAiD;AAAA,EACrD,IAAI;AAAA;AAAA,EACJ,IAAI;AAAA;AAAA,EACJ,SAAS;AAAA;AAAA,EACT,IAAI;AAAA;AAAA,EACJ,IAAI;AAAA;AACN;AAKA,IAAM,sBAA0D;AAAA,EAC9D,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,IAAI;AAAA,EACJ,IAAI;AACN;AAGA,IAAM,cAA8C;AAAA,EAClD,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AACN;AAGA,IAAM,mBAAmD;AAAA,EACvD,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AACN;AAGA,IAAM,eAA+C;AAAA,EACnD,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AACN;AAGA,IAAM,sBAAsD;AAAA,EAC1D,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AACN;AAEA,IAAM,wBAAwD;AAAA,EAC5D,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AACN;AAEA,IAAM,uBAAuD;AAAA,EAC3D,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AACN;AAGA,IAAM,oBAA0B,oBAG7B,EAAE,MAAM,WAAW,QAAQ,UAAU,CAAC;AAGzC,IAAM,qBAA2B,oBAI9B,EAAE,eAAe,MAAM,UAAU,MAAM,OAAO,MAAM,CAAC;AAGxD,IAAM,SAAS,CAAC;AAAA,EACd,OAAO;AAAA,EACP,SAAS;AAAA,EACT,GAAG;AACL,MAIE,oCAAC,kBAAkB,UAAlB,EAA2B,OAAO,EAAE,MAAM,OAAO,KAChD,oCAAiB,sBAAhB,EAAsB,GAAG,OAAO,CACnC;AAIF,IAAM,cAA8B;AAGpC,IAAM,cAA8B;AAGpC,IAAM,gBAAsB,iBAG1B,CAAC,EAAE,WAAW,UAAU,GAAG,MAAM,GAAG,QAAQ;AAC5C,QAAM,EAAE,MAAM,OAAO,IAAU,iBAAW,iBAAiB;AAC3D,SACE;AAAA,IAAiB;AAAA,IAAhB;AAAA,MACC;AAAA,MACA,WAAW;AAAA,QACT;AAAA,QACA;AAAA,QACA,iBAAiB,MAAM;AAAA,QACvB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,eAAe,IAAI;AAAA,QACnB;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,IAEH;AAAA,IACD,oCAAiB,sBAAhB,EAAqB,SAAO,QAC3B;AAAA,MAAC;AAAA;AAAA,QACC,WAAW,GAAG,iCAAiC,mBAAmB,IAAI,CAAC;AAAA,QACvE,MAAK;AAAA,QACL,SAAQ;AAAA,QACR,QAAO;AAAA,QACP,aAAa;AAAA,QACb,eAAY;AAAA;AAAA,MAEZ,oCAAC,UAAK,eAAc,SAAQ,gBAAe,SAAQ,GAAE,kBAAiB;AAAA,IACxE,CACF;AAAA,EACF;AAEJ,CAAC;AACD,cAAc,cAA8B,wBAAQ;AAGpD,IAAM,uBAA6B,iBAGjC,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QAC1B;AAAA,EAAiB;AAAA,EAAhB;AAAA,IACC;AAAA,IACA,WAAW,GAAG,wDAAwD,SAAS;AAAA,IAC9E,GAAG;AAAA;AAAA,EAEJ,oCAAC,SAAI,WAAU,WAAU,MAAK,QAAO,SAAQ,aAAY,QAAO,gBAAe,aAAa,GAAG,eAAY,UACzG,oCAAC,UAAK,eAAc,SAAQ,gBAAe,SAAQ,GAAE,iBAAgB,CACvE;AACF,CACD;AACD,qBAAqB,cAA8B,+BAAe;AAGlE,IAAM,yBAA+B,iBAGnC,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QAC1B;AAAA,EAAiB;AAAA,EAAhB;AAAA,IACC;AAAA,IACA,WAAW,GAAG,wDAAwD,SAAS;AAAA,IAC9E,GAAG;AAAA;AAAA,EAEJ,oCAAC,SAAI,WAAU,WAAU,MAAK,QAAO,SAAQ,aAAY,QAAO,gBAAe,aAAa,GAAG,eAAY,UACzG,oCAAC,UAAK,eAAc,SAAQ,gBAAe,SAAQ,GAAE,kBAAiB,CACxE;AACF,CACD;AACD,uBAAuB,cAA8B,iCAAiB;AAGtE,IAAM,gBAAsB,iBAK1B,CAAC,EAAE,WAAW,UAAU,WAAW,UAAU,aAAa,GAAG,QAAQ,OAAO,kBAAkB,GAAG,MAAM,GAAG,QAAQ;AAClH,QAAM,EAAE,MAAM,OAAO,IAAU,iBAAW,iBAAiB;AAC3D,QAAM,WAAW,oBAAoB,IAAI;AACzC,QAAM,gBAAgB,sBAAsB,MAAM;AAClD,SACE,oCAAiB,wBAAhB,MACC,oCAAC,mBAAmB,UAAnB,EAA4B,OAAO,EAAE,eAAe,UAAU,MAAM,KACnE;AAAA,IAAiB;AAAA,IAAhB;AAAA,MACC;AAAA,MACA,kBAAkB,CAAC,MAAM;AACvB,UAAE,eAAe;AACjB,2BAAmB,CAAC;AAAA,MACtB;AAAA,MACA,WAAW;AAAA,QACT;AAAA,QACA,QAAQ,SAAS;AAAA,QACjB,iBAAiB,aAAa;AAAA,QAC9B,aAAa,YACX;AAAA,QACF;AAAA,MACF;AAAA,MACA;AAAA,MACA;AAAA,MACC,GAAG;AAAA;AAAA,IAEJ,oCAAC,0BAAqB;AAAA,IACtB;AAAA,MAAiB;AAAA,MAAhB;AAAA,QACC,WAAW;AAAA,UACT,aAAa,YACX;AAAA,QACJ;AAAA;AAAA,MAEC;AAAA,IACH;AAAA,IACA,oCAAC,4BAAuB;AAAA,EAC1B,CACF,CACF;AAEJ,CAAC;AACD,cAAc,cAA8B,wBAAQ;AAGpD,IAAM,aAAmB,iBAGvB,CAAC,EAAE,WAAW,UAAU,GAAG,MAAM,GAAG,QAAQ;AAC5C,QAAM,EAAE,eAAe,UAAU,MAAM,IAAU,iBAAW,kBAAkB;AAC9E,SACE;AAAA,IAAiB;AAAA,IAAhB;AAAA,MACC;AAAA,MACA,WAAW;AAAA,QACT;AAAA,QACA,YAAY,QAAQ;AAAA,QACpB,CAAC,SAAS,cAAc,aAAa;AAAA,QACrC,SAAS,oBAAoB,QAAQ;AAAA,QACrC;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,IAEJ,oCAAiB,0BAAhB,EAAyB,WAAU,cAAY,QAAS;AAAA,IACzD,oCAAC,UAAK,WAAW,GAAG,6CAA6C,QAAQ,sBAAsB,QAAQ,IAAI,iBAAiB,QAAQ,CAAC,KACnI,oCAAiB,+BAAhB,MACC,oCAAC,SAAI,WAAU,WAAU,MAAK,QAAO,SAAQ,aAAY,QAAO,gBAAe,aAAa,GAAG,eAAY,UACzG,oCAAC,UAAK,eAAc,SAAQ,gBAAe,SAAQ,GAAE,kBAAiB,CACxE,CACF,CACF;AAAA,EACF;AAEJ,CAAC;AACD,WAAW,cAA8B,qBAAK;AAG9C,IAAM,cAAoB,iBAGxB,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QAAQ;AAClC,QAAM,EAAE,UAAU,MAAM,IAAU,iBAAW,kBAAkB;AAC/D,SACE;AAAA,IAAiB;AAAA,IAAhB;AAAA,MACC;AAAA,MACA,WAAW;AAAA,QACT;AAAA,QACA,aAAa,QAAQ;AAAA,QACrB,SAAS,qBAAqB,QAAQ;AAAA,QACtC;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ,CAAC;AACD,YAAY,cAA8B,sBAAM;AAGhD,IAAM,kBAAwB,iBAG5B,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QAAQ;AAClC,QAAM,EAAE,MAAM,IAAU,iBAAW,kBAAkB;AACrD,SACE;AAAA,IAAiB;AAAA,IAAhB;AAAA,MACC;AAAA,MACA,WAAW,GAAG,uBAAuB,CAAC,SAAS,SAAS,SAAS;AAAA,MAChE,GAAG;AAAA;AAAA,EACN;AAEJ,CAAC;AACD,gBAAgB,cAA8B,0BAAU;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/ui/chat-input.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from '@/lib/utils'\n\n// ============================================================================\n// Size maps\n// ============================================================================\n\n/** Textarea padding per size */\nconst fieldPaddingMap = {\n sm: 'pt-2.5 px-3 text-md',\n default: 'pt-3 px-4 text-md',\n lg: 'pt-4 px-5 text-base',\n} as const\n\n/** Submit row padding per size */\nconst submitWrapperMap = {\n sm: 'px-2.5 pb-2.5',\n default: 'px-3 pb-3',\n lg: 'px-4 pb-4',\n} as const\n\n/** Submit button dimensions per size */\nconst submitSizeMap = {\n sm: 'h-7 w-7',\n default: 'h-8 w-8',\n lg: 'h-9 w-9',\n} as const\n\n/** Submit button radius — auto-calculated from container radius (min rounded-md) */\nconst submitRadiusMap = {\n sm: 'rounded-md',\n md: 'rounded-md',\n lg: 'rounded-md',\n xl: 'rounded-lg',\n '2xl': 'rounded-xl',\n full: 'rounded-full',\n} as const\n\n/** Submit button radius — direct class map for explicit buttonRadius prop */\nconst buttonRadiusClassMap: Record<ChatInputRadius, string> = {\n sm: 'rounded-sm',\n md: 'rounded-md',\n lg: 'rounded-lg',\n xl: 'rounded-xl',\n '2xl': 'rounded-2xl',\n full: 'rounded-full',\n}\n\n/** Submit icon size class per size */\nconst submitIconSizeMap = {\n sm: 'icon-xs',\n default: 'icon-xs',\n lg: 'icon-sm',\n} as const\n\n/** Character count text size per size */\nconst countStyleMap = {\n sm: 'text-xs',\n default: 'text-xs',\n lg: 'text-sm',\n} as const\n\n/** Approximate line-height (px) per size for auto-resize */\nconst lineHeightMap = {\n sm: 20,\n default: 22,\n lg: 24,\n} as const\n\n/** Field padding in inline layout — horizontal only (vertical centering via flex) */\nconst inlineFieldPaddingMap = {\n sm: 'px-3 text-md',\n default: 'px-4 text-md',\n lg: 'px-5 text-base',\n} as const\n\n/** Submit wrapper padding in inline layout — symmetric vertical */\nconst submitWrapperInlineMap = {\n sm: 'px-2.5 py-2.5',\n default: 'px-3 py-3',\n lg: 'px-4 py-4',\n} as const\n\n// ============================================================================\n// CVA — root container variants\n// ============================================================================\n\nconst chatInputVariants = cva(\n [\n 'flex flex-col w-full overflow-hidden cursor-text',\n 'transition-colors duration-micro',\n ].join(' '),\n {\n variants: {\n variant: {\n outline: [\n 'border border-border bg-background',\n 'hover:border-border-strong',\n 'focus-within:border-border-strong focus-within:hover:border-border-strong',\n ].join(' '),\n filled: [\n 'border border-transparent bg-background-muted',\n 'focus-within:border-border',\n ].join(' '),\n },\n radius: {\n sm: 'rounded-sm',\n md: 'rounded-md',\n lg: 'rounded-lg',\n xl: 'rounded-xl',\n '2xl': 'rounded-2xl',\n full: 'rounded-full',\n },\n },\n defaultVariants: {\n variant: 'outline',\n radius: 'xl',\n },\n }\n)\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type ChatInputSize = 'sm' | 'default' | 'lg'\nexport type ChatInputVariant = 'outline' | 'filled'\nexport type ChatInputRadius = 'sm' | 'md' | 'lg' | 'xl' | '2xl' | 'full'\nexport type ChatInputColor = 'default' | 'primary'\nexport type ChatInputLayout = 'default' | 'inline'\n\n// ============================================================================\n// Context\n// ============================================================================\n\ninterface ChatInputContextValue {\n size: ChatInputSize\n color: ChatInputColor\n layout: ChatInputLayout\n radius: ChatInputRadius\n disabled: boolean\n isEmpty: boolean\n charCount: number\n showCount: boolean\n maxLength: number | undefined\n _setIsEmpty: React.Dispatch<React.SetStateAction<boolean>>\n _setCharCount: React.Dispatch<React.SetStateAction<number>>\n _setShowCount: React.Dispatch<React.SetStateAction<boolean>>\n _setMaxLength: React.Dispatch<React.SetStateAction<number | undefined>>\n _fieldRef: React.MutableRefObject<HTMLTextAreaElement | null>\n _handleSubmit: () => void\n}\n\nconst ChatInputContext = React.createContext<ChatInputContextValue>({\n size: 'default',\n color: 'default',\n layout: 'default',\n radius: 'xl',\n disabled: false,\n isEmpty: true,\n charCount: 0,\n showCount: false,\n maxLength: undefined,\n _setIsEmpty: () => {},\n _setCharCount: () => {},\n _setShowCount: () => {},\n _setMaxLength: () => {},\n _fieldRef: { current: null },\n _handleSubmit: () => {},\n})\n\n// ============================================================================\n// Props interfaces\n// ============================================================================\n\nexport interface ChatInputRootProps\n extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onSubmit'>,\n VariantProps<typeof chatInputVariants> {\n /** Visual style of the container */\n variant?: ChatInputVariant\n /** Corner radius */\n radius?: ChatInputRadius\n /** Size scale */\n size?: ChatInputSize\n /** Submit button color — default (dark) or primary (brand) */\n color?: ChatInputColor\n /** Layout direction — default (stacked) or inline (field + button side by side) */\n layout?: ChatInputLayout\n /** Disable all interaction */\n disabled?: boolean\n /** Called when the user submits (Enter key or Submit button) — receives current field value */\n onSubmit?: (value: string) => void\n}\n\nexport interface ChatInputFieldProps\n extends Omit<React.TextareaHTMLAttributes<HTMLTextAreaElement>, 'children'> {\n /** Maximum visible rows before the field scrolls */\n maxRows?: number\n /** Show character counter — requires maxLength to be set */\n showCount?: boolean\n}\n\nexport interface ChatInputSubmitProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n /** Show loading/stop state — keeps button enabled so user can stop generation */\n loading?: boolean\n /** Called when clicked during loading state (e.g., stop generation) */\n onStop?: () => void\n /** Override the auto-calculated button radius */\n buttonRadius?: ChatInputRadius\n}\n\n// ============================================================================\n// ChatInput — Root container\n// ============================================================================\n\nconst ChatInput = React.forwardRef<HTMLDivElement, ChatInputRootProps>(\n (\n {\n className,\n variant = 'outline',\n radius = 'xl',\n size = 'default',\n color = 'default',\n layout = 'default',\n disabled = false,\n onSubmit,\n children,\n ...props\n },\n ref\n ) => {\n const [isEmpty, setIsEmpty] = React.useState(true)\n const [charCount, setCharCount] = React.useState(0)\n const [showCount, setShowCount] = React.useState(false)\n const [maxLength, setMaxLength] = React.useState<number | undefined>(undefined)\n const fieldRef = React.useRef<HTMLTextAreaElement | null>(null)\n\n const handleSubmit = React.useCallback(() => {\n const el = fieldRef.current\n if (!el || disabled) return\n const value = el.value.trim()\n if (!value) return\n onSubmit?.(value)\n // Auto-clear in uncontrolled mode\n // Controlled-mode users should clear value inside their onSubmit callback\n el.value = ''\n el.style.height = 'auto'\n setIsEmpty(true)\n setCharCount(0)\n }, [disabled, onSubmit])\n\n const contextValue = React.useMemo<ChatInputContextValue>(\n () => ({\n size,\n color,\n layout,\n radius,\n disabled,\n isEmpty,\n charCount,\n showCount,\n maxLength,\n _setIsEmpty: setIsEmpty,\n _setCharCount: setCharCount,\n _setShowCount: setShowCount,\n _setMaxLength: setMaxLength,\n _fieldRef: fieldRef,\n _handleSubmit: handleSubmit,\n }),\n [size, color, layout, radius, disabled, isEmpty, charCount, showCount, maxLength, handleSubmit]\n )\n\n const handleContainerClick = React.useCallback(\n (e: React.MouseEvent<HTMLDivElement>) => {\n // Focus the textarea when clicking anywhere in the container (not on a button)\n if (!disabled && !(e.target as HTMLElement).closest('button')) {\n fieldRef.current?.focus()\n }\n },\n [disabled]\n )\n\n return (\n <ChatInputContext.Provider value={contextValue}>\n <div\n ref={ref}\n data-disabled={disabled || undefined}\n onClick={handleContainerClick}\n className={cn(\n chatInputVariants({ variant, radius }),\n layout === 'inline' && 'flex-row',\n disabled && 'opacity-50 pointer-events-none',\n className\n )}\n {...props}\n >\n {children}\n </div>\n </ChatInputContext.Provider>\n )\n }\n)\nChatInput.displayName = 'ChatInput'\n\n// ============================================================================\n// ChatInputField — Auto-resizing textarea\n// ============================================================================\n\nconst ChatInputField = React.forwardRef<HTMLTextAreaElement, ChatInputFieldProps>(\n (\n {\n className,\n maxRows = 8,\n showCount = false,\n maxLength,\n placeholder,\n onChange,\n onKeyDown,\n disabled,\n ...props\n },\n forwardedRef\n ) => {\n const ctx = React.useContext(ChatInputContext)\n const internalRef = React.useRef<HTMLTextAreaElement | null>(null)\n const isDisabled = disabled ?? ctx.disabled\n\n // Sync showCount + maxLength into root context on mount/update\n React.useEffect(() => {\n ctx._setShowCount(showCount)\n ctx._setMaxLength(maxLength)\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [showCount, maxLength])\n\n // Merge forwarded ref + internal ref + context field ref\n const setRef = React.useCallback(\n (el: HTMLTextAreaElement | null) => {\n internalRef.current = el\n ctx._fieldRef.current = el\n if (typeof forwardedRef === 'function') {\n forwardedRef(el)\n } else if (forwardedRef) {\n (forwardedRef as React.MutableRefObject<HTMLTextAreaElement | null>).current = el\n }\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [forwardedRef]\n )\n\n // Adjust textarea height to content, bounded by maxRows\n const autoResize = React.useCallback(() => {\n const el = internalRef.current\n if (!el) return\n el.style.height = 'auto'\n const maxHeight = maxRows * lineHeightMap[ctx.size]\n const newHeight = Math.min(el.scrollHeight, maxHeight)\n el.style.height = `${newHeight}px`\n el.style.overflowY = el.scrollHeight > maxHeight ? 'auto' : 'hidden'\n }, [ctx.size, maxRows])\n\n const handleChange = React.useCallback(\n (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n const val = e.target.value\n ctx._setIsEmpty(val.trim() === '')\n ctx._setCharCount(val.length)\n autoResize()\n onChange?.(e)\n },\n [ctx, autoResize, onChange]\n )\n\n const handleKeyDown = React.useCallback(\n (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n // Enter = submit | Shift+Enter = new line\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault()\n ctx._handleSubmit()\n }\n onKeyDown?.(e)\n },\n [ctx, onKeyDown]\n )\n\n return (\n <div className={cn('flex-1 min-w-0', ctx.layout === 'inline' && 'flex items-center self-stretch')}>\n <textarea\n ref={setRef}\n rows={1}\n placeholder={placeholder}\n maxLength={maxLength}\n disabled={isDisabled}\n className={cn(\n 'w-full bg-transparent text-foreground placeholder:text-foreground/30',\n 'resize-none outline-none focus:outline-none',\n 'disabled:cursor-not-allowed',\n 'overflow-hidden',\n ctx.layout === 'inline' ? inlineFieldPaddingMap[ctx.size] : fieldPaddingMap[ctx.size],\n className\n )}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n {...props}\n />\n </div>\n )\n }\n)\nChatInputField.displayName = 'ChatInputField'\n\n// ============================================================================\n// ChatInputSubmit — Send / stop button\n// ============================================================================\n\nconst ChatInputSubmit = React.forwardRef<HTMLButtonElement, ChatInputSubmitProps>(\n (\n {\n className,\n loading = false,\n onStop,\n children,\n disabled,\n onClick,\n buttonRadius,\n ...props\n },\n ref\n ) => {\n const ctx = React.useContext(ChatInputContext)\n\n // Disabled: context disabled | user prop | empty field (only when not loading)\n const isDisabled = (disabled ?? ctx.disabled) || (!loading && ctx.isEmpty)\n\n const handleClick = React.useCallback(\n (e: React.MouseEvent<HTMLButtonElement>) => {\n if (loading) {\n onStop?.()\n } else if (!isDisabled) {\n ctx._handleSubmit()\n }\n onClick?.(e)\n },\n [ctx, isDisabled, loading, onStop, onClick]\n )\n\n return (\n <div className={cn('flex items-center justify-end gap-2 shrink-0 cursor-default', ctx.layout === 'inline' ? submitWrapperInlineMap[ctx.size] : submitWrapperMap[ctx.size])}>\n {ctx.showCount && ctx.maxLength != null && (\n <span className={cn('text-text-subtle select-none', countStyleMap[ctx.size])}>\n {ctx.charCount} / {ctx.maxLength}\n </span>\n )}\n <button\n ref={ref}\n type=\"button\"\n disabled={isDisabled && !loading}\n aria-label={loading ? 'Stop generating' : 'Send message'}\n className={cn(\n 'inline-flex items-center justify-center shrink-0',\n buttonRadius ? buttonRadiusClassMap[buttonRadius] : submitRadiusMap[ctx.radius],\n 'transition-all duration-fast',\n 'focus-visible:outline-none focus-visible:focus-ring',\n submitSizeMap[ctx.size],\n // Loading state — enabled, pulsing\n loading && ctx.color === 'default' && 'bg-foreground text-background animate-pulse cursor-pointer',\n loading && ctx.color === 'primary' && 'bg-primary text-primary-foreground animate-pulse cursor-pointer',\n // Enabled state\n !loading && !isDisabled && ctx.color === 'default' && [\n 'bg-foreground text-background',\n 'hover:bg-foreground/90 active:bg-foreground/80 active:scale-pressed cursor-pointer',\n ],\n !loading && !isDisabled && ctx.color === 'primary' && [\n 'bg-primary text-primary-foreground',\n 'hover:bg-primary-hover active:scale-pressed cursor-pointer',\n ],\n // Disabled state\n !loading && isDisabled && 'bg-background-muted text-text-subtle pointer-events-none',\n className\n )}\n onClick={handleClick}\n {...props}\n >\n <span\n aria-hidden=\"true\"\n className={cn('flex items-center justify-center', submitIconSizeMap[ctx.size])}\n >\n {children ?? (loading ? <StopIcon /> : <SendIcon />)}\n </span>\n </button>\n </div>\n )\n }\n)\nChatInputSubmit.displayName = 'ChatInputSubmit'\n\n// ============================================================================\n// Built-in SVG icons — no external icon dependency\n// ============================================================================\n\nfunction SendIcon() {\n return (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2.5}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"w-full h-full\"\n >\n <path d=\"M22 2 11 13\" />\n <path d=\"M22 2 15 22 11 13 2 9l20-7Z\" />\n </svg>\n )\n}\n\nfunction StopIcon() {\n return (\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\" className=\"w-full h-full\">\n <rect x=\"5\" y=\"5\" width=\"14\" height=\"14\" rx=\"2\" />\n </svg>\n )\n}\n\nexport {\n ChatInput,\n ChatInputField,\n ChatInputSubmit,\n chatInputVariants,\n}\n"],"mappings":";;;;;;AAEA,YAAY,WAAW;AACvB,SAAS,WAA8B;AAQvC,IAAM,kBAAkB;AAAA,EACtB,IAAS;AAAA,EACT,SAAS;AAAA,EACT,IAAS;AACX;AAGA,IAAM,mBAAmB;AAAA,EACvB,IAAS;AAAA,EACT,SAAS;AAAA,EACT,IAAS;AACX;AAGA,IAAM,gBAAgB;AAAA,EACpB,IAAS;AAAA,EACT,SAAS;AAAA,EACT,IAAS;AACX;AAGA,IAAM,kBAAkB;AAAA,EACtB,IAAO;AAAA,EACP,IAAO;AAAA,EACP,IAAO;AAAA,EACP,IAAO;AAAA,EACP,OAAO;AAAA,EACP,MAAO;AACT;AAGA,IAAM,uBAAwD;AAAA,EAC5D,IAAO;AAAA,EACP,IAAO;AAAA,EACP,IAAO;AAAA,EACP,IAAO;AAAA,EACP,OAAO;AAAA,EACP,MAAO;AACT;AAGA,IAAM,oBAAoB;AAAA,EACxB,IAAS;AAAA,EACT,SAAS;AAAA,EACT,IAAS;AACX;AAGA,IAAM,gBAAgB;AAAA,EACpB,IAAS;AAAA,EACT,SAAS;AAAA,EACT,IAAS;AACX;AAGA,IAAM,gBAAgB;AAAA,EACpB,IAAS;AAAA,EACT,SAAS;AAAA,EACT,IAAS;AACX;AAGA,IAAM,wBAAwB;AAAA,EAC5B,IAAS;AAAA,EACT,SAAS;AAAA,EACT,IAAS;AACX;AAGA,IAAM,yBAAyB;AAAA,EAC7B,IAAS;AAAA,EACT,SAAS;AAAA,EACT,IAAS;AACX;AAMA,IAAM,oBAAoB;AAAA,EACxB;AAAA,IACE;AAAA,IACA;AAAA,EACF,EAAE,KAAK,GAAG;AAAA,EACV;AAAA,IACE,UAAU;AAAA,MACR,SAAS;AAAA,QACP,SAAS;AAAA,UACP;AAAA,UACA;AAAA,UACA;AAAA,QACF,EAAE,KAAK,GAAG;AAAA,QACV,QAAQ;AAAA,UACN;AAAA,UACA;AAAA,QACF,EAAE,KAAK,GAAG;AAAA,MACZ;AAAA,MACA,QAAQ;AAAA,QACN,IAAO;AAAA,QACP,IAAO;AAAA,QACP,IAAO;AAAA,QACP,IAAO;AAAA,QACP,OAAO;AAAA,QACP,MAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,iBAAiB;AAAA,MACf,SAAS;AAAA,MACT,QAAS;AAAA,IACX;AAAA,EACF;AACF;AAkCA,IAAM,mBAAyB,oBAAqC;AAAA,EAClE,MAAgB;AAAA,EAChB,OAAgB;AAAA,EAChB,QAAgB;AAAA,EAChB,QAAgB;AAAA,EAChB,UAAgB;AAAA,EAChB,SAAgB;AAAA,EAChB,WAAgB;AAAA,EAChB,WAAgB;AAAA,EAChB,WAAgB;AAAA,EAChB,aAAgB,MAAM;AAAA,EAAC;AAAA,EACvB,eAAgB,MAAM;AAAA,EAAC;AAAA,EACvB,eAAgB,MAAM;AAAA,EAAC;AAAA,EACvB,eAAgB,MAAM;AAAA,EAAC;AAAA,EACvB,WAAgB,EAAE,SAAS,KAAK;AAAA,EAChC,eAAgB,MAAM;AAAA,EAAC;AACzB,CAAC;AA+CD,IAAM,YAAkB;AAAA,EACtB,CACE;AAAA,IACE;AAAA,IACA,UAAW;AAAA,IACX,SAAW;AAAA,IACX,OAAW;AAAA,IACX,QAAW;AAAA,IACX,SAAW;AAAA,IACX,WAAW;AAAA,IACX;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EACL,GACA,QACG;AACH,UAAM,CAAC,SAAY,UAAU,IAAa,eAAS,IAAI;AACvD,UAAM,CAAC,WAAY,YAAY,IAAW,eAAS,CAAC;AACpD,UAAM,CAAC,WAAY,YAAY,IAAW,eAAS,KAAK;AACxD,UAAM,CAAC,WAAY,YAAY,IAAW,eAA6B,MAAS;AAChF,UAAM,WAAiB,aAAmC,IAAI;AAE9D,UAAM,eAAqB,kBAAY,MAAM;AAC3C,YAAM,KAAK,SAAS;AACpB,UAAI,CAAC,MAAM,SAAU;AACrB,YAAM,QAAQ,GAAG,MAAM,KAAK;AAC5B,UAAI,CAAC,MAAO;AACZ,iBAAW,KAAK;AAGhB,SAAG,QAAQ;AACX,SAAG,MAAM,SAAS;AAClB,iBAAW,IAAI;AACf,mBAAa,CAAC;AAAA,IAChB,GAAG,CAAC,UAAU,QAAQ,CAAC;AAEvB,UAAM,eAAqB;AAAA,MACzB,OAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,aAAe;AAAA,QACf,eAAe;AAAA,QACf,eAAe;AAAA,QACf,eAAe;AAAA,QACf,WAAe;AAAA,QACf,eAAe;AAAA,MACjB;AAAA,MACA,CAAC,MAAM,OAAO,QAAQ,QAAQ,UAAU,SAAS,WAAW,WAAW,WAAW,YAAY;AAAA,IAChG;AAEA,UAAM,uBAA6B;AAAA,MACjC,CAAC,MAAwC;AAEvC,YAAI,CAAC,YAAY,CAAE,EAAE,OAAuB,QAAQ,QAAQ,GAAG;AAC7D,mBAAS,SAAS,MAAM;AAAA,QAC1B;AAAA,MACF;AAAA,MACA,CAAC,QAAQ;AAAA,IACX;AAEA,WACE,oCAAC,iBAAiB,UAAjB,EAA0B,OAAO,gBAChC;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,iBAAe,YAAY;AAAA,QAC3B,SAAS;AAAA,QACT,WAAW;AAAA,UACT,kBAAkB,EAAE,SAAS,OAAO,CAAC;AAAA,UACrC,WAAW,YAAY;AAAA,UACvB,YAAY;AAAA,UACZ;AAAA,QACF;AAAA,QACC,GAAG;AAAA;AAAA,MAEH;AAAA,IACH,CACF;AAAA,EAEJ;AACF;AACA,UAAU,cAAc;AAMxB,IAAM,iBAAuB;AAAA,EAC3B,CACE;AAAA,IACE;AAAA,IACA,UAAY;AAAA,IACZ,YAAY;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EACL,GACA,iBACG;AACH,UAAM,MAAY,iBAAW,gBAAgB;AAC7C,UAAM,cAAoB,aAAmC,IAAI;AACjE,UAAM,aAAa,YAAY,IAAI;AAGnC,IAAM,gBAAU,MAAM;AACpB,UAAI,cAAc,SAAS;AAC3B,UAAI,cAAc,SAAS;AAAA,IAE7B,GAAG,CAAC,WAAW,SAAS,CAAC;AAGzB,UAAM,SAAe;AAAA,MACnB,CAAC,OAAmC;AAClC,oBAAY,UAAU;AACtB,YAAI,UAAU,UAAU;AACxB,YAAI,OAAO,iBAAiB,YAAY;AACtC,uBAAa,EAAE;AAAA,QACjB,WAAW,cAAc;AACvB,UAAC,aAAoE,UAAU;AAAA,QACjF;AAAA,MACF;AAAA;AAAA,MAEA,CAAC,YAAY;AAAA,IACf;AAGA,UAAM,aAAmB,kBAAY,MAAM;AACzC,YAAM,KAAK,YAAY;AACvB,UAAI,CAAC,GAAI;AACT,SAAG,MAAM,SAAS;AAClB,YAAM,YAAY,UAAU,cAAc,IAAI,IAAI;AAClD,YAAM,YAAY,KAAK,IAAI,GAAG,cAAc,SAAS;AACrD,SAAG,MAAM,SAAS,GAAG,SAAS;AAC9B,SAAG,MAAM,YAAY,GAAG,eAAe,YAAY,SAAS;AAAA,IAC9D,GAAG,CAAC,IAAI,MAAM,OAAO,CAAC;AAEtB,UAAM,eAAqB;AAAA,MACzB,CAAC,MAA8C;AAC7C,cAAM,MAAM,EAAE,OAAO;AACrB,YAAI,YAAY,IAAI,KAAK,MAAM,EAAE;AACjC,YAAI,cAAc,IAAI,MAAM;AAC5B,mBAAW;AACX,mBAAW,CAAC;AAAA,MACd;AAAA,MACA,CAAC,KAAK,YAAY,QAAQ;AAAA,IAC5B;AAEA,UAAM,gBAAsB;AAAA,MAC1B,CAAC,MAAgD;AAE/C,YAAI,EAAE,QAAQ,WAAW,CAAC,EAAE,UAAU;AACpC,YAAE,eAAe;AACjB,cAAI,cAAc;AAAA,QACpB;AACA,oBAAY,CAAC;AAAA,MACf;AAAA,MACA,CAAC,KAAK,SAAS;AAAA,IACjB;AAEA,WACE,oCAAC,SAAI,WAAW,GAAG,kBAAkB,IAAI,WAAW,YAAY,gCAAgC,KAC9F;AAAA,MAAC;AAAA;AAAA,QACC,KAAK;AAAA,QACL,MAAM;AAAA,QACN;AAAA,QACA;AAAA,QACA,UAAU;AAAA,QACV,WAAW;AAAA,UACT;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA,IAAI,WAAW,WAAW,sBAAsB,IAAI,IAAI,IAAI,gBAAgB,IAAI,IAAI;AAAA,UACpF;AAAA,QACF;AAAA,QACA,UAAU;AAAA,QACV,WAAW;AAAA,QACV,GAAG;AAAA;AAAA,IACN,CACF;AAAA,EAEJ;AACF;AACA,eAAe,cAAc;AAM7B,IAAM,kBAAwB;AAAA,EAC5B,CACE;AAAA,IACE;AAAA,IACA,UAAe;AAAA,IACf;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EACL,GACA,QACG;AACH,UAAM,MAAY,iBAAW,gBAAgB;AAG7C,UAAM,cAAc,YAAY,IAAI,aAAc,CAAC,WAAW,IAAI;AAElE,UAAM,cAAoB;AAAA,MACxB,CAAC,MAA2C;AAC1C,YAAI,SAAS;AACX,mBAAS;AAAA,QACX,WAAW,CAAC,YAAY;AACtB,cAAI,cAAc;AAAA,QACpB;AACA,kBAAU,CAAC;AAAA,MACb;AAAA,MACA,CAAC,KAAK,YAAY,SAAS,QAAQ,OAAO;AAAA,IAC5C;AAEA,WACE,oCAAC,SAAI,WAAW,GAAG,+DAA+D,IAAI,WAAW,WAAW,uBAAuB,IAAI,IAAI,IAAI,iBAAiB,IAAI,IAAI,CAAC,KACtK,IAAI,aAAa,IAAI,aAAa,QACjC,oCAAC,UAAK,WAAW,GAAG,gCAAgC,cAAc,IAAI,IAAI,CAAC,KACxE,IAAI,WAAU,OAAI,IAAI,SACzB,GAEF;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,MAAK;AAAA,QACL,UAAU,cAAc,CAAC;AAAA,QACzB,cAAY,UAAU,oBAAoB;AAAA,QAC1C,WAAW;AAAA,UACT;AAAA,UACA,eAAe,qBAAqB,YAAY,IAAI,gBAAgB,IAAI,MAAM;AAAA,UAC9E;AAAA,UACA;AAAA,UACA,cAAc,IAAI,IAAI;AAAA;AAAA,UAEtB,WAAW,IAAI,UAAU,aAAa;AAAA,UACtC,WAAW,IAAI,UAAU,aAAa;AAAA;AAAA,UAEtC,CAAC,WAAW,CAAC,cAAc,IAAI,UAAU,aAAa;AAAA,YACpD;AAAA,YACA;AAAA,UACF;AAAA,UACA,CAAC,WAAW,CAAC,cAAc,IAAI,UAAU,aAAa;AAAA,YACpD;AAAA,YACA;AAAA,UACF;AAAA;AAAA,UAEA,CAAC,WAAW,cAAc;AAAA,UAC1B;AAAA,QACF;AAAA,QACA,SAAS;AAAA,QACR,GAAG;AAAA;AAAA,MAEJ;AAAA,QAAC;AAAA;AAAA,UACC,eAAY;AAAA,UACZ,WAAW,GAAG,oCAAoC,kBAAkB,IAAI,IAAI,CAAC;AAAA;AAAA,QAE5E,aAAa,UAAU,oCAAC,cAAS,IAAK,oCAAC,cAAS;AAAA,MACnD;AAAA,IACF,CACF;AAAA,EAEJ;AACF;AACA,gBAAgB,cAAc;AAM9B,SAAS,WAAW;AAClB,SACE;AAAA,IAAC;AAAA;AAAA,MACC,SAAQ;AAAA,MACR,MAAK;AAAA,MACL,QAAO;AAAA,MACP,aAAa;AAAA,MACb,eAAc;AAAA,MACd,gBAAe;AAAA,MACf,WAAU;AAAA;AAAA,IAEV,oCAAC,UAAK,GAAE,eAAc;AAAA,IACtB,oCAAC,UAAK,GAAE,+BAA8B;AAAA,EACxC;AAEJ;AAEA,SAAS,WAAW;AAClB,SACE,oCAAC,SAAI,SAAQ,aAAY,MAAK,gBAAe,WAAU,mBACrD,oCAAC,UAAK,GAAE,KAAI,GAAE,KAAI,OAAM,MAAK,QAAO,MAAK,IAAG,KAAI,CAClD;AAEJ;","names":[]}
@@ -1 +0,0 @@
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 } 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 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"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/ui/checkbox.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport * as CheckboxPrimitive from '@radix-ui/react-checkbox'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from '@/lib/utils'\nimport { useFieldContext } from './field'\n\n// Color maps for checked/indeterminate state\nconst checkboxColorMap = {\n default: 'data-[state=checked]:bg-foreground data-[state=checked]:border-foreground data-[state=checked]:text-background data-[state=indeterminate]:bg-foreground data-[state=indeterminate]:border-foreground data-[state=indeterminate]:text-background',\n primary: 'data-[state=checked]:bg-primary data-[state=checked]:border-primary data-[state=checked]:text-primary-foreground data-[state=indeterminate]:bg-primary data-[state=indeterminate]:border-primary data-[state=indeterminate]:text-primary-foreground',\n} as const\n\nexport type CheckboxColor = keyof typeof checkboxColorMap\n\n// Checkbox box variants\nconst checkboxVariants = cva(\n [\n 'peer relative shrink-0 border-border hover:border-border-strong transition-all duration-micro ease-out',\n 'focus-visible:focus-ring',\n 'disabled:cursor-not-allowed disabled:opacity-50',\n // Transparent hit area expansion via ::after\n \"after:absolute after:content-['']\",\n ].join(' '),\n {\n variants: {\n size: {\n sm: 'w-3.5 h-3.5 after:-inset-[5px]', // 14px box → 24px click\n default: 'w-4 h-4 after:-inset-2', // 16px box → 32px click\n lg: 'w-5 h-5 after:-inset-2', // 20px box → 36px click\n },\n radius: {\n none: 'rounded-none', // 0px — sharp square\n sm: 'rounded-sm', // 2px — default checkbox style\n md: 'rounded', // 4px — softer corners\n },\n weight: {\n thin: 'border', // 1px\n bold: 'border-2', // 2px\n },\n },\n defaultVariants: {\n size: 'default',\n radius: 'sm',\n weight: 'bold',\n },\n }\n)\n\n// Check icon sizes per checkbox size\nconst checkIconSizes = {\n sm: 'w-2.5 h-2.5', // 10px in 14px box\n default: 'w-3 h-3', // 12px in 16px box\n lg: 'icon-xs', // 14px in 20px box\n}\n\n// Label font sizes per checkbox size\nconst labelSizes = {\n sm: 'text-xs', // 12px\n default: 'text-md', // 14px\n lg: 'text-base', // 16px\n}\n\n// Gap between checkbox and label\nconst gapSizes = {\n sm: 'gap-1.5',\n default: 'gap-2',\n lg: 'gap-2.5',\n}\n\nexport interface CheckboxProps\n extends Omit<React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>, 'children'>,\n VariantProps<typeof checkboxVariants> {\n /** Checked state color */\n color?: CheckboxColor\n label?: string\n radius?: 'none' | 'sm' | 'md'\n}\n\nconst Checkbox = React.forwardRef<\n React.ElementRef<typeof CheckboxPrimitive.Root>,\n CheckboxProps\n>(({ className, size, radius, weight, color = 'default', label, disabled, id, ...props }, ref) => {\n const fieldContext = useFieldContext()\n const resolvedSize = size || 'default'\n const resolvedDisabled = disabled ?? fieldContext?.disabled\n const generatedId = React.useId()\n const checkboxId = id ?? fieldContext?.id ?? generatedId\n\n const checkbox = (\n <CheckboxPrimitive.Root\n ref={ref}\n id={checkboxId}\n disabled={resolvedDisabled}\n className={cn(\n checkboxVariants({ size, radius, weight }),\n checkboxColorMap[color],\n className\n )}\n {...props}\n >\n <CheckboxPrimitive.Indicator className=\"flex items-center justify-center animate-checkbox-enter\">\n <CheckIcon className={checkIconSizes[resolvedSize]} />\n </CheckboxPrimitive.Indicator>\n </CheckboxPrimitive.Root>\n )\n\n if (!label) return checkbox\n\n return (\n <div className={cn('group flex items-center', gapSizes[resolvedSize])}>\n <div className=\"flex items-center\">\n {checkbox}\n </div>\n <label\n htmlFor={checkboxId}\n className={cn(\n labelSizes[resolvedSize],\n 'text-text-muted cursor-pointer select-none transition-colors duration-micro',\n 'group-hover:text-foreground',\n resolvedDisabled && 'opacity-50 cursor-not-allowed'\n )}\n >\n {label}\n </label>\n </div>\n )\n})\nCheckbox.displayName = 'Checkbox'\n\n// Check icon — renders ✓ for checked, — for indeterminate\nfunction CheckIcon({ className }: { className?: string }) {\n return (\n <>\n {/* Check mark (shown when data-state=checked on parent Indicator) */}\n <svg\n className={cn(className, 'hidden [[data-state=checked]_&]:block')}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={3}\n aria-hidden=\"true\"\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M5 13l4 4L19 7\" />\n </svg>\n {/* Dash (shown when data-state=indeterminate on parent Indicator) */}\n <svg\n className={cn(className, 'hidden [[data-state=indeterminate]_&]:block')}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={3}\n aria-hidden=\"true\"\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M5 12h14\" />\n </svg>\n </>\n )\n}\n\nexport { Checkbox, checkboxVariants }\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
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'\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, ...props }, ref) => {\n const resolvedSize = size || 'default'\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 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":"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","names":[]}