@7onic-ui/react 0.3.8 → 0.3.10

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 (171) hide show
  1. package/README.md +2 -2
  2. package/dist/chart.js +1 -1
  3. package/dist/chart.js.map +1 -1
  4. package/dist/chart.mjs +4 -10
  5. package/dist/chart.mjs.map +1 -1
  6. package/dist/chunk-234NAXGV.mjs +252 -0
  7. package/dist/chunk-234NAXGV.mjs.map +1 -0
  8. package/dist/chunk-53MIUPSY.mjs +13 -0
  9. package/dist/chunk-53MIUPSY.mjs.map +1 -0
  10. package/dist/chunk-BN5BEA3V.mjs +195 -0
  11. package/dist/chunk-BN5BEA3V.mjs.map +1 -0
  12. package/dist/chunk-COW3B62M.mjs +214 -0
  13. package/dist/chunk-COW3B62M.mjs.map +1 -0
  14. package/dist/chunk-CTH6SN5Y.mjs +114 -0
  15. package/dist/chunk-CTH6SN5Y.mjs.map +1 -0
  16. package/dist/chunk-D3NTQNDW.mjs +440 -0
  17. package/dist/chunk-D3NTQNDW.mjs.map +1 -0
  18. package/dist/chunk-DDRYEJBJ.mjs +164 -0
  19. package/dist/chunk-DDRYEJBJ.mjs.map +1 -0
  20. package/dist/chunk-DJAEXCRU.mjs +190 -0
  21. package/dist/chunk-DJAEXCRU.mjs.map +1 -0
  22. package/dist/chunk-DRVHHEAY.mjs +145 -0
  23. package/dist/chunk-DRVHHEAY.mjs.map +1 -0
  24. package/dist/chunk-DTLNWOTR.mjs +482 -0
  25. package/dist/chunk-DTLNWOTR.mjs.map +1 -0
  26. package/dist/chunk-DYYQOHQR.mjs +214 -0
  27. package/dist/chunk-DYYQOHQR.mjs.map +1 -0
  28. package/dist/chunk-FHUAH6AJ.mjs +93 -0
  29. package/dist/chunk-FHUAH6AJ.mjs.map +1 -0
  30. package/dist/chunk-GD4YE5AE.mjs +209 -0
  31. package/dist/chunk-GD4YE5AE.mjs.map +1 -0
  32. package/dist/chunk-GRCJ35DX.mjs +144 -0
  33. package/dist/chunk-GRCJ35DX.mjs.map +1 -0
  34. package/dist/chunk-HHX4GABH.mjs +129 -0
  35. package/dist/chunk-HHX4GABH.mjs.map +1 -0
  36. package/dist/chunk-IPCIC2BI.mjs +148 -0
  37. package/dist/chunk-IPCIC2BI.mjs.map +1 -0
  38. package/dist/chunk-IY3R2VGB.mjs +272 -0
  39. package/dist/chunk-IY3R2VGB.mjs.map +1 -0
  40. package/dist/chunk-JCJEVXER.mjs +170 -0
  41. package/dist/chunk-JCJEVXER.mjs.map +1 -0
  42. package/dist/chunk-KBPYAMGS.mjs +157 -0
  43. package/dist/chunk-KBPYAMGS.mjs.map +1 -0
  44. package/dist/chunk-LJJ6K4IU.mjs +318 -0
  45. package/dist/chunk-LJJ6K4IU.mjs.map +1 -0
  46. package/dist/chunk-MRUVGHGP.mjs +375 -0
  47. package/dist/chunk-MRUVGHGP.mjs.map +1 -0
  48. package/dist/chunk-N4K2BDGM.mjs +153 -0
  49. package/dist/chunk-N4K2BDGM.mjs.map +1 -0
  50. package/dist/chunk-NWFMJWGX.mjs +165 -0
  51. package/dist/chunk-NWFMJWGX.mjs.map +1 -0
  52. package/dist/chunk-PTAPPOKU.mjs +117 -0
  53. package/dist/chunk-PTAPPOKU.mjs.map +1 -0
  54. package/dist/chunk-PVTBM7V7.mjs +316 -0
  55. package/dist/chunk-PVTBM7V7.mjs.map +1 -0
  56. package/dist/chunk-Q5WVLK2L.mjs +77 -0
  57. package/dist/chunk-Q5WVLK2L.mjs.map +1 -0
  58. package/dist/chunk-RKSB2N5L.mjs +206 -0
  59. package/dist/chunk-RKSB2N5L.mjs.map +1 -0
  60. package/dist/chunk-S4DGVKBK.mjs +151 -0
  61. package/dist/chunk-S4DGVKBK.mjs.map +1 -0
  62. package/dist/chunk-S4T4PU7F.mjs +114 -0
  63. package/dist/chunk-S4T4PU7F.mjs.map +1 -0
  64. package/dist/chunk-SZPZOGPC.mjs +394 -0
  65. package/dist/chunk-SZPZOGPC.mjs.map +1 -0
  66. package/dist/chunk-T546XBQG.mjs +443 -0
  67. package/dist/chunk-T546XBQG.mjs.map +1 -0
  68. package/dist/chunk-UWTT5AE6.mjs +145 -0
  69. package/dist/chunk-UWTT5AE6.mjs.map +1 -0
  70. package/dist/chunk-V5UFWYFI.mjs +255 -0
  71. package/dist/chunk-V5UFWYFI.mjs.map +1 -0
  72. package/dist/chunk-VUPGBB5X.mjs +150 -0
  73. package/dist/chunk-VUPGBB5X.mjs.map +1 -0
  74. package/dist/chunk-W6YNEU53.mjs +175 -0
  75. package/dist/chunk-W6YNEU53.mjs.map +1 -0
  76. package/dist/chunk-WWSN5YME.mjs +222 -0
  77. package/dist/chunk-WWSN5YME.mjs.map +1 -0
  78. package/dist/chunk-XK52LYR4.mjs +182 -0
  79. package/dist/chunk-XK52LYR4.mjs.map +1 -0
  80. package/dist/chunk-YIAH6KHV.mjs +164 -0
  81. package/dist/chunk-YIAH6KHV.mjs.map +1 -0
  82. package/dist/chunk-Z6JWWCNL.mjs +108 -0
  83. package/dist/chunk-Z6JWWCNL.mjs.map +1 -0
  84. package/dist/chunk-ZDRUTJ4T.mjs +119 -0
  85. package/dist/chunk-ZDRUTJ4T.mjs.map +1 -0
  86. package/dist/components/accordion.mjs +19 -0
  87. package/dist/components/accordion.mjs.map +1 -0
  88. package/dist/components/alert.mjs +15 -0
  89. package/dist/components/alert.mjs.map +1 -0
  90. package/dist/components/avatar.mjs +23 -0
  91. package/dist/components/avatar.mjs.map +1 -0
  92. package/dist/components/badge.mjs +11 -0
  93. package/dist/components/badge.mjs.map +1 -0
  94. package/dist/components/breadcrumb.mjs +23 -0
  95. package/dist/components/breadcrumb.mjs.map +1 -0
  96. package/dist/components/button-group.mjs +11 -0
  97. package/dist/components/button-group.mjs.map +1 -0
  98. package/dist/components/button.mjs +12 -0
  99. package/dist/components/button.mjs.map +1 -0
  100. package/dist/components/card.mjs +25 -0
  101. package/dist/components/card.mjs.map +1 -0
  102. package/dist/components/chat-input.mjs +15 -0
  103. package/dist/components/chat-input.mjs.map +1 -0
  104. package/dist/components/chat-message.mjs +17 -0
  105. package/dist/components/chat-message.mjs.map +1 -0
  106. package/dist/components/checkbox.mjs +12 -0
  107. package/dist/components/checkbox.mjs.map +1 -0
  108. package/dist/components/divider.mjs +11 -0
  109. package/dist/components/divider.mjs.map +1 -0
  110. package/dist/components/drawer.mjs +33 -0
  111. package/dist/components/drawer.mjs.map +1 -0
  112. package/dist/components/dropdown.mjs +35 -0
  113. package/dist/components/dropdown.mjs.map +1 -0
  114. package/dist/components/field.mjs +17 -0
  115. package/dist/components/field.mjs.map +1 -0
  116. package/dist/components/icon-button.mjs +12 -0
  117. package/dist/components/icon-button.mjs.map +1 -0
  118. package/dist/components/input.mjs +12 -0
  119. package/dist/components/input.mjs.map +1 -0
  120. package/dist/components/metric-card.mjs +23 -0
  121. package/dist/components/metric-card.mjs.map +1 -0
  122. package/dist/components/modal.mjs +57 -0
  123. package/dist/components/modal.mjs.map +1 -0
  124. package/dist/components/navigation-menu.mjs +27 -0
  125. package/dist/components/navigation-menu.mjs.map +1 -0
  126. package/dist/components/pagination.mjs +33 -0
  127. package/dist/components/pagination.mjs.map +1 -0
  128. package/dist/components/popover.mjs +23 -0
  129. package/dist/components/popover.mjs.map +1 -0
  130. package/dist/components/progress.mjs +11 -0
  131. package/dist/components/progress.mjs.map +1 -0
  132. package/dist/components/quick-reply.mjs +15 -0
  133. package/dist/components/quick-reply.mjs.map +1 -0
  134. package/dist/components/radio-group.mjs +16 -0
  135. package/dist/components/radio-group.mjs.map +1 -0
  136. package/dist/components/segmented.mjs +15 -0
  137. package/dist/components/segmented.mjs.map +1 -0
  138. package/dist/components/select.mjs +23 -0
  139. package/dist/components/select.mjs.map +1 -0
  140. package/dist/components/skeleton.mjs +11 -0
  141. package/dist/components/skeleton.mjs.map +1 -0
  142. package/dist/components/slider.mjs +11 -0
  143. package/dist/components/slider.mjs.map +1 -0
  144. package/dist/components/spinner.mjs +11 -0
  145. package/dist/components/spinner.mjs.map +1 -0
  146. package/dist/components/switch.mjs +12 -0
  147. package/dist/components/switch.mjs.map +1 -0
  148. package/dist/components/table.mjs +23 -0
  149. package/dist/components/table.mjs.map +1 -0
  150. package/dist/components/tabs.mjs +19 -0
  151. package/dist/components/tabs.mjs.map +1 -0
  152. package/dist/components/textarea.mjs +12 -0
  153. package/dist/components/textarea.mjs.map +1 -0
  154. package/dist/components/toast.mjs +13 -0
  155. package/dist/components/toast.mjs.map +1 -0
  156. package/dist/components/toggle-group.mjs +15 -0
  157. package/dist/components/toggle-group.mjs.map +1 -0
  158. package/dist/components/toggle.mjs +11 -0
  159. package/dist/components/toggle.mjs.map +1 -0
  160. package/dist/components/tooltip.mjs +21 -0
  161. package/dist/components/tooltip.mjs.map +1 -0
  162. package/dist/components/typing-indicator.mjs +11 -0
  163. package/dist/components/typing-indicator.mjs.map +1 -0
  164. package/dist/index.js +22 -7
  165. package/dist/index.js.map +1 -1
  166. package/dist/index.mjs +296 -7521
  167. package/dist/index.mjs.map +1 -1
  168. package/llms.txt +29 -25
  169. package/package.json +4 -3
  170. package/dist/chart.d.mts +0 -147
  171. package/dist/index.d.mts +0 -1535
@@ -0,0 +1,77 @@
1
+ "use client";
2
+ import {
3
+ cn
4
+ } from "./chunk-53MIUPSY.mjs";
5
+
6
+ // src/components/ui/button-group.tsx
7
+ import * as React from "react";
8
+ var ButtonGroupContext = React.createContext(null);
9
+ function useButtonGroup() {
10
+ return React.useContext(ButtonGroupContext);
11
+ }
12
+ var ButtonGroup = React.forwardRef(
13
+ ({
14
+ className,
15
+ orientation = "horizontal",
16
+ attached = true,
17
+ variant,
18
+ size,
19
+ radius,
20
+ fontWeight,
21
+ disabled,
22
+ children,
23
+ ...props
24
+ }, ref) => {
25
+ const contextValue = React.useMemo(() => ({
26
+ variant,
27
+ size,
28
+ radius,
29
+ fontWeight,
30
+ disabled
31
+ }), [variant, size, radius, fontWeight, disabled]);
32
+ return /* @__PURE__ */ React.createElement(ButtonGroupContext.Provider, { value: contextValue }, /* @__PURE__ */ React.createElement(
33
+ "div",
34
+ {
35
+ ref,
36
+ role: "group",
37
+ className: cn(
38
+ "inline-flex",
39
+ orientation === "vertical" ? "flex-col" : "flex-row",
40
+ // Attached mode: use negative margin to overlap borders, raise z-index on hover/focus
41
+ attached && orientation === "horizontal" && [
42
+ "[&>*:not(:first-child)]:rounded-l-none",
43
+ "[&>*:not(:last-child)]:rounded-r-none",
44
+ "[&>*:not(:first-child)]:-ml-px",
45
+ "[&>*]:relative",
46
+ "[&>*:hover]:z-10",
47
+ "[&>*:focus-visible]:z-10",
48
+ "[&>*:active]:scale-none",
49
+ "[&>*:hover]:border-border"
50
+ ],
51
+ attached && orientation === "vertical" && [
52
+ "[&>*:not(:first-child)]:rounded-t-none",
53
+ "[&>*:not(:last-child)]:rounded-b-none",
54
+ "[&>*:not(:first-child)]:-mt-px",
55
+ "[&>*]:relative",
56
+ "[&>*]:w-full",
57
+ "[&>*:hover]:z-10",
58
+ "[&>*:focus-visible]:z-10",
59
+ "[&>*:active]:scale-none",
60
+ "[&>*:hover]:border-border"
61
+ ],
62
+ !attached && "gap-2",
63
+ className
64
+ ),
65
+ ...props
66
+ },
67
+ children
68
+ ));
69
+ }
70
+ );
71
+ ButtonGroup.displayName = "ButtonGroup";
72
+
73
+ export {
74
+ useButtonGroup,
75
+ ButtonGroup
76
+ };
77
+ //# sourceMappingURL=chunk-Q5WVLK2L.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/ui/button-group.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { cn } from '@/lib/utils'\n\n// ButtonGroup Context\ntype ButtonGroupContextValue = {\n variant?: 'outline' | 'ghost'\n size?: 'xs' | 'sm' | 'md' | 'default' | 'lg'\n radius?: 'none' | 'sm' | 'base' | 'default' | 'lg' | 'xl' | '2xl' | '3xl' | 'full'\n fontWeight?: 'normal' | 'semibold'\n disabled?: boolean\n}\n\nconst ButtonGroupContext = React.createContext<ButtonGroupContextValue | null>(null)\n\nexport function useButtonGroup() {\n return React.useContext(ButtonGroupContext)\n}\n\nexport interface ButtonGroupProps extends React.HTMLAttributes<HTMLDivElement> {\n orientation?: 'horizontal' | 'vertical'\n attached?: boolean\n variant?: 'outline' | 'ghost'\n size?: 'xs' | 'sm' | 'md' | 'default' | 'lg'\n radius?: 'none' | 'sm' | 'base' | 'default' | 'lg' | 'xl' | '2xl' | '3xl' | 'full'\n fontWeight?: 'normal' | 'semibold'\n disabled?: boolean\n}\n\nconst ButtonGroup = React.forwardRef<HTMLDivElement, ButtonGroupProps>(\n ({\n className,\n orientation = 'horizontal',\n attached = true,\n variant,\n size,\n radius,\n fontWeight,\n disabled,\n children,\n ...props\n }, ref) => {\n const contextValue = React.useMemo(() => ({\n variant,\n size,\n radius,\n fontWeight,\n disabled,\n }), [variant, size, radius, fontWeight, disabled])\n\n return (\n <ButtonGroupContext.Provider value={contextValue}>\n <div\n ref={ref}\n role=\"group\"\n className={cn(\n 'inline-flex',\n orientation === 'vertical' ? 'flex-col' : 'flex-row',\n // Attached mode: use negative margin to overlap borders, raise z-index on hover/focus\n attached && orientation === 'horizontal' && [\n '[&>*:not(:first-child)]:rounded-l-none',\n '[&>*:not(:last-child)]:rounded-r-none',\n '[&>*:not(:first-child)]:-ml-px',\n '[&>*]:relative',\n '[&>*:hover]:z-10',\n '[&>*:focus-visible]:z-10',\n '[&>*:active]:scale-none',\n '[&>*:hover]:border-border',\n ],\n attached && orientation === 'vertical' && [\n '[&>*:not(:first-child)]:rounded-t-none',\n '[&>*:not(:last-child)]:rounded-b-none',\n '[&>*:not(:first-child)]:-mt-px',\n '[&>*]:relative',\n '[&>*]:w-full',\n '[&>*:hover]:z-10',\n '[&>*:focus-visible]:z-10',\n '[&>*:active]:scale-none',\n '[&>*:hover]:border-border',\n ],\n !attached && 'gap-2',\n className\n )}\n {...props}\n >\n {children}\n </div>\n </ButtonGroupContext.Provider>\n )\n }\n)\nButtonGroup.displayName = 'ButtonGroup'\n\nexport { ButtonGroup }\n"],"mappings":";;;;;;AAEA,YAAY,WAAW;AAYvB,IAAM,qBAA2B,oBAA8C,IAAI;AAE5E,SAAS,iBAAiB;AAC/B,SAAa,iBAAW,kBAAkB;AAC5C;AAYA,IAAM,cAAoB;AAAA,EACxB,CAAC;AAAA,IACC;AAAA,IACA,cAAc;AAAA,IACd,WAAW;AAAA,IACX;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EACL,GAAG,QAAQ;AACT,UAAM,eAAqB,cAAQ,OAAO;AAAA,MACxC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,IAAI,CAAC,SAAS,MAAM,QAAQ,YAAY,QAAQ,CAAC;AAEjD,WACE,oCAAC,mBAAmB,UAAnB,EAA4B,OAAO,gBAClC;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,MAAK;AAAA,QACL,WAAW;AAAA,UACT;AAAA,UACA,gBAAgB,aAAa,aAAa;AAAA;AAAA,UAE1C,YAAY,gBAAgB,gBAAgB;AAAA,YAC1C;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAAA,UACA,YAAY,gBAAgB,cAAc;AAAA,YACxC;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAAA,UACA,CAAC,YAAY;AAAA,UACb;AAAA,QACF;AAAA,QACC,GAAG;AAAA;AAAA,MAEH;AAAA,IACH,CACF;AAAA,EAEJ;AACF;AACA,YAAY,cAAc;","names":[]}
@@ -0,0 +1,206 @@
1
+ "use client";
2
+ import {
3
+ cn
4
+ } from "./chunk-53MIUPSY.mjs";
5
+
6
+ // src/components/ui/segmented.tsx
7
+ import * as React from "react";
8
+ import * as RadioGroupPrimitive from "@radix-ui/react-radio-group";
9
+ import { cva } from "class-variance-authority";
10
+ var SegmentedContext = React.createContext({});
11
+ var useSegmentedContext = () => React.useContext(SegmentedContext);
12
+ var segmentedVariants = cva(
13
+ "inline-flex items-center text-text-subtle",
14
+ {
15
+ variants: {
16
+ variant: {
17
+ default: "bg-background-muted gap-1",
18
+ outline: "bg-background border border-border gap-1",
19
+ underline: "bg-transparent border-b border-border gap-0",
20
+ ghost: "bg-transparent gap-1"
21
+ },
22
+ size: {
23
+ sm: "h-8",
24
+ // 32px height
25
+ md: "h-9",
26
+ // 36px height
27
+ default: "h-10",
28
+ // 40px height
29
+ lg: "h-12"
30
+ // 48px height
31
+ },
32
+ radius: {
33
+ none: "rounded-none",
34
+ sm: "rounded-sm",
35
+ base: "rounded",
36
+ default: "rounded-md",
37
+ lg: "rounded-lg",
38
+ xl: "rounded-xl",
39
+ "2xl": "rounded-2xl",
40
+ "3xl": "rounded-3xl",
41
+ full: "rounded-full"
42
+ },
43
+ fontWeight: {
44
+ normal: "[&>*]:font-normal",
45
+ semibold: "[&>*]:font-semibold"
46
+ }
47
+ },
48
+ compoundVariants: [
49
+ // Padding for default/outline/ghost variants
50
+ { variant: "default", className: "p-1" },
51
+ { variant: "outline", className: "p-1" },
52
+ { variant: "ghost", className: "p-1" },
53
+ // Underline has no padding
54
+ { variant: "underline", className: "p-0" }
55
+ ],
56
+ defaultVariants: {
57
+ variant: "default",
58
+ size: "default",
59
+ radius: "default",
60
+ fontWeight: "normal"
61
+ }
62
+ }
63
+ );
64
+ var segmentedItemVariants = cva(
65
+ [
66
+ "inline-flex items-center justify-center whitespace-nowrap h-full",
67
+ "transition-all duration-micro ease-out",
68
+ "focus-visible:focus-ring",
69
+ "disabled:pointer-events-none disabled:opacity-50"
70
+ ].join(" "),
71
+ {
72
+ variants: {
73
+ variant: {
74
+ // Default: light background when selected, text emphasis on hover
75
+ default: [
76
+ "hover:text-foreground",
77
+ "data-[state=checked]:bg-background data-[state=checked]:text-foreground",
78
+ "data-[state=checked]:shadow-sm"
79
+ ].join(" "),
80
+ // Outline: gray background when selected
81
+ outline: [
82
+ "data-[state=checked]:bg-background-muted data-[state=checked]:text-foreground",
83
+ "hover:text-foreground hover:bg-background-muted"
84
+ ].join(" "),
85
+ // Underline: bottom border indicator (Stripe/GitHub style)
86
+ underline: [
87
+ "border-b-2 border-transparent -mb-px",
88
+ "hover:text-foreground hover:border-border",
89
+ "data-[state=checked]:text-foreground data-[state=checked]:border-foreground"
90
+ ].join(" "),
91
+ // Ghost: pill background only on selected (Notion/Figma style)
92
+ ghost: [
93
+ "hover:text-foreground hover:bg-background-muted",
94
+ "data-[state=checked]:bg-background-muted data-[state=checked]:text-foreground"
95
+ ].join(" ")
96
+ },
97
+ size: {
98
+ sm: "text-xs",
99
+ // 12px
100
+ md: "text-sm",
101
+ // 13px
102
+ default: "text-sm",
103
+ // 13px
104
+ lg: "text-md"
105
+ // 14px
106
+ },
107
+ radius: {
108
+ none: "rounded-none",
109
+ sm: "rounded-sm",
110
+ base: "rounded",
111
+ default: "rounded-md",
112
+ lg: "rounded-md",
113
+ xl: "rounded-lg",
114
+ "2xl": "rounded-xl",
115
+ "3xl": "rounded-2xl",
116
+ full: "rounded-full"
117
+ },
118
+ // Content type determines padding and aspect ratio
119
+ contentType: {
120
+ // Icon only: square aspect ratio like IconButton
121
+ icon: "aspect-square",
122
+ // Icon + text: rectangular (gap is set via compoundVariants)
123
+ "icon-text": "",
124
+ // Text only: standard button padding
125
+ text: ""
126
+ }
127
+ },
128
+ compoundVariants: [
129
+ // Icon + text - same padding rules as Button/Toggle
130
+ { contentType: "icon-text", size: "sm", className: "px-3 gap-2" },
131
+ // 12px padding, 8px gap
132
+ { contentType: "icon-text", size: "md", className: "px-3.5 gap-2" },
133
+ // 14px padding, 8px gap
134
+ { contentType: "icon-text", size: "default", className: "px-4 gap-2" },
135
+ // 16px padding, 8px gap
136
+ { contentType: "icon-text", size: "lg", className: "px-6 gap-2" },
137
+ // 24px padding, 8px gap
138
+ // Text only - same padding rules as Button/Toggle
139
+ { contentType: "text", size: "sm", className: "px-3.5" },
140
+ // 14px
141
+ { contentType: "text", size: "md", className: "px-3.5" },
142
+ // 14px
143
+ { contentType: "text", size: "default", className: "px-4" },
144
+ // 16px
145
+ { contentType: "text", size: "lg", className: "px-6" },
146
+ // 24px
147
+ // Underline variant has no rounded corners
148
+ { variant: "underline", className: "rounded-none" }
149
+ ],
150
+ defaultVariants: {
151
+ variant: "default",
152
+ size: "default",
153
+ radius: "default",
154
+ contentType: "text"
155
+ }
156
+ }
157
+ );
158
+ var Segmented = React.forwardRef(({ className, variant, size, radius, fontWeight, ...props }, ref) => {
159
+ const resolvedFontWeight = fontWeight ?? "normal";
160
+ return /* @__PURE__ */ React.createElement(SegmentedContext.Provider, { value: { variant: variant || "default", size: size || "default", radius: radius || "default" } }, /* @__PURE__ */ React.createElement(
161
+ RadioGroupPrimitive.Root,
162
+ {
163
+ className: cn(segmentedVariants({ variant, size, radius, fontWeight: resolvedFontWeight }), className),
164
+ ...props,
165
+ ref
166
+ }
167
+ ));
168
+ });
169
+ Segmented.displayName = "Segmented";
170
+ var iconSizeClasses = {
171
+ sm: "[&>svg]:icon-xs",
172
+ // 14px
173
+ md: "[&>svg]:icon-sm",
174
+ // 16px
175
+ default: "[&>svg]:icon-sm",
176
+ // 16px
177
+ lg: "[&>svg]:icon-sm"
178
+ // 16px
179
+ };
180
+ var SegmentedItem = React.forwardRef(({ className, children, size, radius, contentType, ...props }, ref) => {
181
+ const { variant, size: contextSize, radius: contextRadius } = useSegmentedContext();
182
+ const resolvedSize = size || contextSize || "default";
183
+ const resolvedRadius = radius || contextRadius || "default";
184
+ return /* @__PURE__ */ React.createElement(
185
+ RadioGroupPrimitive.Item,
186
+ {
187
+ ref,
188
+ className: cn(
189
+ segmentedItemVariants({ variant, size: resolvedSize, radius: resolvedRadius, contentType }),
190
+ iconSizeClasses[resolvedSize],
191
+ className
192
+ ),
193
+ ...props
194
+ },
195
+ children
196
+ );
197
+ });
198
+ SegmentedItem.displayName = "SegmentedItem";
199
+
200
+ export {
201
+ segmentedVariants,
202
+ segmentedItemVariants,
203
+ Segmented,
204
+ SegmentedItem
205
+ };
206
+ //# sourceMappingURL=chunk-RKSB2N5L.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/ui/segmented.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport * as RadioGroupPrimitive from '@radix-ui/react-radio-group'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from '@/lib/utils'\n\n// Context to pass variant and size from Segmented to SegmentedItem\ntype SegmentedContextValue = {\n variant?: 'default' | 'outline' | 'underline' | 'ghost'\n size?: 'sm' | 'md' | 'default' | 'lg'\n radius?: 'none' | 'sm' | 'base' | 'default' | 'lg' | 'xl' | '2xl' | '3xl' | 'full'\n}\nconst SegmentedContext = React.createContext<SegmentedContextValue>({})\nconst useSegmentedContext = () => React.useContext(SegmentedContext)\n\nconst segmentedVariants = cva(\n 'inline-flex items-center text-text-subtle',\n {\n variants: {\n variant: {\n default: 'bg-background-muted gap-1',\n outline: 'bg-background border border-border gap-1',\n underline: 'bg-transparent border-b border-border gap-0',\n ghost: 'bg-transparent gap-1',\n },\n size: {\n sm: 'h-8', // 32px height\n md: 'h-9', // 36px height\n default: 'h-10', // 40px height\n lg: 'h-12', // 48px height\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-full',\n },\n fontWeight: {\n normal: '[&>*]:font-normal',\n semibold: '[&>*]:font-semibold',\n },\n },\n compoundVariants: [\n // Padding for default/outline/ghost variants\n { variant: 'default', className: 'p-1' },\n { variant: 'outline', className: 'p-1' },\n { variant: 'ghost', className: 'p-1' },\n // Underline has no padding\n { variant: 'underline', className: 'p-0' },\n ],\n defaultVariants: {\n variant: 'default',\n size: 'default',\n radius: 'default',\n fontWeight: 'normal',\n },\n }\n)\n\nconst segmentedItemVariants = cva(\n [\n 'inline-flex items-center justify-center whitespace-nowrap h-full',\n 'transition-all duration-micro ease-out',\n 'focus-visible:focus-ring',\n 'disabled:pointer-events-none disabled:opacity-50',\n ].join(' '),\n {\n variants: {\n variant: {\n // Default: light background when selected, text emphasis on hover\n default: [\n 'hover:text-foreground',\n 'data-[state=checked]:bg-background data-[state=checked]:text-foreground',\n 'data-[state=checked]:shadow-sm',\n ].join(' '),\n // Outline: gray background when selected\n outline: [\n 'data-[state=checked]:bg-background-muted data-[state=checked]:text-foreground',\n 'hover:text-foreground hover:bg-background-muted',\n ].join(' '),\n // Underline: bottom border indicator (Stripe/GitHub style)\n underline: [\n 'border-b-2 border-transparent -mb-px',\n 'hover:text-foreground hover:border-border',\n 'data-[state=checked]:text-foreground data-[state=checked]:border-foreground',\n ].join(' '),\n // Ghost: pill background only on selected (Notion/Figma style)\n ghost: [\n 'hover:text-foreground hover:bg-background-muted',\n 'data-[state=checked]:bg-background-muted data-[state=checked]:text-foreground',\n ].join(' '),\n },\n size: {\n sm: 'text-xs', // 12px\n md: 'text-sm', // 13px\n default: 'text-sm', // 13px\n lg: 'text-md', // 14px\n },\n radius: {\n none: 'rounded-none',\n sm: 'rounded-sm',\n base: 'rounded',\n default: 'rounded-md',\n lg: 'rounded-md',\n xl: 'rounded-lg',\n '2xl': 'rounded-xl',\n '3xl': 'rounded-2xl',\n full: 'rounded-full',\n },\n // Content type determines padding and aspect ratio\n contentType: {\n // Icon only: square aspect ratio like IconButton\n icon: 'aspect-square',\n // Icon + text: rectangular (gap is set via compoundVariants)\n 'icon-text': '',\n // Text only: standard button padding\n text: '',\n },\n },\n compoundVariants: [\n // Icon + text - same padding rules as Button/Toggle\n { contentType: 'icon-text', size: 'sm', className: 'px-3 gap-2' }, // 12px padding, 8px gap\n { contentType: 'icon-text', size: 'md', className: 'px-3.5 gap-2' }, // 14px padding, 8px gap\n { contentType: 'icon-text', size: 'default', className: 'px-4 gap-2' }, // 16px padding, 8px gap\n { contentType: 'icon-text', size: 'lg', className: 'px-6 gap-2' }, // 24px padding, 8px gap\n // Text only - same padding rules as Button/Toggle\n { contentType: 'text', size: 'sm', className: 'px-3.5' }, // 14px\n { contentType: 'text', size: 'md', className: 'px-3.5' }, // 14px\n { contentType: 'text', size: 'default', className: 'px-4' }, // 16px\n { contentType: 'text', size: 'lg', className: 'px-6' }, // 24px\n // Underline variant has no rounded corners\n { variant: 'underline', className: 'rounded-none' },\n ],\n defaultVariants: {\n variant: 'default',\n size: 'default',\n radius: 'default',\n contentType: 'text',\n },\n }\n)\n\nexport interface SegmentedProps\n extends React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Root>,\n VariantProps<typeof segmentedVariants> {}\n\nconst Segmented = React.forwardRef<\n React.ElementRef<typeof RadioGroupPrimitive.Root>,\n SegmentedProps\n>(({ className, variant, size, radius, fontWeight, ...props }, ref) => {\n // All variants default to normal font weight\n const resolvedFontWeight = fontWeight ?? 'normal'\n\n return (\n <SegmentedContext.Provider value={{ variant: variant || 'default', size: size || 'default', radius: radius || 'default' }}>\n <RadioGroupPrimitive.Root\n className={cn(segmentedVariants({ variant, size, radius, fontWeight: resolvedFontWeight }), className)}\n {...props}\n ref={ref}\n />\n </SegmentedContext.Provider>\n )\n})\nSegmented.displayName = 'Segmented'\n\n// Icon size for segmented control (4-step scale, Icon+Text mode)\n// sm: 14px, md~default~lg: 16px\nconst iconSizeClasses = {\n sm: '[&>svg]:icon-xs', // 14px\n md: '[&>svg]:icon-sm', // 16px\n default: '[&>svg]:icon-sm', // 16px\n lg: '[&>svg]:icon-sm', // 16px\n}\n\nexport interface SegmentedItemProps\n extends React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Item>,\n Omit<VariantProps<typeof segmentedItemVariants>, 'variant'> {}\n\nconst SegmentedItem = React.forwardRef<\n React.ElementRef<typeof RadioGroupPrimitive.Item>,\n SegmentedItemProps\n>(({ className, children, size, radius, contentType, ...props }, ref) => {\n const { variant, size: contextSize, radius: contextRadius } = useSegmentedContext()\n const resolvedSize = size || contextSize || 'default'\n const resolvedRadius = radius || contextRadius || 'default'\n\n return (\n <RadioGroupPrimitive.Item\n ref={ref}\n className={cn(\n segmentedItemVariants({ variant, size: resolvedSize, radius: resolvedRadius, contentType }),\n iconSizeClasses[resolvedSize],\n className\n )}\n {...props}\n >\n {children}\n </RadioGroupPrimitive.Item>\n )\n})\nSegmentedItem.displayName = 'SegmentedItem'\n\nexport { Segmented, SegmentedItem, segmentedVariants, segmentedItemVariants }\n"],"mappings":"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","names":[]}
@@ -0,0 +1,151 @@
1
+ "use client";
2
+ import {
3
+ cn
4
+ } from "./chunk-53MIUPSY.mjs";
5
+
6
+ // src/components/ui/toggle-group.tsx
7
+ import * as React from "react";
8
+ import * as ToggleGroupPrimitive from "@radix-ui/react-toggle-group";
9
+ import { cva } from "class-variance-authority";
10
+ var toggleGroupVariants = cva(
11
+ "inline-flex items-center justify-center",
12
+ {
13
+ variants: {
14
+ orientation: {
15
+ horizontal: "flex-row",
16
+ vertical: "flex-col"
17
+ }
18
+ },
19
+ defaultVariants: {
20
+ orientation: "horizontal"
21
+ }
22
+ }
23
+ );
24
+ var toggleGroupItemVariants = cva(
25
+ "inline-flex items-center justify-center text-sm text-text-muted transition-all duration-micro focus-visible:focus-ring disabled:pointer-events-none disabled:opacity-50",
26
+ {
27
+ variants: {
28
+ variant: {
29
+ default: "bg-transparent hover:bg-background-muted hover:text-foreground data-[state=on]:bg-background-muted data-[state=on]:text-foreground",
30
+ outline: "border border-border bg-transparent hover:bg-background-muted hover:text-foreground data-[state=on]:bg-background-muted data-[state=on]:text-foreground"
31
+ },
32
+ fontWeight: {
33
+ normal: "font-normal",
34
+ semibold: "font-semibold"
35
+ },
36
+ size: {
37
+ xs: "h-7 px-2.5 text-xs gap-1",
38
+ // 28px height, 10px paddingX, 12px font
39
+ sm: "h-8 px-3 text-sm gap-2",
40
+ // 32px height, 12px paddingX, 13px font
41
+ md: "h-9 px-3.5 text-md gap-2",
42
+ // 36px height, 14px paddingX, 14px font
43
+ default: "h-10 px-4 text-md gap-2",
44
+ // 40px height, 16px paddingX, 14px font
45
+ lg: "h-12 px-6 text-base gap-2"
46
+ // 48px height, 24px paddingX, 16px font
47
+ },
48
+ radius: {
49
+ none: "rounded-none",
50
+ sm: "rounded-sm",
51
+ base: "rounded",
52
+ default: "rounded-md",
53
+ lg: "rounded-lg",
54
+ xl: "rounded-xl",
55
+ "2xl": "rounded-2xl",
56
+ "3xl": "rounded-3xl",
57
+ full: "rounded-full"
58
+ }
59
+ },
60
+ defaultVariants: {
61
+ variant: "default",
62
+ size: "default",
63
+ radius: "default",
64
+ fontWeight: "normal"
65
+ }
66
+ }
67
+ );
68
+ var ToggleGroupContext = React.createContext({
69
+ variant: "default",
70
+ size: "default",
71
+ radius: "default",
72
+ fontWeight: "normal"
73
+ });
74
+ var ToggleGroup = React.forwardRef(({ className, orientation, variant, size, radius, fontWeight, children, ...props }, ref) => /* @__PURE__ */ React.createElement(
75
+ ToggleGroupPrimitive.Root,
76
+ {
77
+ ref,
78
+ className: cn(
79
+ toggleGroupVariants({ orientation }),
80
+ // Attached style for horizontal
81
+ orientation !== "vertical" && [
82
+ "[&>*:not(:first-child)]:rounded-l-none",
83
+ "[&>*:not(:last-child)]:rounded-r-none",
84
+ "[&>*:not(:first-child)]:-ml-px",
85
+ "[&>*]:relative",
86
+ "[&>*:hover]:z-10",
87
+ "[&>*:focus-visible]:z-10",
88
+ "[&>*:active]:scale-none"
89
+ ],
90
+ // Attached style for vertical
91
+ orientation === "vertical" && [
92
+ "[&>*:not(:first-child)]:rounded-t-none",
93
+ "[&>*:not(:last-child)]:rounded-b-none",
94
+ "[&>*:not(:first-child)]:-mt-px",
95
+ "[&>*]:relative",
96
+ "[&>*]:w-full",
97
+ "[&>*:hover]:z-10",
98
+ "[&>*:focus-visible]:z-10",
99
+ "[&>*:active]:scale-none"
100
+ ],
101
+ className
102
+ ),
103
+ orientation,
104
+ ...props
105
+ },
106
+ /* @__PURE__ */ React.createElement(ToggleGroupContext.Provider, { value: { variant, size, radius, fontWeight } }, children)
107
+ ));
108
+ ToggleGroup.displayName = ToggleGroupPrimitive.Root.displayName;
109
+ var iconSizeClasses = {
110
+ xs: "[&>svg]:icon-xs",
111
+ // 14px
112
+ sm: "[&>svg]:icon-xs",
113
+ // 14px
114
+ md: "[&>svg]:icon-sm",
115
+ // 16px
116
+ default: "[&>svg]:icon-sm",
117
+ // 16px
118
+ lg: "[&>svg]:icon-sm"
119
+ // 16px
120
+ };
121
+ var ToggleGroupItem = React.forwardRef(({ className, variant, size, radius, fontWeight, children, ...props }, ref) => {
122
+ const context = React.useContext(ToggleGroupContext);
123
+ const resolvedSize = size || context.size || "default";
124
+ return /* @__PURE__ */ React.createElement(
125
+ ToggleGroupPrimitive.Item,
126
+ {
127
+ ref,
128
+ className: cn(
129
+ toggleGroupItemVariants({
130
+ variant: variant || context.variant,
131
+ size: resolvedSize,
132
+ radius: radius || context.radius,
133
+ fontWeight: fontWeight || context.fontWeight
134
+ }),
135
+ iconSizeClasses[resolvedSize],
136
+ className
137
+ ),
138
+ ...props
139
+ },
140
+ children
141
+ );
142
+ });
143
+ ToggleGroupItem.displayName = ToggleGroupPrimitive.Item.displayName;
144
+
145
+ export {
146
+ toggleGroupVariants,
147
+ toggleGroupItemVariants,
148
+ ToggleGroup,
149
+ ToggleGroupItem
150
+ };
151
+ //# sourceMappingURL=chunk-S4DGVKBK.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/ui/toggle-group.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport * as ToggleGroupPrimitive from '@radix-ui/react-toggle-group'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from '@/lib/utils'\n\nconst toggleGroupVariants = cva(\n 'inline-flex items-center justify-center',\n {\n variants: {\n orientation: {\n horizontal: 'flex-row',\n vertical: 'flex-col',\n },\n },\n defaultVariants: {\n orientation: 'horizontal',\n },\n }\n)\n\nconst toggleGroupItemVariants = cva(\n 'inline-flex items-center justify-center text-sm text-text-muted transition-all duration-micro focus-visible:focus-ring disabled:pointer-events-none disabled:opacity-50',\n {\n variants: {\n variant: {\n default: 'bg-transparent hover:bg-background-muted hover:text-foreground data-[state=on]:bg-background-muted data-[state=on]:text-foreground',\n outline: 'border border-border bg-transparent hover:bg-background-muted hover:text-foreground data-[state=on]:bg-background-muted data-[state=on]:text-foreground',\n },\n fontWeight: {\n normal: 'font-normal',\n semibold: 'font-semibold',\n },\n size: {\n xs: 'h-7 px-2.5 text-xs gap-1', // 28px height, 10px paddingX, 12px font\n sm: 'h-8 px-3 text-sm gap-2', // 32px height, 12px paddingX, 13px font\n md: 'h-9 px-3.5 text-md gap-2', // 36px height, 14px paddingX, 14px font\n default: 'h-10 px-4 text-md gap-2', // 40px height, 16px paddingX, 14px font\n lg: 'h-12 px-6 text-base gap-2', // 48px height, 24px paddingX, 16px font\n },\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-full',\n },\n },\n defaultVariants: {\n variant: 'default',\n size: 'default',\n radius: 'default',\n fontWeight: 'normal',\n },\n }\n)\n\nconst ToggleGroupContext = React.createContext<\n VariantProps<typeof toggleGroupItemVariants>\n>({\n variant: 'default',\n size: 'default',\n radius: 'default',\n fontWeight: 'normal',\n})\n\ntype ToggleGroupSingleProps = {\n type: 'single'\n value?: string\n defaultValue?: string\n onValueChange?: (value: string) => void\n}\n\ntype ToggleGroupMultipleProps = {\n type: 'multiple'\n value?: string[]\n defaultValue?: string[]\n onValueChange?: (value: string[]) => void\n}\n\ntype ToggleGroupBaseProps = Omit<\n React.ComponentPropsWithoutRef<'div'>,\n 'defaultValue' | 'dir'\n> & {\n disabled?: boolean\n rovingFocus?: boolean\n orientation?: 'horizontal' | 'vertical'\n dir?: 'ltr' | 'rtl'\n loop?: boolean\n children?: React.ReactNode\n}\n\nexport type ToggleGroupProps = ToggleGroupBaseProps &\n VariantProps<typeof toggleGroupVariants> &\n VariantProps<typeof toggleGroupItemVariants> &\n (ToggleGroupSingleProps | ToggleGroupMultipleProps)\n\nconst ToggleGroup = React.forwardRef<\n React.ElementRef<typeof ToggleGroupPrimitive.Root>,\n ToggleGroupProps\n>(({ className, orientation, variant, size, radius, fontWeight, children, ...props }, ref) => (\n <ToggleGroupPrimitive.Root\n ref={ref}\n className={cn(\n toggleGroupVariants({ orientation }),\n // Attached style for horizontal\n orientation !== 'vertical' && [\n '[&>*:not(:first-child)]:rounded-l-none',\n '[&>*:not(:last-child)]:rounded-r-none',\n '[&>*:not(:first-child)]:-ml-px',\n '[&>*]:relative',\n '[&>*:hover]:z-10',\n '[&>*:focus-visible]:z-10',\n '[&>*:active]:scale-none',\n ],\n // Attached style for vertical\n orientation === 'vertical' && [\n '[&>*:not(:first-child)]:rounded-t-none',\n '[&>*:not(:last-child)]:rounded-b-none',\n '[&>*:not(:first-child)]:-mt-px',\n '[&>*]:relative',\n '[&>*]:w-full',\n '[&>*:hover]:z-10',\n '[&>*:focus-visible]:z-10',\n '[&>*:active]:scale-none',\n ],\n className\n )}\n orientation={orientation}\n {...(props as React.ComponentPropsWithoutRef<typeof ToggleGroupPrimitive.Root>)}\n >\n <ToggleGroupContext.Provider value={{ variant, size, radius, fontWeight }}>\n {children}\n </ToggleGroupContext.Provider>\n </ToggleGroupPrimitive.Root>\n))\nToggleGroup.displayName = ToggleGroupPrimitive.Root.displayName\n\nexport interface ToggleGroupItemProps\n extends React.ComponentPropsWithoutRef<typeof ToggleGroupPrimitive.Item>,\n Omit<VariantProps<typeof toggleGroupItemVariants>, 'fontWeight'> {\n fontWeight?: 'normal' | 'semibold'\n}\n\n// Icon size for toggle group (5-step scale, Icon+Text mode)\n// xs~sm: 14px, md~default~lg: 16px\nconst iconSizeClasses = {\n xs: '[&>svg]:icon-xs', // 14px\n sm: '[&>svg]:icon-xs', // 14px\n md: '[&>svg]:icon-sm', // 16px\n default: '[&>svg]:icon-sm', // 16px\n lg: '[&>svg]:icon-sm', // 16px\n}\n\nconst ToggleGroupItem = React.forwardRef<\n React.ElementRef<typeof ToggleGroupPrimitive.Item>,\n ToggleGroupItemProps\n>(({ className, variant, size, radius, fontWeight, children, ...props }, ref) => {\n const context = React.useContext(ToggleGroupContext)\n const resolvedSize = size || context.size || 'default'\n\n return (\n <ToggleGroupPrimitive.Item\n ref={ref}\n className={cn(\n toggleGroupItemVariants({\n variant: variant || context.variant,\n size: resolvedSize,\n radius: radius || context.radius,\n fontWeight: fontWeight || context.fontWeight,\n }),\n iconSizeClasses[resolvedSize],\n className\n )}\n {...props}\n >\n {children}\n </ToggleGroupPrimitive.Item>\n )\n})\nToggleGroupItem.displayName = ToggleGroupPrimitive.Item.displayName\n\nexport { ToggleGroup, ToggleGroupItem, toggleGroupVariants, toggleGroupItemVariants }\n"],"mappings":"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","names":[]}
@@ -0,0 +1,114 @@
1
+ "use client";
2
+ import {
3
+ cn
4
+ } from "./chunk-53MIUPSY.mjs";
5
+
6
+ // src/components/ui/typing-indicator.tsx
7
+ import * as React from "react";
8
+ import { cva } from "class-variance-authority";
9
+ var DOT_SIZES = { sm: 4, default: 6, lg: 8 };
10
+ var DOT_GAP = { sm: 3, default: 4, lg: 5 };
11
+ var SPEED_MS = { slow: 1600, default: 1100, fast: 700 };
12
+ var DOT_COUNT = 3;
13
+ var bgColorMap = {
14
+ default: "bg-foreground",
15
+ primary: "bg-primary",
16
+ muted: "bg-text-subtle"
17
+ };
18
+ var typingIndicatorVariants = cva(
19
+ "inline-flex items-center",
20
+ {
21
+ variants: {
22
+ size: {
23
+ sm: "gap-1.5 text-xs",
24
+ default: "gap-2 text-sm",
25
+ lg: "gap-2.5 text-base"
26
+ }
27
+ },
28
+ defaultVariants: {
29
+ size: "default"
30
+ }
31
+ }
32
+ );
33
+ var TypingIndicator = React.forwardRef(
34
+ ({
35
+ className,
36
+ variant = "dots",
37
+ size,
38
+ color = "muted",
39
+ speed = "default",
40
+ label = "Typing",
41
+ showLabel = false,
42
+ ...props
43
+ }, ref) => {
44
+ const resolvedSize = size ?? "default";
45
+ return /* @__PURE__ */ React.createElement(
46
+ "div",
47
+ {
48
+ ref,
49
+ role: "status",
50
+ "aria-live": "polite",
51
+ "aria-label": label,
52
+ className: cn(typingIndicatorVariants({ size }), className),
53
+ ...props
54
+ },
55
+ variant === "dots" && /* @__PURE__ */ React.createElement(DotsIndicator, { size: resolvedSize, color, speed }),
56
+ variant === "cursor" && /* @__PURE__ */ React.createElement(CursorIndicator, { size: resolvedSize, color }),
57
+ showLabel && /* @__PURE__ */ React.createElement("span", { className: "text-text-muted select-none" }, label)
58
+ );
59
+ }
60
+ );
61
+ TypingIndicator.displayName = "TypingIndicator";
62
+ function DotsIndicator({
63
+ size,
64
+ color,
65
+ speed
66
+ }) {
67
+ const dotSize = DOT_SIZES[size];
68
+ const gap = DOT_GAP[size];
69
+ const duration = SPEED_MS[speed];
70
+ return /* @__PURE__ */ React.createElement("div", { className: "inline-flex items-center", style: { gap } }, Array.from({ length: DOT_COUNT }, (_, i) => /* @__PURE__ */ React.createElement(
71
+ "div",
72
+ {
73
+ key: i,
74
+ className: cn(
75
+ "rounded-full animate-spinner-dot motion-reduce:animate-none motion-reduce:opacity-60",
76
+ bgColorMap[color]
77
+ ),
78
+ style: {
79
+ width: dotSize,
80
+ height: dotSize,
81
+ animationDuration: `${duration}ms`,
82
+ animationDelay: `${i * (duration / DOT_COUNT / 1.5)}ms`
83
+ }
84
+ }
85
+ )));
86
+ }
87
+ var CURSOR_SIZE = {
88
+ sm: { width: 2, height: 14 },
89
+ default: { width: 2.5, height: 20 },
90
+ lg: { width: 3, height: 26 }
91
+ };
92
+ function CursorIndicator({
93
+ size,
94
+ color
95
+ }) {
96
+ const { width, height } = CURSOR_SIZE[size];
97
+ return /* @__PURE__ */ React.createElement(
98
+ "div",
99
+ {
100
+ "aria-hidden": "true",
101
+ className: cn(
102
+ "rounded-full animate-typing-cursor motion-reduce:animate-none motion-reduce:opacity-60",
103
+ bgColorMap[color]
104
+ ),
105
+ style: { width, height, animationDuration: "1200ms" }
106
+ }
107
+ );
108
+ }
109
+
110
+ export {
111
+ typingIndicatorVariants,
112
+ TypingIndicator
113
+ };
114
+ //# sourceMappingURL=chunk-S4T4PU7F.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/ui/typing-indicator.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// Constants\n// ============================================================================\n\n/** Dot diameter per size (px) */\nconst DOT_SIZES = { sm: 4, default: 6, lg: 8 } as const\n\n/** Gap between dots per size (px) */\nconst DOT_GAP = { sm: 3, default: 4, lg: 5 } as const\n\n/** Animation speed in ms */\nconst SPEED_MS = { slow: 1600, default: 1100, fast: 700 } as const\n\n/** Number of dots */\nconst DOT_COUNT = 3\n\n// ============================================================================\n// Color mapping\n// ============================================================================\n\nconst bgColorMap = {\n default: 'bg-foreground',\n primary: 'bg-primary',\n muted: 'bg-text-subtle',\n} as const\n\n// ============================================================================\n// Variants (CVA)\n// ============================================================================\n\nconst typingIndicatorVariants = cva(\n 'inline-flex items-center',\n {\n variants: {\n size: {\n sm: 'gap-1.5 text-xs',\n default: 'gap-2 text-sm',\n lg: 'gap-2.5 text-base',\n },\n },\n defaultVariants: {\n size: 'default',\n },\n }\n)\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface TypingIndicatorProps\n extends React.HTMLAttributes<HTMLDivElement>,\n VariantProps<typeof typingIndicatorVariants> {\n /** Animation style */\n variant?: 'dots' | 'cursor'\n /** Indicator color */\n color?: 'default' | 'primary' | 'muted'\n /** Animation speed */\n speed?: 'slow' | 'default' | 'fast'\n /** Accessible label (also shown as visual text when showLabel is true) */\n label?: string\n /** Render label text alongside the indicator */\n showLabel?: boolean\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\nconst TypingIndicator = React.forwardRef<HTMLDivElement, TypingIndicatorProps>(\n (\n {\n className,\n variant = 'dots',\n size,\n color = 'muted',\n speed = 'default',\n label = 'Typing',\n showLabel = false,\n ...props\n },\n ref\n ) => {\n const resolvedSize = size ?? 'default'\n\n return (\n <div\n ref={ref}\n role=\"status\"\n aria-live=\"polite\"\n aria-label={label}\n className={cn(typingIndicatorVariants({ size }), className)}\n {...props}\n >\n {variant === 'dots' && (\n <DotsIndicator size={resolvedSize} color={color} speed={speed} />\n )}\n {variant === 'cursor' && (\n <CursorIndicator size={resolvedSize} color={color} />\n )}\n {showLabel && (\n <span className=\"text-text-muted select-none\">{label}</span>\n )}\n </div>\n )\n }\n)\nTypingIndicator.displayName = 'TypingIndicator'\n\n// ============================================================================\n// Dots Indicator — 3 staggered bouncing dots (reuses animate-spinner-dot)\n// ============================================================================\n\nfunction DotsIndicator({\n size,\n color,\n speed,\n}: {\n size: 'sm' | 'default' | 'lg'\n color: 'default' | 'primary' | 'muted'\n speed: 'slow' | 'default' | 'fast'\n}) {\n const dotSize = DOT_SIZES[size]\n const gap = DOT_GAP[size]\n const duration = SPEED_MS[speed]\n\n return (\n <div className=\"inline-flex items-center\" style={{ gap }}>\n {Array.from({ length: DOT_COUNT }, (_, i) => (\n <div\n key={i}\n className={cn(\n 'rounded-full animate-spinner-dot motion-reduce:animate-none motion-reduce:opacity-60',\n bgColorMap[color]\n )}\n style={{\n width: dotSize,\n height: dotSize,\n animationDuration: `${duration}ms`,\n animationDelay: `${i * (duration / DOT_COUNT / 1.5)}ms`,\n }}\n />\n ))}\n </div>\n )\n}\n\n// ============================================================================\n// Cursor sizes per component size\n// ============================================================================\n\nconst CURSOR_SIZE = {\n sm: { width: 2, height: 14 },\n default: { width: 2.5, height: 20 },\n lg: { width: 3, height: 26 },\n} as const\n\n// ============================================================================\n// Cursor Indicator — blinking cursor (text-cursor style)\n// ============================================================================\n\nfunction CursorIndicator({\n size,\n color,\n}: {\n size: 'sm' | 'default' | 'lg'\n color: 'default' | 'primary' | 'muted'\n}) {\n const { width, height } = CURSOR_SIZE[size]\n\n return (\n <div\n aria-hidden=\"true\"\n className={cn(\n 'rounded-full animate-typing-cursor motion-reduce:animate-none motion-reduce:opacity-60',\n bgColorMap[color]\n )}\n style={{ width, height, animationDuration: '1200ms' }}\n />\n )\n}\n\nexport { TypingIndicator, typingIndicatorVariants }\n"],"mappings":";;;;;;AAEA,YAAY,WAAW;AACvB,SAAS,WAA8B;AAQvC,IAAM,YAAY,EAAE,IAAI,GAAG,SAAS,GAAG,IAAI,EAAE;AAG7C,IAAM,UAAU,EAAE,IAAI,GAAG,SAAS,GAAG,IAAI,EAAE;AAG3C,IAAM,WAAW,EAAE,MAAM,MAAM,SAAS,MAAM,MAAM,IAAI;AAGxD,IAAM,YAAY;AAMlB,IAAM,aAAa;AAAA,EACjB,SAAS;AAAA,EACT,SAAS;AAAA,EACT,OAAS;AACX;AAMA,IAAM,0BAA0B;AAAA,EAC9B;AAAA,EACA;AAAA,IACE,UAAU;AAAA,MACR,MAAM;AAAA,QACJ,IAAS;AAAA,QACT,SAAS;AAAA,QACT,IAAS;AAAA,MACX;AAAA,IACF;AAAA,IACA,iBAAiB;AAAA,MACf,MAAM;AAAA,IACR;AAAA,EACF;AACF;AAyBA,IAAM,kBAAwB;AAAA,EAC5B,CACE;AAAA,IACE;AAAA,IACA,UAAU;AAAA,IACV;AAAA,IACA,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,YAAY;AAAA,IACZ,GAAG;AAAA,EACL,GACA,QACG;AACH,UAAM,eAAe,QAAQ;AAE7B,WACE;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,MAAK;AAAA,QACL,aAAU;AAAA,QACV,cAAY;AAAA,QACZ,WAAW,GAAG,wBAAwB,EAAE,KAAK,CAAC,GAAG,SAAS;AAAA,QACzD,GAAG;AAAA;AAAA,MAEH,YAAY,UACX,oCAAC,iBAAc,MAAM,cAAc,OAAc,OAAc;AAAA,MAEhE,YAAY,YACX,oCAAC,mBAAgB,MAAM,cAAc,OAAc;AAAA,MAEpD,aACC,oCAAC,UAAK,WAAU,iCAA+B,KAAM;AAAA,IAEzD;AAAA,EAEJ;AACF;AACA,gBAAgB,cAAc;AAM9B,SAAS,cAAc;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,QAAM,UAAU,UAAU,IAAI;AAC9B,QAAM,MAAM,QAAQ,IAAI;AACxB,QAAM,WAAW,SAAS,KAAK;AAE/B,SACE,oCAAC,SAAI,WAAU,4BAA2B,OAAO,EAAE,IAAI,KACpD,MAAM,KAAK,EAAE,QAAQ,UAAU,GAAG,CAAC,GAAG,MACrC;AAAA,IAAC;AAAA;AAAA,MACC,KAAK;AAAA,MACL,WAAW;AAAA,QACT;AAAA,QACA,WAAW,KAAK;AAAA,MAClB;AAAA,MACA,OAAO;AAAA,QACL,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,mBAAmB,GAAG,QAAQ;AAAA,QAC9B,gBAAgB,GAAG,KAAK,WAAW,YAAY,IAAI;AAAA,MACrD;AAAA;AAAA,EACF,CACD,CACH;AAEJ;AAMA,IAAM,cAAc;AAAA,EAClB,IAAS,EAAE,OAAO,GAAG,QAAQ,GAAG;AAAA,EAChC,SAAS,EAAE,OAAO,KAAK,QAAQ,GAAG;AAAA,EAClC,IAAS,EAAE,OAAO,GAAG,QAAQ,GAAG;AAClC;AAMA,SAAS,gBAAgB;AAAA,EACvB;AAAA,EACA;AACF,GAGG;AACD,QAAM,EAAE,OAAO,OAAO,IAAI,YAAY,IAAI;AAE1C,SACE;AAAA,IAAC;AAAA;AAAA,MACC,eAAY;AAAA,MACZ,WAAW;AAAA,QACT;AAAA,QACA,WAAW,KAAK;AAAA,MAClB;AAAA,MACA,OAAO,EAAE,OAAO,QAAQ,mBAAmB,SAAS;AAAA;AAAA,EACtD;AAEJ;","names":[]}