@tulipfarm/sprout 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (306) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +183 -2
  3. package/dist/components/accordion.d.ts +28 -0
  4. package/dist/components/accordion.js +26 -0
  5. package/dist/components/alert-dialog.d.ts +60 -0
  6. package/dist/components/alert-dialog.js +69 -0
  7. package/dist/components/alert.d.ts +30 -0
  8. package/dist/components/alert.js +35 -0
  9. package/dist/components/aspect-ratio.d.ts +7 -0
  10. package/dist/components/aspect-ratio.js +6 -0
  11. package/dist/components/attachment.d.ts +118 -0
  12. package/dist/components/attachment.js +285 -0
  13. package/dist/components/avatar.d.ts +32 -0
  14. package/dist/components/avatar.js +73 -0
  15. package/dist/components/badge.d.ts +21 -0
  16. package/dist/components/badge.js +27 -0
  17. package/dist/components/brand-icon.d.ts +28 -0
  18. package/dist/components/brand-icon.js +78 -0
  19. package/dist/components/breadcrumb.d.ts +29 -0
  20. package/dist/components/breadcrumb.js +44 -0
  21. package/dist/components/button-group.d.ts +28 -0
  22. package/dist/components/button-group.js +36 -0
  23. package/dist/components/button.d.ts +79 -0
  24. package/dist/components/button.js +93 -0
  25. package/dist/components/calendar.d.ts +27 -0
  26. package/dist/components/calendar.js +107 -0
  27. package/dist/components/canvas.d.ts +78 -0
  28. package/dist/components/canvas.js +180 -0
  29. package/dist/components/card.d.ts +43 -0
  30. package/dist/components/card.js +42 -0
  31. package/dist/components/carousel.d.ts +57 -0
  32. package/dist/components/carousel.js +422 -0
  33. package/dist/components/chart.d.ts +112 -0
  34. package/dist/components/chart.js +172 -0
  35. package/dist/components/chat-confirmation.d.ts +42 -0
  36. package/dist/components/chat-confirmation.js +62 -0
  37. package/dist/components/chat-plan.d.ts +21 -0
  38. package/dist/components/chat-plan.js +35 -0
  39. package/dist/components/chat-sources.d.ts +64 -0
  40. package/dist/components/chat-sources.js +66 -0
  41. package/dist/components/checkbox.d.ts +16 -0
  42. package/dist/components/checkbox.js +17 -0
  43. package/dist/components/choice-list.d.ts +53 -0
  44. package/dist/components/choice-list.js +36 -0
  45. package/dist/components/code-block.d.ts +35 -0
  46. package/dist/components/code-block.js +95 -0
  47. package/dist/components/collapsible.d.ts +24 -0
  48. package/dist/components/collapsible.js +27 -0
  49. package/dist/components/combobox.d.ts +95 -0
  50. package/dist/components/combobox.js +106 -0
  51. package/dist/components/command.d.ts +94 -0
  52. package/dist/components/command.js +414 -0
  53. package/dist/components/context-menu.d.ts +57 -0
  54. package/dist/components/context-menu.js +60 -0
  55. package/dist/components/dialog.d.ts +60 -0
  56. package/dist/components/dialog.js +79 -0
  57. package/dist/components/direction.d.ts +6 -0
  58. package/dist/components/direction.js +6 -0
  59. package/dist/components/dropdown-menu.d.ts +62 -0
  60. package/dist/components/dropdown-menu.js +59 -0
  61. package/dist/components/field.d.ts +117 -0
  62. package/dist/components/field.js +150 -0
  63. package/dist/components/file-viewer.d.ts +120 -0
  64. package/dist/components/file-viewer.js +373 -0
  65. package/dist/components/form.d.ts +87 -0
  66. package/dist/components/form.js +55 -0
  67. package/dist/components/glass-banner.d.ts +27 -0
  68. package/dist/components/glass-banner.js +116 -0
  69. package/dist/components/gradient-banner.d.ts +37 -0
  70. package/dist/components/gradient-banner.js +43 -0
  71. package/dist/components/hover-card.d.ts +27 -0
  72. package/dist/components/hover-card.js +26 -0
  73. package/dist/components/input-group.d.ts +68 -0
  74. package/dist/components/input-group.js +88 -0
  75. package/dist/components/input-otp.d.ts +38 -0
  76. package/dist/components/input-otp.js +43 -0
  77. package/dist/components/input.d.ts +16 -0
  78. package/dist/components/input.js +18 -0
  79. package/dist/components/kbd.d.ts +12 -0
  80. package/dist/components/kbd.js +11 -0
  81. package/dist/components/label.d.ts +8 -0
  82. package/dist/components/label.js +10 -0
  83. package/dist/components/mention-list.d.ts +54 -0
  84. package/dist/components/mention-list.js +31 -0
  85. package/dist/components/menubar.d.ts +64 -0
  86. package/dist/components/menubar.js +68 -0
  87. package/dist/components/message-actions.d.ts +34 -0
  88. package/dist/components/message-actions.js +68 -0
  89. package/dist/components/message-response.d.ts +20 -0
  90. package/dist/components/message-response.js +46 -0
  91. package/dist/components/message-scroller.d.ts +71 -0
  92. package/dist/components/message-scroller.js +217 -0
  93. package/dist/components/message.d.ts +49 -0
  94. package/dist/components/message.js +59 -0
  95. package/dist/components/navigation-menu.d.ts +45 -0
  96. package/dist/components/navigation-menu.js +54 -0
  97. package/dist/components/notice-banner.d.ts +14 -0
  98. package/dist/components/notice-banner.js +11 -0
  99. package/dist/components/page-content.d.ts +7 -0
  100. package/dist/components/page-content.js +9 -0
  101. package/dist/components/page-header.d.ts +37 -0
  102. package/dist/components/page-header.js +53 -0
  103. package/dist/components/pagination.d.ts +29 -0
  104. package/dist/components/pagination.js +29 -0
  105. package/dist/components/plan-outline.d.ts +60 -0
  106. package/dist/components/plan-outline.js +108 -0
  107. package/dist/components/popover.d.ts +34 -0
  108. package/dist/components/popover.js +35 -0
  109. package/dist/components/progress.d.ts +27 -0
  110. package/dist/components/progress.js +35 -0
  111. package/dist/components/prompt-list.d.ts +23 -0
  112. package/dist/components/prompt-list.js +11 -0
  113. package/dist/components/questionnaire.d.ts +148 -0
  114. package/dist/components/questionnaire.js +1001 -0
  115. package/dist/components/radio-group.d.ts +16 -0
  116. package/dist/components/radio-group.js +21 -0
  117. package/dist/components/reasoning-effort.d.ts +24 -0
  118. package/dist/components/reasoning-effort.js +269 -0
  119. package/dist/components/resizable.d.ts +67 -0
  120. package/dist/components/resizable.js +536 -0
  121. package/dist/components/result-card.d.ts +58 -0
  122. package/dist/components/result-card.js +88 -0
  123. package/dist/components/review-card.d.ts +62 -0
  124. package/dist/components/review-card.js +49 -0
  125. package/dist/components/rich-text-editor.d.ts +51 -0
  126. package/dist/components/rich-text-editor.js +248 -0
  127. package/dist/components/schema-diagram.d.ts +52 -0
  128. package/dist/components/schema-diagram.js +226 -0
  129. package/dist/components/scroll-area.d.ts +22 -0
  130. package/dist/components/scroll-area.js +19 -0
  131. package/dist/components/search-dialog.d.ts +103 -0
  132. package/dist/components/search-dialog.js +64 -0
  133. package/dist/components/search-field.d.ts +17 -0
  134. package/dist/components/search-field.js +27 -0
  135. package/dist/components/select.d.ts +57 -0
  136. package/dist/components/select.js +57 -0
  137. package/dist/components/selection-slot.d.ts +18 -0
  138. package/dist/components/selection-slot.js +53 -0
  139. package/dist/components/separator.d.ts +48 -0
  140. package/dist/components/separator.js +54 -0
  141. package/dist/components/settings-list.d.ts +26 -0
  142. package/dist/components/settings-list.js +17 -0
  143. package/dist/components/sheet.d.ts +70 -0
  144. package/dist/components/sheet.js +77 -0
  145. package/dist/components/sidebar.d.ts +70 -0
  146. package/dist/components/sidebar.js +187 -0
  147. package/dist/components/skeleton.d.ts +31 -0
  148. package/dist/components/skeleton.js +32 -0
  149. package/dist/components/slider.d.ts +17 -0
  150. package/dist/components/slider.js +24 -0
  151. package/dist/components/spinner.d.ts +37 -0
  152. package/dist/components/spinner.js +43 -0
  153. package/dist/components/state-panel-samples.d.ts +25 -0
  154. package/dist/components/state-panel-samples.js +423 -0
  155. package/dist/components/state-panel.d.ts +35 -0
  156. package/dist/components/state-panel.js +29 -0
  157. package/dist/components/state-sample.d.ts +63 -0
  158. package/dist/components/state-sample.js +42 -0
  159. package/dist/components/switch.d.ts +12 -0
  160. package/dist/components/switch.js +14 -0
  161. package/dist/components/table-nuqs.d.ts +16 -0
  162. package/dist/components/table-nuqs.js +59 -0
  163. package/dist/components/table.d.ts +120 -0
  164. package/dist/components/table.js +663 -0
  165. package/dist/components/tabs.d.ts +37 -0
  166. package/dist/components/tabs.js +36 -0
  167. package/dist/components/textarea.d.ts +18 -0
  168. package/dist/components/textarea.js +19 -0
  169. package/dist/components/toast.d.ts +45 -0
  170. package/dist/components/toast.js +83 -0
  171. package/dist/components/toggle-group.d.ts +30 -0
  172. package/dist/components/toggle-group.js +39 -0
  173. package/dist/components/toggle.d.ts +27 -0
  174. package/dist/components/toggle.js +21 -0
  175. package/dist/components/tool-activity.d.ts +79 -0
  176. package/dist/components/tool-activity.js +226 -0
  177. package/dist/components/toolbar-status.d.ts +21 -0
  178. package/dist/components/toolbar-status.js +14 -0
  179. package/dist/components/tooltip.d.ts +31 -0
  180. package/dist/components/tooltip.js +99 -0
  181. package/dist/components/typed-text.d.ts +17 -0
  182. package/dist/components/typed-text.js +56 -0
  183. package/dist/index.d.ts +88 -0
  184. package/dist/index.js +88 -0
  185. package/dist/internal/brand-glyphs.d.ts +342 -0
  186. package/dist/internal/brand-glyphs.js +238 -0
  187. package/dist/internal/classes.d.ts +3 -0
  188. package/dist/internal/classes.js +20 -0
  189. package/dist/internal/fieldset.d.ts +6 -0
  190. package/dist/internal/fieldset.js +38 -0
  191. package/dist/internal/file-kind.d.ts +4 -0
  192. package/dist/internal/file-kind.js +62 -0
  193. package/dist/internal/languages.d.ts +7 -0
  194. package/dist/internal/languages.js +1010 -0
  195. package/dist/internal/message-scroller.d.ts +102 -0
  196. package/dist/internal/message-scroller.js +637 -0
  197. package/dist/internal/pressable.d.ts +2 -0
  198. package/dist/internal/pressable.js +29 -0
  199. package/dist/internal/syntax.d.ts +14 -0
  200. package/dist/internal/syntax.js +137 -0
  201. package/dist/styles/accordion.css +102 -0
  202. package/dist/styles/alert-dialog.css +198 -0
  203. package/dist/styles/alert.css +149 -0
  204. package/dist/styles/aspect-ratio.css +8 -0
  205. package/dist/styles/attachment.css +720 -0
  206. package/dist/styles/avatar.css +186 -0
  207. package/dist/styles/badge.css +178 -0
  208. package/dist/styles/brand-icon.css +104 -0
  209. package/dist/styles/breadcrumb.css +121 -0
  210. package/dist/styles/button-group.css +113 -0
  211. package/dist/styles/button.css +380 -0
  212. package/dist/styles/calendar.css +295 -0
  213. package/dist/styles/canvas.css +327 -0
  214. package/dist/styles/card.css +146 -0
  215. package/dist/styles/carousel.css +107 -0
  216. package/dist/styles/chart.css +227 -0
  217. package/dist/styles/chat-confirmation.css +29 -0
  218. package/dist/styles/chat-plan.css +109 -0
  219. package/dist/styles/chat-sources.css +191 -0
  220. package/dist/styles/checkbox.css +123 -0
  221. package/dist/styles/choice-list.css +343 -0
  222. package/dist/styles/code-block.css +211 -0
  223. package/dist/styles/collapsible.css +72 -0
  224. package/dist/styles/combobox.css +347 -0
  225. package/dist/styles/command.css +233 -0
  226. package/dist/styles/context-menu.css +151 -0
  227. package/dist/styles/dialog.css +237 -0
  228. package/dist/styles/dropdown-menu.css +150 -0
  229. package/dist/styles/field.css +341 -0
  230. package/dist/styles/file-viewer.css +278 -0
  231. package/dist/styles/form.css +155 -0
  232. package/dist/styles/glass-banner.css +308 -0
  233. package/dist/styles/gradient-banner.css +256 -0
  234. package/dist/styles/hover-card.css +95 -0
  235. package/dist/styles/index.css +262 -0
  236. package/dist/styles/input-group.css +290 -0
  237. package/dist/styles/input-otp.css +138 -0
  238. package/dist/styles/input.css +99 -0
  239. package/dist/styles/kbd.css +59 -0
  240. package/dist/styles/label.css +89 -0
  241. package/dist/styles/mention-list.css +166 -0
  242. package/dist/styles/menubar.css +226 -0
  243. package/dist/styles/message-actions.css +83 -0
  244. package/dist/styles/message-response.css +176 -0
  245. package/dist/styles/message-scroller.css +136 -0
  246. package/dist/styles/message.css +310 -0
  247. package/dist/styles/navigation-menu.css +291 -0
  248. package/dist/styles/notice-banner.css +68 -0
  249. package/dist/styles/page-content.css +21 -0
  250. package/dist/styles/page-header.css +156 -0
  251. package/dist/styles/pagination.css +72 -0
  252. package/dist/styles/plan-outline.css +393 -0
  253. package/dist/styles/popover.css +140 -0
  254. package/dist/styles/progress.css +93 -0
  255. package/dist/styles/prompt-list.css +165 -0
  256. package/dist/styles/questionnaire.css +323 -0
  257. package/dist/styles/radio-group.css +120 -0
  258. package/dist/styles/reasoning-effort.css +157 -0
  259. package/dist/styles/resizable.css +108 -0
  260. package/dist/styles/result-card.css +215 -0
  261. package/dist/styles/review-card.css +235 -0
  262. package/dist/styles/rich-text-editor.css +169 -0
  263. package/dist/styles/schema-diagram.css +419 -0
  264. package/dist/styles/scroll-area.css +77 -0
  265. package/dist/styles/search-dialog.css +363 -0
  266. package/dist/styles/search-field.css +17 -0
  267. package/dist/styles/select.css +285 -0
  268. package/dist/styles/selection-slot.css +31 -0
  269. package/dist/styles/separator.css +206 -0
  270. package/dist/styles/settings-list.css +81 -0
  271. package/dist/styles/sheet.css +361 -0
  272. package/dist/styles/sidebar.css +363 -0
  273. package/dist/styles/skeleton.css +80 -0
  274. package/dist/styles/slider.css +142 -0
  275. package/dist/styles/spinner.css +39 -0
  276. package/dist/styles/state-panel-samples.css +41 -0
  277. package/dist/styles/state-panel.css +182 -0
  278. package/dist/styles/state-sample.css +285 -0
  279. package/dist/styles/switch.css +128 -0
  280. package/dist/styles/table.css +604 -0
  281. package/dist/styles/tabs.css +223 -0
  282. package/dist/styles/textarea.css +78 -0
  283. package/dist/styles/themes/chatgpt.css +125 -0
  284. package/dist/styles/themes/claude.css +125 -0
  285. package/dist/styles/themes/cloudflare.css +125 -0
  286. package/dist/styles/themes/discord.css +125 -0
  287. package/dist/styles/themes/github.css +125 -0
  288. package/dist/styles/themes/grok.css +125 -0
  289. package/dist/styles/themes/linear.css +126 -0
  290. package/dist/styles/themes/neutral.css +125 -0
  291. package/dist/styles/themes/notion.css +125 -0
  292. package/dist/styles/themes/perplexity.css +125 -0
  293. package/dist/styles/themes/raycast.css +125 -0
  294. package/dist/styles/themes/spotify.css +125 -0
  295. package/dist/styles/themes/stripe.css +125 -0
  296. package/dist/styles/themes/supabase.css +125 -0
  297. package/dist/styles/themes/tulipfarm.css +125 -0
  298. package/dist/styles/themes/vercel.css +126 -0
  299. package/dist/styles/toast.css +197 -0
  300. package/dist/styles/toggle-group.css +161 -0
  301. package/dist/styles/toggle.css +119 -0
  302. package/dist/styles/tool-activity.css +396 -0
  303. package/dist/styles/toolbar-status.css +52 -0
  304. package/dist/styles/tooltip.css +122 -0
  305. package/dist/styles/typed-text.css +17 -0
  306. package/package.json +443 -4
@@ -0,0 +1,116 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useId, useImperativeHandle, useRef, } from "react";
3
+ import { cn } from "../internal/classes.js";
4
+ /**
5
+ * A frosted showcase banner with draggable glass chips. The bubble art is
6
+ * hidden from assistive technology; the chips are announced as a list named
7
+ * by the caption, or by the title when there is no caption.
8
+ */
9
+ export function GlassBanner({ title, caption, className, children, ...props }) {
10
+ const id = useId();
11
+ const titleId = `${id}-title`;
12
+ const captionId = `${id}-caption`;
13
+ const hasCaption = caption !== undefined &&
14
+ caption !== null &&
15
+ caption !== false &&
16
+ caption !== "";
17
+ return (_jsxs("div", { "data-slot": "glass-banner", ...props, className: cn("sprout-glass-banner", className), children: [_jsx("div", { "data-slot": "glass-banner-art", className: "sprout-glass-banner-art", "aria-hidden": "true", children: Array.from({ length: 5 }, (_, index) => (_jsx("span", { "data-slot": "glass-bubble", className: "sprout-glass-bubble" }, index))) }), _jsxs("div", { "data-slot": "glass-banner-copy", className: "sprout-glass-banner-copy", children: [_jsx("p", { id: titleId, "data-slot": "glass-banner-title", className: "sprout-glass-banner-title", children: title }), hasCaption && (_jsx("p", { id: captionId, "data-slot": "glass-banner-caption", className: "sprout-glass-banner-caption", children: caption }))] }), _jsx("ul", { "data-slot": "glass-banner-chips", className: "sprout-glass-banner-chips", "aria-labelledby": hasCaption ? captionId : titleId, children: children })] }));
18
+ }
19
+ const clamp = (value, limit) => Math.max(-limit, Math.min(limit, value));
20
+ const prefersReducedMotion = () => typeof window !== "undefined" &&
21
+ typeof window.matchMedia === "function" &&
22
+ window.matchMedia("(prefers-reduced-motion: reduce)").matches;
23
+ /**
24
+ * A glass pill that can be dragged with a pointer and springs back on
25
+ * release, stretching with its speed. The drag is play only: chips are not
26
+ * controls and take no focus. With reduced motion the chip neither floats
27
+ * nor springs; it snaps home on release.
28
+ */
29
+ export function GlassChip({ icon, className, children, ref, ...props }) {
30
+ const chip = useRef(null);
31
+ useImperativeHandle(ref, () => chip.current, []);
32
+ useEffect(() => {
33
+ const element = chip.current;
34
+ if (!element)
35
+ return;
36
+ let x = 0, y = 0, vx = 0, vy = 0, targetX = 0, targetY = 0;
37
+ let startX = 0, startY = 0, pointer = null, frame = 0;
38
+ const paint = () => {
39
+ const speed = Math.hypot(vx, vy);
40
+ const stretch = Math.min(speed / 70, 0.22);
41
+ const angle = Math.atan2(vy, vx);
42
+ element.style.transform = `translate(${x}px, ${y}px) rotate(${angle}rad) scale(${1 + stretch}, ${1 - stretch * 0.55}) rotate(${-angle}rad) rotate(${clamp(vx * 0.35, 10)}deg) skewX(${clamp(-vx * 0.25, 8)}deg)`;
43
+ };
44
+ const rest = () => {
45
+ x = y = vx = vy = 0;
46
+ element.style.transform = "";
47
+ element.removeAttribute("data-dragging");
48
+ frame = 0;
49
+ };
50
+ const tick = () => {
51
+ if (pointer !== null) {
52
+ vx = (targetX - x) * 0.28;
53
+ vy = (targetY - y) * 0.28;
54
+ }
55
+ else {
56
+ vx = (vx - x * 0.09) * 0.82;
57
+ vy = (vy - y * 0.09) * 0.82;
58
+ if (Math.abs(x) + Math.abs(y) + Math.abs(vx) + Math.abs(vy) < 0.05) {
59
+ rest();
60
+ return;
61
+ }
62
+ }
63
+ x += vx;
64
+ y += vy;
65
+ paint();
66
+ frame = requestAnimationFrame(tick);
67
+ };
68
+ const run = () => {
69
+ if (!frame)
70
+ frame = requestAnimationFrame(tick);
71
+ };
72
+ const down = (event) => {
73
+ if (event.button !== 0 || pointer !== null)
74
+ return;
75
+ pointer = event.pointerId;
76
+ element.setPointerCapture?.(pointer);
77
+ element.setAttribute("data-dragging", "");
78
+ startX = event.clientX - x;
79
+ startY = event.clientY - y;
80
+ targetX = x;
81
+ targetY = y;
82
+ run();
83
+ };
84
+ const move = (event) => {
85
+ if (event.pointerId !== pointer)
86
+ return;
87
+ targetX = event.clientX - startX;
88
+ targetY = event.clientY - startY;
89
+ };
90
+ const up = (event) => {
91
+ if (event.pointerId !== pointer)
92
+ return;
93
+ pointer = null;
94
+ if (prefersReducedMotion()) {
95
+ cancelAnimationFrame(frame);
96
+ rest();
97
+ return;
98
+ }
99
+ run();
100
+ };
101
+ element.addEventListener("pointerdown", down);
102
+ element.addEventListener("pointermove", move);
103
+ element.addEventListener("pointerup", up);
104
+ element.addEventListener("pointercancel", up);
105
+ element.addEventListener("lostpointercapture", up);
106
+ return () => {
107
+ cancelAnimationFrame(frame);
108
+ element.removeEventListener("pointerdown", down);
109
+ element.removeEventListener("pointermove", move);
110
+ element.removeEventListener("pointerup", up);
111
+ element.removeEventListener("pointercancel", up);
112
+ element.removeEventListener("lostpointercapture", up);
113
+ };
114
+ }, []);
115
+ return (_jsx("li", { ref: chip, "data-slot": "glass-chip", ...props, className: cn("sprout-glass-chip", className), children: _jsxs("span", { "data-slot": "glass-chip-surface", className: "sprout-glass-chip-surface", children: [icon && (_jsx("span", { "data-slot": "glass-chip-icon", className: "sprout-glass-chip-icon", children: icon })), _jsx("span", { "data-slot": "glass-chip-label", className: "sprout-glass-chip-label", children: children })] }) }));
116
+ }
@@ -0,0 +1,37 @@
1
+ import { type ComponentProps } from "react";
2
+ export declare const gradientBannerVariantNames: readonly ["aurora", "citrus", "lagoon", "iris", "cobalt", "mint"];
3
+ export declare const gradientBannerSizeNames: readonly ["sm", "md", "lg", "xl"];
4
+ export declare const gradientBannerPanelToneNames: readonly ["light", "dark"];
5
+ export type GradientBannerVariant = (typeof gradientBannerVariantNames)[number];
6
+ export type GradientBannerSize = (typeof gradientBannerSizeNames)[number];
7
+ export type GradientBannerPanelTone = (typeof gradientBannerPanelToneNames)[number];
8
+ export interface GradientBannerProps extends ComponentProps<"div"> {
9
+ /** Color story of the art. Defaults to `"aurora"`. */
10
+ variant?: GradientBannerVariant | undefined;
11
+ /** `sm` 96px, `md` 160px, `lg` 240px (default), `xl` 360px minimum height. */
12
+ size?: GradientBannerSize | undefined;
13
+ /** Film grain over the art. Defaults to `true`. */
14
+ texture?: boolean | undefined;
15
+ }
16
+ /**
17
+ * Decorative gradient art with centered content on top. The art is hidden from
18
+ * assistive technology; only children are announced.
19
+ */
20
+ export declare function GradientBanner({ variant, size, texture, className, children, ...props }: GradientBannerProps): import("react").JSX.Element;
21
+ export interface GradientBannerPanelProps extends ComponentProps<"div"> {
22
+ /** `"light"` paper (default) or `"dark"` night surface. */
23
+ tone?: GradientBannerPanelTone | undefined;
24
+ }
25
+ /** A solid surface that keeps text readable on any banner variant. */
26
+ export declare function GradientBannerPanel({ tone, className, ...props }: GradientBannerPanelProps): import("react").JSX.Element;
27
+ /** A pill label that adapts to the panel tone around it. */
28
+ export declare function GradientBannerBadge({ className, ...props }: ComponentProps<"span">): import("react").JSX.Element;
29
+ export interface GradientBannerProgressProps extends Omit<ComponentProps<"div">, "children"> {
30
+ /** Percent complete. Values outside 0–100 are clamped. */
31
+ value: number;
32
+ }
33
+ /**
34
+ * A thin `progressbar` in the current text color. Name it with `aria-label`
35
+ * or `aria-labelledby`.
36
+ */
37
+ export declare function GradientBannerProgress({ value, className, style, ...props }: GradientBannerProgressProps): import("react").JSX.Element;
@@ -0,0 +1,43 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Children, useId } from "react";
3
+ import { cn } from "../internal/classes.js";
4
+ export const gradientBannerVariantNames = [
5
+ "aurora",
6
+ "citrus",
7
+ "lagoon",
8
+ "iris",
9
+ "cobalt",
10
+ "mint",
11
+ ];
12
+ export const gradientBannerSizeNames = ["sm", "md", "lg", "xl"];
13
+ export const gradientBannerPanelToneNames = ["light", "dark"];
14
+ /**
15
+ * Decorative gradient art with centered content on top. The art is hidden from
16
+ * assistive technology; only children are announced.
17
+ */
18
+ export function GradientBanner({ variant = "aurora", size = "lg", texture = true, className, children, ...props }) {
19
+ const grainId = useId();
20
+ const hasContent = Children.toArray(children).length > 0;
21
+ return (_jsxs("div", { "data-slot": "gradient-banner", "data-variant": variant, "data-size": size, ...props, className: cn("sprout-gradient-banner", className), children: [_jsxs("div", { "data-slot": "gradient-banner-art", className: "sprout-gradient-banner-art", "aria-hidden": "true", children: [_jsx("span", { className: "sprout-gradient-banner-fold" }), _jsx("span", { className: "sprout-gradient-banner-light" }), texture && (_jsxs("svg", { "data-slot": "gradient-banner-texture", className: "sprout-gradient-banner-texture", "aria-hidden": "true", focusable: "false", children: [_jsxs("filter", { id: grainId, x: "0%", y: "0%", width: "100%", height: "100%", children: [_jsx("feTurbulence", { type: "fractalNoise", baseFrequency: "0.82", numOctaves: "3", stitchTiles: "stitch", seed: "17" }), _jsx("feColorMatrix", { type: "saturate", values: "0" })] }), _jsx("rect", { width: "100%", height: "100%", filter: `url(#${grainId})` })] }))] }), hasContent && (_jsx("div", { "data-slot": "gradient-banner-content", className: "sprout-gradient-banner-content", children: children }))] }));
22
+ }
23
+ /** A solid surface that keeps text readable on any banner variant. */
24
+ export function GradientBannerPanel({ tone = "light", className, ...props }) {
25
+ return (_jsx("div", { "data-slot": "gradient-banner-panel", "data-tone": tone, ...props, className: cn("sprout-gradient-banner-panel", className) }));
26
+ }
27
+ /** A pill label that adapts to the panel tone around it. */
28
+ export function GradientBannerBadge({ className, ...props }) {
29
+ return (_jsx("span", { "data-slot": "gradient-banner-badge", ...props, className: cn("sprout-gradient-banner-badge", className) }));
30
+ }
31
+ /**
32
+ * A thin `progressbar` in the current text color. Name it with `aria-label`
33
+ * or `aria-labelledby`.
34
+ */
35
+ export function GradientBannerProgress({ value, className, style, ...props }) {
36
+ const percent = Number.isFinite(value)
37
+ ? Math.min(Math.max(value, 0), 100)
38
+ : 0;
39
+ return (_jsx("div", { "data-slot": "gradient-banner-progress", role: "progressbar", "aria-valuemin": 0, "aria-valuemax": 100, "aria-valuenow": Math.round(percent), ...props, style: {
40
+ ...style,
41
+ ["--sprout-gradient-banner-progress"]: percent / 100,
42
+ }, className: cn("sprout-gradient-banner-progress", className), children: _jsx("div", { className: "sprout-gradient-banner-progress-fill" }) }));
43
+ }
@@ -0,0 +1,27 @@
1
+ import { PreviewCard as PreviewCardPrimitive } from "@base-ui/react/preview-card";
2
+ export type HoverCardProps = PreviewCardPrimitive.Root.Props;
3
+ /**
4
+ * A card that previews what a link points to. It opens when the link is
5
+ * hovered or keyboard-focused and closes on Escape, blur, or pointer leave.
6
+ */
7
+ export declare function HoverCard(props: HoverCardProps): import("react").JSX.Element;
8
+ export type HoverCardTriggerProps = PreviewCardPrimitive.Trigger.Props;
9
+ /**
10
+ * The link that opens the card. It renders an `a` by default; pass your own
11
+ * link or router link through `render`. Takes `delay` (600ms) and
12
+ * `closeDelay` (300ms).
13
+ */
14
+ export declare function HoverCardTrigger({ className, ...props }: HoverCardTriggerProps): import("react").JSX.Element;
15
+ type PositionerProps = Pick<PreviewCardPrimitive.Positioner.Props, "align" | "alignOffset" | "side" | "sideOffset" | "anchor" | "collisionPadding" | "collisionAvoidance" | "sticky" | "positionMethod">;
16
+ export interface HoverCardContentProps extends PreviewCardPrimitive.Popup.Props, PositionerProps {
17
+ /** Keep the card in the DOM while closed. */
18
+ keepMounted?: PreviewCardPrimitive.Portal.Props["keepMounted"];
19
+ /** Where the portal renders. Defaults to `document.body`. */
20
+ container?: PreviewCardPrimitive.Portal.Props["container"];
21
+ }
22
+ /**
23
+ * The 16rem floating card. It renders its own portal and positioner, so place
24
+ * it directly inside `HoverCard`.
25
+ */
26
+ export declare function HoverCardContent({ side, sideOffset, align, alignOffset, collisionPadding, collisionAvoidance, sticky, positionMethod, anchor, keepMounted, container, className, ...props }: HoverCardContentProps): import("react").JSX.Element;
27
+ export {};
@@ -0,0 +1,26 @@
1
+ "use client";
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { PreviewCard as PreviewCardPrimitive } from "@base-ui/react/preview-card";
4
+ import { stateClassName } from "../internal/classes.js";
5
+ /**
6
+ * A card that previews what a link points to. It opens when the link is
7
+ * hovered or keyboard-focused and closes on Escape, blur, or pointer leave.
8
+ */
9
+ export function HoverCard(props) {
10
+ return _jsx(PreviewCardPrimitive.Root, { "data-slot": "hover-card", ...props });
11
+ }
12
+ /**
13
+ * The link that opens the card. It renders an `a` by default; pass your own
14
+ * link or router link through `render`. Takes `delay` (600ms) and
15
+ * `closeDelay` (300ms).
16
+ */
17
+ export function HoverCardTrigger({ className, ...props }) {
18
+ return (_jsx(PreviewCardPrimitive.Trigger, { "data-slot": "hover-card-trigger", ...props, className: stateClassName("sprout-hover-card-trigger", className) }));
19
+ }
20
+ /**
21
+ * The 16rem floating card. It renders its own portal and positioner, so place
22
+ * it directly inside `HoverCard`.
23
+ */
24
+ export function HoverCardContent({ side = "bottom", sideOffset = 4, align = "center", alignOffset = 4, collisionPadding = 8, collisionAvoidance, sticky, positionMethod, anchor, keepMounted = false, container, className, ...props }) {
25
+ return (_jsx(PreviewCardPrimitive.Portal, { "data-slot": "hover-card-portal", keepMounted: keepMounted, container: container, children: _jsx(PreviewCardPrimitive.Positioner, { className: "sprout-hover-card-positioner", anchor: anchor, align: align, alignOffset: alignOffset, side: side, sideOffset: sideOffset, collisionPadding: collisionPadding, collisionAvoidance: collisionAvoidance, sticky: sticky, positionMethod: positionMethod, children: _jsx(PreviewCardPrimitive.Popup, { "data-slot": "hover-card-content", ...props, className: stateClassName("sprout-hover-card-content", className) }) }) }));
26
+ }
@@ -0,0 +1,68 @@
1
+ import type { ComponentProps } from "react";
2
+ import { type ButtonProps } from "./button.js";
3
+ import { type InputProps } from "./input.js";
4
+ import { type TextareaProps } from "./textarea.js";
5
+ export declare const inputGroupSizeNames: readonly ["default", "lg"];
6
+ export declare const inputGroupVariantNames: readonly ["default", "composer", "question-composer"];
7
+ export declare const inputGroupAddonAlignNames: readonly ["inline-start", "inline-end", "block-start", "block-end"];
8
+ export declare const inputGroupButtonSizeNames: readonly ["xs", "sm", "icon-xs", "icon-sm"];
9
+ export type InputGroupSize = (typeof inputGroupSizeNames)[number];
10
+ export type InputGroupVariant = (typeof inputGroupVariantNames)[number];
11
+ export type InputGroupAddonAlign = (typeof inputGroupAddonAlignNames)[number];
12
+ export type InputGroupButtonSize = (typeof inputGroupButtonSizeNames)[number];
13
+ export interface InputGroupProps extends ComponentProps<"div"> {
14
+ /** `default` is 32px tall with 14px text. `lg` is 44px with 16px text. */
15
+ size?: InputGroupSize | null;
16
+ /**
17
+ * `default` is a single field row. `composer` stacks a message box with
18
+ * block additions on a raised card. `question-composer` is the same box
19
+ * with a quieter border while an agent question waits for an answer.
20
+ */
21
+ variant?: InputGroupVariant | null;
22
+ }
23
+ /**
24
+ * One bordered field made of a control and its additions: icons, text,
25
+ * shortcuts, and buttons. The group draws the border, fill, focus ring, and
26
+ * invalid and disabled states for the control inside it. Any element marked
27
+ * `data-slot="input-group-control"`, such as `InputGroupInput`,
28
+ * `InputGroupTextarea`, or a rich text editor, drives those states.
29
+ */
30
+ export declare function InputGroup({ size, variant, className, ...props }: InputGroupProps): import("react").JSX.Element;
31
+ export interface InputGroupAddonProps extends ComponentProps<"div"> {
32
+ /** Inline additions sit beside the control; block additions span a row above or below it. */
33
+ align?: InputGroupAddonAlign | null;
34
+ }
35
+ /**
36
+ * An icon, text, shortcut, or button area inside an `InputGroup`. It may come
37
+ * before or after the control in markup; `align` places it. Clicking anywhere
38
+ * in it except a button focuses the control, like a label.
39
+ */
40
+ export declare function InputGroupAddon({ align, className, onClick, ...props }: InputGroupAddonProps): import("react").JSX.Element;
41
+ export interface InputGroupButtonProps extends Omit<ButtonProps, "size" | "type"> {
42
+ /** `xs` and `sm` fit a label; `icon-xs` (24px) and `icon-sm` (28px) are square. */
43
+ size?: InputGroupButtonSize | null;
44
+ type?: "button" | "submit" | "reset";
45
+ }
46
+ /**
47
+ * A compact Sprout `Button` sized to sit inside an `InputGroup` addon. It is
48
+ * `ghost` and `xs` by default, and a plain `type="button"` so it never
49
+ * submits a form by accident. Use `render` to make it a menu, popover, or
50
+ * combobox trigger.
51
+ */
52
+ export declare function InputGroupButton({ size, variant, type, className, ...props }: InputGroupButtonProps): import("react").JSX.Element;
53
+ export type InputGroupTextProps = ComponentProps<"span">;
54
+ /** Muted text or an icon with text inside an addon, such as a URL prefix or a unit. */
55
+ export declare function InputGroupText({ className, ...props }: InputGroupTextProps): import("react").JSX.Element;
56
+ export type InputGroupInputProps = Omit<InputProps, "scale">;
57
+ /**
58
+ * A Sprout `Input` without its own border, fill, or ring, so the group draws
59
+ * them. It reads a surrounding `Field` the same way `Input` does.
60
+ */
61
+ export declare function InputGroupInput({ className, ...props }: InputGroupInputProps): import("react").JSX.Element;
62
+ export type InputGroupTextareaProps = Omit<TextareaProps, "variant">;
63
+ /**
64
+ * A Sprout `Textarea` without its own border, fill, or ring, so the group
65
+ * draws them. It grows with its content from a 96px floor and never resizes
66
+ * by hand.
67
+ */
68
+ export declare function InputGroupTextarea({ className, ...props }: InputGroupTextareaProps): import("react").JSX.Element;
@@ -0,0 +1,88 @@
1
+ "use client";
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { cn } from "../internal/classes.js";
4
+ import { Button } from "./button.js";
5
+ import { Input } from "./input.js";
6
+ import { Textarea } from "./textarea.js";
7
+ export const inputGroupSizeNames = ["default", "lg"];
8
+ export const inputGroupVariantNames = [
9
+ "default",
10
+ "composer",
11
+ "question-composer",
12
+ ];
13
+ export const inputGroupAddonAlignNames = [
14
+ "inline-start",
15
+ "inline-end",
16
+ "block-start",
17
+ "block-end",
18
+ ];
19
+ export const inputGroupButtonSizeNames = [
20
+ "xs",
21
+ "sm",
22
+ "icon-xs",
23
+ "icon-sm",
24
+ ];
25
+ /**
26
+ * One bordered field made of a control and its additions: icons, text,
27
+ * shortcuts, and buttons. The group draws the border, fill, focus ring, and
28
+ * invalid and disabled states for the control inside it. Any element marked
29
+ * `data-slot="input-group-control"`, such as `InputGroupInput`,
30
+ * `InputGroupTextarea`, or a rich text editor, drives those states.
31
+ */
32
+ export function InputGroup({ size, variant, className, ...props }) {
33
+ const scale = size ?? "default";
34
+ const kind = variant ?? "default";
35
+ return (_jsx("div", { "data-slot": "input-group", role: "group", "data-size": scale, "data-variant": kind, ...props, className: cn("sprout-input-group", `sprout-input-group-size-${scale}`, `sprout-input-group-variant-${kind}`, className) }));
36
+ }
37
+ const controlSelector = '[data-slot="input-group-control"], input, textarea, [contenteditable="true"]';
38
+ /**
39
+ * An icon, text, shortcut, or button area inside an `InputGroup`. It may come
40
+ * before or after the control in markup; `align` places it. Clicking anywhere
41
+ * in it except a button focuses the control, like a label.
42
+ */
43
+ export function InputGroupAddon({ align, className, onClick, ...props }) {
44
+ const side = align ?? "inline-start";
45
+ const focusControl = (event) => {
46
+ onClick?.(event);
47
+ if (event.defaultPrevented)
48
+ return;
49
+ const target = event.target;
50
+ if (target.closest("button, a[href], [role='button'], input, textarea"))
51
+ return;
52
+ const control = event.currentTarget.parentElement?.querySelector(controlSelector);
53
+ if (!control || control.matches(":disabled"))
54
+ return;
55
+ control.focus();
56
+ };
57
+ return (_jsx("div", { role: "group", "data-slot": "input-group-addon", "data-align": side, ...props, onClick: focusControl, className: cn("sprout-input-group-addon", `sprout-input-group-addon-align-${side}`, className) }));
58
+ }
59
+ /**
60
+ * A compact Sprout `Button` sized to sit inside an `InputGroup` addon. It is
61
+ * `ghost` and `xs` by default, and a plain `type="button"` so it never
62
+ * submits a form by accident. Use `render` to make it a menu, popover, or
63
+ * combobox trigger.
64
+ */
65
+ export function InputGroupButton({ size, variant, type = "button", className, ...props }) {
66
+ const scale = size ?? "xs";
67
+ const kind = variant ?? "ghost";
68
+ return (_jsx(Button, { type: type, variant: kind, "data-size": scale, "data-variant": kind, ...props, className: (state) => cn("sprout-input-group-button", `sprout-input-group-button-size-${scale}`, typeof className === "function" ? className(state) : className) }));
69
+ }
70
+ /** Muted text or an icon with text inside an addon, such as a URL prefix or a unit. */
71
+ export function InputGroupText({ className, ...props }) {
72
+ return (_jsx("span", { "data-slot": "input-group-text", ...props, className: cn("sprout-input-group-text", className) }));
73
+ }
74
+ /**
75
+ * A Sprout `Input` without its own border, fill, or ring, so the group draws
76
+ * them. It reads a surrounding `Field` the same way `Input` does.
77
+ */
78
+ export function InputGroupInput({ className, ...props }) {
79
+ return (_jsx(Input, { "data-slot": "input-group-control", ...props, className: (state) => cn("sprout-input-group-input", typeof className === "function" ? className(state) : className) }));
80
+ }
81
+ /**
82
+ * A Sprout `Textarea` without its own border, fill, or ring, so the group
83
+ * draws them. It grows with its content from a 96px floor and never resizes
84
+ * by hand.
85
+ */
86
+ export function InputGroupTextarea({ className, ...props }) {
87
+ return (_jsx(Textarea, { variant: "embedded", "data-slot": "input-group-control", ...props, className: cn("sprout-input-group-textarea", className) }));
88
+ }
@@ -0,0 +1,38 @@
1
+ import { type ComponentProps, type ReactNode } from "react";
2
+ import { OTPField } from "@base-ui/react/otp-field";
3
+ export type InputOTPState = OTPField.Root.State;
4
+ export type InputOTPSlotState = OTPField.Input.State;
5
+ type Invalid = boolean | "true" | "false" | "grammar" | "spelling";
6
+ export interface InputOTPProps extends Omit<OTPField.Root.Props, "length" | "aria-invalid" | "children"> {
7
+ /** Number of character slots. Matches the slot indexes you render. */
8
+ maxLength: number;
9
+ /** Called with the new code on every edit, paste, or autofill. */
10
+ onChange?: ((value: string) => void) | undefined;
11
+ /** Marks every slot invalid and draws the danger ring on its group. */
12
+ "aria-invalid"?: Invalid | undefined;
13
+ children?: ReactNode;
14
+ }
15
+ /**
16
+ * A one-time code field on Base UI `OTPField`. Each slot is a real input, so
17
+ * typing, paste, autofill (`autoComplete="one-time-code"`), arrow keys, Home,
18
+ * End, Backspace, and Delete all work. `aria-label` names the whole code and
19
+ * its first slot; later slots are announced as "Character 2 of 6".
20
+ */
21
+ export declare function InputOTP({ maxLength, onChange, onValueChange, className, children, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, "aria-invalid": ariaInvalid, validationType, ...props }: InputOTPProps): import("react").JSX.Element;
22
+ export type InputOTPGroupProps = ComponentProps<"div">;
23
+ /** Joins adjacent slots into one bordered segment. */
24
+ export declare function InputOTPGroup({ className, ...props }: InputOTPGroupProps): import("react").JSX.Element;
25
+ export interface InputOTPSlotProps extends Omit<OTPField.Input.Props, "aria-invalid"> {
26
+ /** Zero-based position of this slot in the code. */
27
+ index: number;
28
+ "aria-invalid"?: Invalid | undefined;
29
+ }
30
+ /**
31
+ * One character of the code. Render slots in index order; Base UI tracks
32
+ * focus and value by their DOM order.
33
+ */
34
+ export declare function InputOTPSlot({ index, className, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, "aria-invalid": ariaInvalid, ...props }: InputOTPSlotProps): import("react").JSX.Element;
35
+ export type InputOTPSeparatorProps = ComponentProps<typeof OTPField.Separator>;
36
+ /** A dash between slot groups, such as `123–456`. */
37
+ export declare function InputOTPSeparator({ className, children, ...props }: InputOTPSeparatorProps): import("react").JSX.Element;
38
+ export {};
@@ -0,0 +1,43 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { createContext, useContext, useId, } from "react";
4
+ import { OTPField } from "@base-ui/react/otp-field";
5
+ import { Minus } from "reicon-react/icons/Minus";
6
+ import { cn, stateClassName } from "../internal/classes.js";
7
+ const InputOTPContext = createContext(null);
8
+ const isInvalid = (value) => value === true || value === "true";
9
+ /**
10
+ * A one-time code field on Base UI `OTPField`. Each slot is a real input, so
11
+ * typing, paste, autofill (`autoComplete="one-time-code"`), arrow keys, Home,
12
+ * End, Backspace, and Delete all work. `aria-label` names the whole code and
13
+ * its first slot; later slots are announced as "Character 2 of 6".
14
+ */
15
+ export function InputOTP({ maxLength, onChange, onValueChange, className, children, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, "aria-invalid": ariaInvalid, validationType = "numeric", ...props }) {
16
+ const generated = useId();
17
+ const labelId = ariaLabelledBy ?? (ariaLabel ? `${generated}-label` : undefined);
18
+ const invalid = isInvalid(ariaInvalid);
19
+ return (_jsx(InputOTPContext.Provider, { value: { length: maxLength, labelId, invalid }, children: _jsxs(OTPField.Root, { "data-slot": "input-otp", "data-invalid": invalid ? "" : undefined, length: maxLength, validationType: validationType, "aria-labelledby": labelId, onValueChange: (value, details) => {
20
+ onValueChange?.(value, details);
21
+ onChange?.(value);
22
+ }, ...props, className: stateClassName("sprout-input-otp", className), children: [ariaLabel && !ariaLabelledBy ? (_jsx("span", { id: labelId, className: "sprout-input-otp-sr-only", children: ariaLabel })) : null, children] }) }));
23
+ }
24
+ /** Joins adjacent slots into one bordered segment. */
25
+ export function InputOTPGroup({ className, ...props }) {
26
+ return (_jsx("div", { "data-slot": "input-otp-group", ...props, className: cn("sprout-input-otp-group", className) }));
27
+ }
28
+ /**
29
+ * One character of the code. Render slots in index order; Base UI tracks
30
+ * focus and value by their DOM order.
31
+ */
32
+ export function InputOTPSlot({ index, className, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, "aria-invalid": ariaInvalid, ...props }) {
33
+ const context = useContext(InputOTPContext);
34
+ const length = context?.length ?? index + 1;
35
+ const invalid = ariaInvalid === undefined ? context?.invalid : isInvalid(ariaInvalid);
36
+ return (_jsx(OTPField.Input, { "data-slot": "input-otp-slot", "data-index": index, "aria-labelledby": ariaLabelledBy ?? (index === 0 ? context?.labelId : undefined), "aria-label": index === 0
37
+ ? undefined
38
+ : (ariaLabel ?? `Character ${index + 1} of ${length}`), "aria-invalid": invalid || undefined, ...props, className: stateClassName("sprout-input-otp-slot", className) }));
39
+ }
40
+ /** A dash between slot groups, such as `123–456`. */
41
+ export function InputOTPSeparator({ className, children, ...props }) {
42
+ return (_jsx(OTPField.Separator, { "data-slot": "input-otp-separator", orientation: "vertical", ...props, className: stateClassName("sprout-input-otp-separator", className), children: children ?? _jsx(Minus, { "aria-hidden": "true" }) }));
43
+ }
@@ -0,0 +1,16 @@
1
+ import { Input as BaseInput } from "@base-ui/react/input";
2
+ export declare const inputScaleNames: readonly ["default", "lg"];
3
+ export type InputScale = (typeof inputScaleNames)[number];
4
+ export type InputState = BaseInput.State;
5
+ export interface InputProps extends BaseInput.Props {
6
+ /** `default` is 32px tall with 14px text. `lg` is 44px with 16px text. */
7
+ scale?: InputScale | null;
8
+ }
9
+ /**
10
+ * A single-line text field on Base UI `Input`. It takes every native input
11
+ * prop, such as `type`, `value`, `required`, and `ref`. Inside a Base UI
12
+ * `Field.Root` it gets its id, label, description, and invalid and disabled
13
+ * states from the field. Inside a Sprout `Field` it reads the same from
14
+ * `useFieldControl`.
15
+ */
16
+ export declare function Input({ scale, className, ...rest }: InputProps): import("react").JSX.Element;
@@ -0,0 +1,18 @@
1
+ "use client";
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { Input as BaseInput } from "@base-ui/react/input";
4
+ import { cn, stateClassName } from "../internal/classes.js";
5
+ import { useFieldControl } from "./field.js";
6
+ export const inputScaleNames = ["default", "lg"];
7
+ /**
8
+ * A single-line text field on Base UI `Input`. It takes every native input
9
+ * prop, such as `type`, `value`, `required`, and `ref`. Inside a Base UI
10
+ * `Field.Root` it gets its id, label, description, and invalid and disabled
11
+ * states from the field. Inside a Sprout `Field` it reads the same from
12
+ * `useFieldControl`.
13
+ */
14
+ export function Input({ scale, className, ...rest }) {
15
+ const props = useFieldControl(rest);
16
+ const size = scale ?? "default";
17
+ return (_jsx(BaseInput, { "data-slot": "input", "data-scale": size, ...props, className: stateClassName(cn("sprout-input", `sprout-input-scale-${size}`), className) }));
18
+ }
@@ -0,0 +1,12 @@
1
+ import type { ComponentProps } from "react";
2
+ export declare const kbdVariantNames: readonly ["default", "outline"];
3
+ export type KbdVariant = (typeof kbdVariantNames)[number];
4
+ export interface KbdProps extends ComponentProps<"kbd"> {
5
+ /** `"outline"` adds a border on the surface color, for hints on tinted strips and selected rows. */
6
+ variant?: KbdVariant;
7
+ }
8
+ /** One keyboard key, such as `⌘`, `Enter`, or `Esc`. */
9
+ export declare function Kbd({ variant, className, ...props }: KbdProps): import("react").JSX.Element;
10
+ export type KbdGroupProps = ComponentProps<"kbd">;
11
+ /** Keys pressed together, such as `⌘` `K`. */
12
+ export declare function KbdGroup({ className, ...props }: KbdGroupProps): import("react").JSX.Element;
@@ -0,0 +1,11 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { cn } from "../internal/classes.js";
3
+ export const kbdVariantNames = ["default", "outline"];
4
+ /** One keyboard key, such as `⌘`, `Enter`, or `Esc`. */
5
+ export function Kbd({ variant = "default", className, ...props }) {
6
+ return (_jsx("kbd", { "data-slot": "kbd", "data-variant": variant, className: cn("sprout-kbd", className), ...props }));
7
+ }
8
+ /** Keys pressed together, such as `⌘` `K`. */
9
+ export function KbdGroup({ className, ...props }) {
10
+ return (_jsx("kbd", { "data-slot": "kbd-group", className: cn("sprout-kbd-group", className), ...props }));
11
+ }
@@ -0,0 +1,8 @@
1
+ import type { ComponentProps } from "react";
2
+ export type LabelProps = ComponentProps<"label">;
3
+ /**
4
+ * Names one form control. Point `htmlFor` at a control's `id`, or wrap a
5
+ * checkbox, switch, or radio with its text. A label wrapping a text control,
6
+ * such as a textarea, stacks the text above it.
7
+ */
8
+ export declare function Label({ className, ...props }: LabelProps): import("react").JSX.Element;
@@ -0,0 +1,10 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { cn } from "../internal/classes.js";
3
+ /**
4
+ * Names one form control. Point `htmlFor` at a control's `id`, or wrap a
5
+ * checkbox, switch, or radio with its text. A label wrapping a text control,
6
+ * such as a textarea, stacks the text above it.
7
+ */
8
+ export function Label({ className, ...props }) {
9
+ return (_jsx("label", { "data-slot": "label", className: cn("sprout-label", className), ...props }));
10
+ }
@@ -0,0 +1,54 @@
1
+ import { type ComponentProps, type ReactNode } from "react";
2
+ export declare const mentionStatusToneNames: readonly ["loading", "empty", "error"];
3
+ export type MentionStatusTone = (typeof mentionStatusToneNames)[number];
4
+ export interface MentionListProps extends Omit<ComponentProps<"div">, "id" | "children"> {
5
+ /** The listbox id. Point the text field's `aria-controls` at it. */
6
+ id: string;
7
+ /** Names the listbox, such as “Files you can add”. */
8
+ label: string;
9
+ /** One or more `MentionStatus` rows shown under the options. */
10
+ status?: ReactNode;
11
+ /**
12
+ * Read by screen readers when it changes. A textarea keeps its textbox
13
+ * role, so this tells people the panel opened and how to use it.
14
+ */
15
+ announcement?: string | undefined;
16
+ /** `MentionOption` rows, or `MentionGroup`s of them. */
17
+ children?: ReactNode;
18
+ }
19
+ /**
20
+ * A suggestion panel for `@` and `/` triggers. The text field keeps focus and
21
+ * owns the arrow keys; it points `aria-activedescendant` at the active option.
22
+ */
23
+ export declare function MentionList({ id, label, status, announcement, children, className, ...props }: MentionListProps): import("react").JSX.Element;
24
+ export interface MentionOptionProps extends Omit<ComponentProps<"li">, "id" | "title" | "children" | "onSelect"> {
25
+ /** Unique id the text field uses in `aria-activedescendant`. */
26
+ id: string;
27
+ /** The keyboard-highlighted option. It scrolls into view when it becomes active. */
28
+ active: boolean;
29
+ onSelect: () => void;
30
+ /** A 16px icon, file icon, brand glyph, or small avatar. */
31
+ media?: ReactNode;
32
+ title: string;
33
+ description?: string | undefined;
34
+ }
35
+ export declare function MentionOption({ id, active, onSelect, media, title, description, className, ...props }: MentionOptionProps): import("react").JSX.Element;
36
+ export interface MentionGroupProps {
37
+ /** The source, such as “Files” or “Google Drive”. */
38
+ label: string;
39
+ children: ReactNode;
40
+ }
41
+ /** A labelled run of options inside the same listbox, so arrow keys move across groups. */
42
+ export declare function MentionGroup({ label, children }: MentionGroupProps): import("react").JSX.Element;
43
+ export interface MentionStatusAction {
44
+ label: string;
45
+ onAction: () => void;
46
+ }
47
+ export interface MentionStatusProps {
48
+ /** `loading` adds a spinner; `error` is an alert in the danger color. */
49
+ tone: MentionStatusTone;
50
+ children: ReactNode;
51
+ /** A small outline button, usually Retry. */
52
+ action?: MentionStatusAction | undefined;
53
+ }
54
+ export declare function MentionStatus({ tone, children, action }: MentionStatusProps): import("react").JSX.Element;