@tulipfarm/sprout 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (349) hide show
  1. package/README.md +45 -40
  2. package/dist/components/accordion.d.ts +2 -2
  3. package/dist/components/accordion.js +9 -9
  4. package/dist/components/agent-fanout.d.ts +2 -2
  5. package/dist/components/agent-fanout.js +65 -87
  6. package/dist/components/alert-dialog.d.ts +6 -6
  7. package/dist/components/alert-dialog.js +20 -20
  8. package/dist/components/alert.d.ts +6 -6
  9. package/dist/components/alert.js +13 -13
  10. package/dist/components/aspect-ratio.d.ts +2 -2
  11. package/dist/components/aspect-ratio.js +2 -2
  12. package/dist/components/attachment.d.ts +17 -17
  13. package/dist/components/attachment.js +82 -115
  14. package/dist/components/avatar.d.ts +10 -10
  15. package/dist/components/avatar.js +14 -14
  16. package/dist/components/badge.d.ts +4 -4
  17. package/dist/components/badge.js +18 -18
  18. package/dist/components/board.d.ts +107 -0
  19. package/dist/components/board.js +640 -0
  20. package/dist/components/brand-icon.d.ts +6 -6
  21. package/dist/components/brand-icon.js +55 -63
  22. package/dist/components/breadcrumb.d.ts +11 -11
  23. package/dist/components/breadcrumb.js +16 -18
  24. package/dist/components/button-group.d.ts +6 -6
  25. package/dist/components/button-group.js +14 -14
  26. package/dist/components/button.d.ts +11 -11
  27. package/dist/components/button.js +46 -56
  28. package/dist/components/calendar.d.ts +5 -5
  29. package/dist/components/calendar.js +44 -53
  30. package/dist/components/canvas.d.ts +4 -4
  31. package/dist/components/canvas.js +39 -46
  32. package/dist/components/card.d.ts +6 -6
  33. package/dist/components/card.js +17 -17
  34. package/dist/components/carousel.d.ts +7 -7
  35. package/dist/components/carousel.js +57 -75
  36. package/dist/components/chart.d.ts +5 -112
  37. package/dist/components/chart.js +5 -172
  38. package/dist/components/chat-confirmation.d.ts +13 -11
  39. package/dist/components/chat-confirmation.js +32 -38
  40. package/dist/components/chat-input.d.ts +4 -4
  41. package/dist/components/chat-input.js +74 -81
  42. package/dist/components/chat-plan.d.ts +2 -2
  43. package/dist/components/chat-plan.js +15 -20
  44. package/dist/components/chat-sources.d.ts +8 -8
  45. package/dist/components/chat-sources.js +18 -27
  46. package/dist/components/checkbox.d.ts +1 -1
  47. package/dist/components/checkbox.js +9 -9
  48. package/dist/components/choice-list.d.ts +2 -2
  49. package/dist/components/choice-list.js +16 -18
  50. package/dist/components/code-block.d.ts +5 -5
  51. package/dist/components/code-block.js +26 -26
  52. package/dist/components/collapsible.d.ts +1 -1
  53. package/dist/components/collapsible.js +7 -11
  54. package/dist/components/combobox.d.ts +3 -3
  55. package/dist/components/combobox.js +24 -24
  56. package/dist/components/command.d.ts +13 -13
  57. package/dist/components/command.js +61 -73
  58. package/dist/components/context-menu.d.ts +5 -5
  59. package/dist/components/context-menu.js +22 -22
  60. package/dist/components/dialog.d.ts +6 -6
  61. package/dist/components/dialog.js +23 -28
  62. package/dist/components/direction.d.ts +1 -1
  63. package/dist/components/direction.js +1 -1
  64. package/dist/components/dropdown-menu.d.ts +5 -5
  65. package/dist/components/dropdown-menu.js +20 -20
  66. package/dist/components/field.d.ts +11 -11
  67. package/dist/components/field.js +41 -61
  68. package/dist/components/file-explorer.d.ts +2 -2
  69. package/dist/components/file-explorer.js +89 -105
  70. package/dist/components/file-viewer.d.ts +10 -10
  71. package/dist/components/file-viewer.js +112 -140
  72. package/dist/components/form.d.ts +7 -7
  73. package/dist/components/form.js +24 -28
  74. package/dist/components/glass-banner.d.ts +3 -3
  75. package/dist/components/glass-banner.js +21 -24
  76. package/dist/components/gradient-banner.d.ts +5 -5
  77. package/dist/components/gradient-banner.js +13 -22
  78. package/dist/components/hover-card.d.ts +4 -4
  79. package/dist/components/hover-card.js +6 -6
  80. package/dist/components/input-group.d.ts +11 -11
  81. package/dist/components/input-group.js +22 -36
  82. package/dist/components/input-otp.d.ts +10 -10
  83. package/dist/components/input-otp.js +13 -15
  84. package/dist/components/input.d.ts +1 -1
  85. package/dist/components/input.js +7 -7
  86. package/dist/components/kbd.d.ts +3 -3
  87. package/dist/components/kbd.js +5 -5
  88. package/dist/components/label.d.ts +2 -2
  89. package/dist/components/label.js +2 -2
  90. package/dist/components/mention-list.d.ts +3 -3
  91. package/dist/components/mention-list.js +10 -10
  92. package/dist/components/menubar.d.ts +6 -6
  93. package/dist/components/menubar.js +22 -22
  94. package/dist/components/message-actions.d.ts +2 -2
  95. package/dist/components/message-actions.js +29 -31
  96. package/dist/components/message-response.d.ts +3 -3
  97. package/dist/components/message-response.js +18 -18
  98. package/dist/components/message-scroller.d.ts +12 -12
  99. package/dist/components/message-scroller.js +44 -56
  100. package/dist/components/message.d.ts +11 -11
  101. package/dist/components/message.js +25 -25
  102. package/dist/components/navigation-menu.d.ts +2 -2
  103. package/dist/components/navigation-menu.js +15 -15
  104. package/dist/components/notice-banner.d.ts +2 -2
  105. package/dist/components/notice-banner.js +2 -2
  106. package/dist/components/page-content.d.ts +2 -2
  107. package/dist/components/page-content.js +2 -2
  108. package/dist/components/page-header.d.ts +1 -1
  109. package/dist/components/page-header.js +16 -16
  110. package/dist/components/pagination.d.ts +9 -9
  111. package/dist/components/pagination.js +17 -17
  112. package/dist/components/plan-outline.d.ts +2 -2
  113. package/dist/components/plan-outline.js +43 -60
  114. package/dist/components/popover.d.ts +6 -6
  115. package/dist/components/popover.js +15 -15
  116. package/dist/components/presence-cursor.d.ts +2 -2
  117. package/dist/components/presence-cursor.js +3 -3
  118. package/dist/components/progress.d.ts +1 -1
  119. package/dist/components/progress.js +8 -8
  120. package/dist/components/prompt-list.d.ts +3 -3
  121. package/dist/components/prompt-list.js +6 -6
  122. package/dist/components/questionnaire.d.ts +19 -19
  123. package/dist/components/questionnaire.js +183 -242
  124. package/dist/components/radio-group.d.ts +2 -2
  125. package/dist/components/radio-group.js +6 -6
  126. package/dist/components/reasoning-effort.d.ts +3 -3
  127. package/dist/components/reasoning-effort.js +9 -12
  128. package/dist/components/record-list.d.ts +66 -0
  129. package/dist/components/record-list.js +151 -0
  130. package/dist/components/resizable.d.ts +5 -5
  131. package/dist/components/resizable.js +76 -102
  132. package/dist/components/result-card.d.ts +10 -5
  133. package/dist/components/result-card.js +42 -53
  134. package/dist/components/result-notice.d.ts +18 -0
  135. package/dist/components/result-notice.js +29 -0
  136. package/dist/components/review-card.d.ts +6 -6
  137. package/dist/components/review-card.js +18 -18
  138. package/dist/components/rich-text-editor.d.ts +2 -2
  139. package/dist/components/rich-text-editor.js +56 -72
  140. package/dist/components/schema-diagram.d.ts +3 -3
  141. package/dist/components/schema-diagram.js +39 -53
  142. package/dist/components/scroll-area.d.ts +1 -1
  143. package/dist/components/scroll-area.js +10 -14
  144. package/dist/components/search-dialog.d.ts +6 -6
  145. package/dist/components/search-dialog.js +16 -16
  146. package/dist/components/search-field.d.ts +1 -1
  147. package/dist/components/search-field.js +11 -11
  148. package/dist/components/select.d.ts +3 -3
  149. package/dist/components/select.js +20 -20
  150. package/dist/components/selection-slot.d.ts +2 -2
  151. package/dist/components/selection-slot.js +6 -9
  152. package/dist/components/separator.d.ts +15 -15
  153. package/dist/components/separator.js +22 -27
  154. package/dist/components/settings-list.d.ts +3 -3
  155. package/dist/components/settings-list.js +5 -5
  156. package/dist/components/sheet.d.ts +6 -6
  157. package/dist/components/sheet.js +27 -27
  158. package/dist/components/sidebar.d.ts +22 -22
  159. package/dist/components/sidebar.js +57 -58
  160. package/dist/components/skeleton.d.ts +5 -5
  161. package/dist/components/skeleton.js +14 -21
  162. package/dist/components/slider.d.ts +2 -2
  163. package/dist/components/slider.js +6 -6
  164. package/dist/components/spinner.d.ts +5 -5
  165. package/dist/components/spinner.js +22 -26
  166. package/dist/components/sql-viewer.d.ts +14 -14
  167. package/dist/components/sql-viewer.js +99 -128
  168. package/dist/components/state-panel-samples.d.ts +2 -2
  169. package/dist/components/state-panel-samples.js +209 -245
  170. package/dist/components/state-panel.d.ts +2 -35
  171. package/dist/components/state-panel.js +2 -29
  172. package/dist/components/state-sample.d.ts +7 -7
  173. package/dist/components/state-sample.js +18 -31
  174. package/dist/components/switch.d.ts +1 -1
  175. package/dist/components/switch.js +7 -7
  176. package/dist/components/table-nuqs.d.ts +2 -2
  177. package/dist/components/table-nuqs.js +11 -12
  178. package/dist/components/table.d.ts +4 -4
  179. package/dist/components/table.js +166 -235
  180. package/dist/components/tabs.d.ts +2 -2
  181. package/dist/components/tabs.js +12 -12
  182. package/dist/components/textarea.d.ts +2 -2
  183. package/dist/components/textarea.js +6 -8
  184. package/dist/components/timeline.d.ts +3 -0
  185. package/dist/components/timeline.js +3 -0
  186. package/dist/components/toast.d.ts +2 -2
  187. package/dist/components/toast.js +19 -25
  188. package/dist/components/toggle-group.d.ts +2 -2
  189. package/dist/components/toggle-group.js +18 -20
  190. package/dist/components/toggle.d.ts +2 -2
  191. package/dist/components/toggle.js +8 -8
  192. package/dist/components/tool-activity.d.ts +1 -1
  193. package/dist/components/tool-activity.js +83 -110
  194. package/dist/components/toolbar-status.d.ts +2 -2
  195. package/dist/components/toolbar-status.js +7 -7
  196. package/dist/components/tooltip.d.ts +5 -5
  197. package/dist/components/tooltip.js +12 -11
  198. package/dist/components/typed-text.d.ts +2 -2
  199. package/dist/components/typed-text.js +10 -12
  200. package/dist/components/view-switcher.d.ts +51 -0
  201. package/dist/components/view-switcher.js +114 -0
  202. package/dist/index.d.ts +98 -93
  203. package/dist/index.js +98 -93
  204. package/dist/internal/chart-kit.d.ts +142 -0
  205. package/dist/internal/chart-kit.js +200 -0
  206. package/dist/internal/charts/bars.d.ts +61 -0
  207. package/dist/internal/charts/bars.js +86 -0
  208. package/dist/internal/charts/lines.d.ts +67 -0
  209. package/dist/internal/charts/lines.js +70 -0
  210. package/dist/internal/charts/more.d.ts +77 -0
  211. package/dist/internal/charts/more.js +68 -0
  212. package/dist/internal/charts/parts.d.ts +54 -0
  213. package/dist/internal/charts/parts.js +82 -0
  214. package/dist/internal/charts/timeline-dates.d.ts +38 -0
  215. package/dist/internal/charts/timeline-dates.js +113 -0
  216. package/dist/internal/charts/timeline-window.d.ts +31 -0
  217. package/dist/internal/charts/timeline-window.js +26 -0
  218. package/dist/internal/charts/timeline.d.ts +72 -0
  219. package/dist/internal/charts/timeline.js +287 -0
  220. package/dist/internal/classes.d.ts +1 -1
  221. package/dist/internal/classes.js +7 -9
  222. package/dist/internal/code-tokens.d.ts +2 -2
  223. package/dist/internal/code-tokens.js +12 -12
  224. package/dist/internal/fieldset.d.ts +1 -1
  225. package/dist/internal/fieldset.js +6 -6
  226. package/dist/internal/file-kind.d.ts +1 -1
  227. package/dist/internal/file-kind.js +43 -51
  228. package/dist/internal/flow.d.ts +4 -4
  229. package/dist/internal/flow.js +20 -23
  230. package/dist/internal/languages.js +999 -999
  231. package/dist/internal/message-scroller.d.ts +3 -3
  232. package/dist/internal/message-scroller.js +64 -112
  233. package/dist/internal/pressable.d.ts +1 -1
  234. package/dist/internal/pressable.js +7 -7
  235. package/dist/internal/state-panel.d.ts +35 -0
  236. package/dist/internal/state-panel.js +22 -0
  237. package/dist/internal/syntax.d.ts +2 -2
  238. package/dist/internal/syntax.js +36 -47
  239. package/dist/styles/accordion.css +3 -5
  240. package/dist/styles/agent-fanout.css +64 -60
  241. package/dist/styles/alert-dialog.css +12 -26
  242. package/dist/styles/alert.css +10 -15
  243. package/dist/styles/attachment.css +51 -93
  244. package/dist/styles/avatar.css +17 -24
  245. package/dist/styles/badge.css +11 -36
  246. package/dist/styles/board.css +571 -0
  247. package/dist/styles/brand-icon.css +7 -8
  248. package/dist/styles/breadcrumb.css +4 -7
  249. package/dist/styles/button-group.css +8 -14
  250. package/dist/styles/button.css +22 -27
  251. package/dist/styles/calendar.css +24 -36
  252. package/dist/styles/canvas.css +2 -3
  253. package/dist/styles/card.css +7 -23
  254. package/dist/styles/carousel.css +11 -12
  255. package/dist/styles/chart.css +215 -31
  256. package/dist/styles/chat-input.css +15 -39
  257. package/dist/styles/chat-plan.css +3 -4
  258. package/dist/styles/chat-sources.css +3 -6
  259. package/dist/styles/checkbox.css +11 -25
  260. package/dist/styles/choice-list.css +17 -31
  261. package/dist/styles/code-block.css +11 -25
  262. package/dist/styles/collapsible.css +10 -15
  263. package/dist/styles/combobox.css +11 -15
  264. package/dist/styles/command.css +5 -8
  265. package/dist/styles/context-menu.css +2 -2
  266. package/dist/styles/dialog.css +5 -16
  267. package/dist/styles/dropdown-menu.css +2 -2
  268. package/dist/styles/field.css +15 -21
  269. package/dist/styles/file-explorer.css +19 -33
  270. package/dist/styles/file-viewer.css +13 -17
  271. package/dist/styles/form.css +3 -3
  272. package/dist/styles/glass-banner.css +12 -47
  273. package/dist/styles/gradient-banner.css +17 -35
  274. package/dist/styles/hover-card.css +9 -15
  275. package/dist/styles/index.css +116 -108
  276. package/dist/styles/input-group.css +25 -41
  277. package/dist/styles/input-otp.css +5 -6
  278. package/dist/styles/input.css +5 -5
  279. package/dist/styles/kbd.css +1 -1
  280. package/dist/styles/label.css +9 -30
  281. package/dist/styles/mention-list.css +6 -8
  282. package/dist/styles/menubar.css +5 -6
  283. package/dist/styles/message-actions.css +1 -1
  284. package/dist/styles/message-response.css +3 -5
  285. package/dist/styles/message-scroller.css +14 -21
  286. package/dist/styles/message.css +23 -60
  287. package/dist/styles/navigation-menu.css +14 -29
  288. package/dist/styles/notice-banner.css +1 -2
  289. package/dist/styles/page-header.css +7 -10
  290. package/dist/styles/pagination.css +1 -4
  291. package/dist/styles/plan-outline.css +20 -37
  292. package/dist/styles/popover.css +10 -19
  293. package/dist/styles/presence-cursor.css +1 -2
  294. package/dist/styles/progress.css +2 -4
  295. package/dist/styles/prompt-list.css +6 -17
  296. package/dist/styles/questionnaire.css +16 -40
  297. package/dist/styles/radio-group.css +12 -23
  298. package/dist/styles/reasoning-effort.css +8 -15
  299. package/dist/styles/record-list.css +243 -0
  300. package/dist/styles/resizable.css +10 -11
  301. package/dist/styles/result-card.css +17 -3
  302. package/dist/styles/result-notice.css +80 -0
  303. package/dist/styles/review-card.css +2 -3
  304. package/dist/styles/rich-text-editor.css +1 -2
  305. package/dist/styles/schema-diagram.css +12 -17
  306. package/dist/styles/scroll-area.css +8 -10
  307. package/dist/styles/search-dialog.css +1 -5
  308. package/dist/styles/search-field.css +1 -2
  309. package/dist/styles/select.css +7 -7
  310. package/dist/styles/selection-slot.css +1 -2
  311. package/dist/styles/separator.css +7 -8
  312. package/dist/styles/settings-list.css +1 -2
  313. package/dist/styles/sheet.css +40 -73
  314. package/dist/styles/sidebar.css +17 -21
  315. package/dist/styles/skeleton.css +9 -11
  316. package/dist/styles/slider.css +11 -21
  317. package/dist/styles/spinner.css +2 -2
  318. package/dist/styles/sql-viewer.css +29 -29
  319. package/dist/styles/state-panel.css +8 -9
  320. package/dist/styles/state-sample.css +20 -33
  321. package/dist/styles/switch.css +11 -18
  322. package/dist/styles/table.css +51 -77
  323. package/dist/styles/tabs.css +12 -16
  324. package/dist/styles/textarea.css +3 -3
  325. package/dist/styles/themes/chatgpt.css +11 -23
  326. package/dist/styles/themes/claude.css +12 -24
  327. package/dist/styles/themes/cloudflare.css +11 -23
  328. package/dist/styles/themes/discord.css +11 -23
  329. package/dist/styles/themes/github.css +11 -23
  330. package/dist/styles/themes/grok.css +11 -23
  331. package/dist/styles/themes/linear.css +12 -25
  332. package/dist/styles/themes/neutral.css +11 -23
  333. package/dist/styles/themes/notion.css +11 -23
  334. package/dist/styles/themes/perplexity.css +11 -23
  335. package/dist/styles/themes/raycast.css +11 -23
  336. package/dist/styles/themes/spotify.css +11 -23
  337. package/dist/styles/themes/stripe.css +11 -23
  338. package/dist/styles/themes/supabase.css +11 -23
  339. package/dist/styles/themes/tulipfarm.css +9 -10
  340. package/dist/styles/themes/vercel.css +12 -25
  341. package/dist/styles/timeline.css +276 -0
  342. package/dist/styles/toast.css +13 -20
  343. package/dist/styles/toggle-group.css +17 -23
  344. package/dist/styles/toggle.css +8 -8
  345. package/dist/styles/tool-activity.css +7 -13
  346. package/dist/styles/toolbar-status.css +2 -7
  347. package/dist/styles/tooltip.css +15 -21
  348. package/dist/styles/view-switcher.css +279 -0
  349. package/package.json +21 -1
@@ -1,57 +1,52 @@
1
- "use client";
1
+ 'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
- import { mergeProps } from "@base-ui/react/merge-props";
4
- import { useRender } from "@base-ui/react/use-render";
5
- import { createContext, useCallback, useContext, useId, useLayoutEffect, useMemo, useRef, useState, } from "react";
6
- import { Check } from "reicon-react/icons/Check";
7
- import { cn } from "../internal/classes.js";
8
- import { buttonVariants, } from "./button.js";
9
- import { Kbd } from "./kbd.js";
10
- export const questionnaireItemStatusNames = [
11
- "unanswered",
12
- "answered",
13
- "skipped",
14
- ];
15
- export const questionnaireShortcutModeNames = ["letters", "numbers"];
3
+ import { mergeProps } from '@base-ui/react/merge-props';
4
+ import { useRender } from '@base-ui/react/use-render';
5
+ import { createContext, useCallback, useContext, useId, useLayoutEffect, useMemo, useRef, useState, } from 'react';
6
+ import { Check } from 'reicon-react/icons/Check';
7
+ import { cn } from '../internal/classes.js';
8
+ import { buttonVariants } from './button.js';
9
+ import { Kbd } from './kbd.js';
10
+ export const questionnaireItemStatusNames = ['unanswered', 'answered', 'skipped'];
11
+ export const questionnaireShortcutModeNames = ['letters', 'numbers'];
16
12
  function hasText(value) {
17
13
  return Array.isArray(value)
18
- ? value.some((part) => String(part).trim().length > 0)
14
+ ? value.some(part => String(part).trim().length > 0)
19
15
  : value != null && String(value).trim().length > 0;
20
16
  }
21
17
  function shortcutKeys(mode) {
22
- if (mode === "letters")
18
+ if (mode === 'letters')
23
19
  return Array.from({ length: 26 }, (_, index) => String.fromCharCode(65 + index));
24
- if (mode === "numbers")
20
+ if (mode === 'numbers')
25
21
  return Array.from({ length: 9 }, (_, index) => String(index + 1));
26
22
  return [];
27
23
  }
28
24
  function shortcutFromKey(key, mode) {
29
- const normalized = mode === "letters" ? key.toUpperCase() : key;
25
+ const normalized = mode === 'letters' ? key.toUpperCase() : key;
30
26
  return shortcutKeys(mode).includes(normalized) ? normalized : null;
31
27
  }
32
28
  function keyShortcuts(shortcut, enter) {
33
- return ([shortcut, enter ? "Enter" : null].filter(Boolean).join(" ") || undefined);
29
+ return [shortcut, enter ? 'Enter' : null].filter(Boolean).join(' ') || undefined;
34
30
  }
35
31
  function isAnswered(control) {
36
- return control.type === "choice"
32
+ return control.type === 'choice'
37
33
  ? control.element.checked
38
- : control.element.hasAttribute("name") && hasText(control.element.value);
34
+ : control.element.hasAttribute('name') && hasText(control.element.value);
39
35
  }
40
36
  function isEmptyTextInput(control) {
41
- return (control?.type === "input" &&
42
- ["email", "password", "search", "tel", "text", "url"].includes(control.element.type) &&
37
+ return (control?.type === 'input' &&
38
+ ['email', 'password', 'search', 'tel', 'text', 'url'].includes(control.element.type) &&
43
39
  !hasText(control.element.value));
44
40
  }
45
41
  function isTextEntry(element) {
46
- if (element instanceof HTMLTextAreaElement ||
47
- element instanceof HTMLSelectElement)
42
+ if (element instanceof HTMLTextAreaElement || element instanceof HTMLSelectElement)
48
43
  return true;
49
44
  if (element instanceof HTMLInputElement)
50
- return !["button", "checkbox", "radio", "reset", "submit"].includes(element.type);
45
+ return !['button', 'checkbox', 'radio', 'reset', 'submit'].includes(element.type);
51
46
  return element instanceof HTMLElement && element.isContentEditable;
52
47
  }
53
48
  function isRadio(element) {
54
- return element instanceof HTMLInputElement && element.type === "radio";
49
+ return element instanceof HTMLInputElement && element.type === 'radio';
55
50
  }
56
51
  function byDocumentOrder(a, b) {
57
52
  if (a.element === b.element)
@@ -64,7 +59,7 @@ function byDocumentOrder(a, b) {
64
59
  return 0;
65
60
  }
66
61
  function assignRef(ref, value) {
67
- if (typeof ref === "function")
62
+ if (typeof ref === 'function')
68
63
  ref(value);
69
64
  else if (ref)
70
65
  ref.current = value;
@@ -72,12 +67,8 @@ function assignRef(ref, value) {
72
67
  function initialItem(definitions, defaultItem) {
73
68
  if (!definitions)
74
69
  return defaultItem ?? null;
75
- const match = defaultItem
76
- ? definitions.itemByName.get(defaultItem)
77
- : undefined;
78
- return match && !match.disabled
79
- ? match.name
80
- : (definitions.enabledItems[0]?.name ?? null);
70
+ const match = defaultItem ? definitions.itemByName.get(defaultItem) : undefined;
71
+ return match && !match.disabled ? match.name : (definitions.enabledItems[0]?.name ?? null);
81
72
  }
82
73
  function shortcutsForDefinition(definition, mode) {
83
74
  const map = new Map();
@@ -120,8 +111,8 @@ export function Questionnaire({ className, defaultItem, item, items, noValidate
120
111
  ? null
121
112
  : {
122
113
  items,
123
- enabledItems: items.filter((entry) => !entry.disabled),
124
- itemByName: new Map(items.map((entry) => [entry.name, entry])),
114
+ enabledItems: items.filter(entry => !entry.disabled),
115
+ itemByName: new Map(items.map(entry => [entry.name, entry])),
125
116
  }, [items]);
126
117
  const [registered, setRegistered] = useState([]);
127
118
  const [internalItem, setInternalItem] = useState(() => initialItem(definitions, defaultItem));
@@ -134,32 +125,24 @@ export function Questionnaire({ className, defaultItem, item, items, noValidate
134
125
  const nativeValidation = noValidate === false;
135
126
  const shortcutMode = shortcuts ?? null;
136
127
  useLayoutEffect(() => {
137
- if (!form || typeof MutationObserver === "undefined")
128
+ if (!form || typeof MutationObserver === 'undefined')
138
129
  return;
139
- const observer = new MutationObserver(() => setDomVersion((version) => version + 1));
130
+ const observer = new MutationObserver(() => setDomVersion(version => version + 1));
140
131
  observer.observe(form, { childList: true, subtree: true });
141
132
  return () => observer.disconnect();
142
133
  }, [form]);
143
- const enabledRegistered = useMemo(() => registered.filter((entry) => !entry.disabled).sort(byDocumentOrder),
134
+ const enabledRegistered = useMemo(() => registered.filter(entry => !entry.disabled).sort(byDocumentOrder),
144
135
  // eslint-disable-next-line react-hooks/exhaustive-deps
145
136
  [registered, domVersion]);
146
- const registeredByName = useMemo(() => new Map(enabledRegistered.map((entry) => [entry.name, entry])), [enabledRegistered]);
137
+ const registeredByName = useMemo(() => new Map(enabledRegistered.map(entry => [entry.name, entry])), [enabledRegistered]);
147
138
  const sequence = definitions?.enabledItems ?? enabledRegistered;
148
- const index = sequence.findIndex((entry) => entry.name === activeName);
149
- const active = index < 0 || !activeName
150
- ? null
151
- : (registeredByName.get(activeName) ?? null);
152
- const activeDefinition = activeName
153
- ? definitions?.itemByName.get(activeName)
154
- : undefined;
155
- const activeRequired = index < 0
156
- ? null
157
- : activeDefinition
158
- ? !!activeDefinition.required
159
- : (active?.required ?? false);
160
- const activeStatus = index < 0 ? null : (active?.status ?? (activeName ? "unanswered" : null));
139
+ const index = sequence.findIndex(entry => entry.name === activeName);
140
+ const active = index < 0 || !activeName ? null : (registeredByName.get(activeName) ?? null);
141
+ const activeDefinition = activeName ? definitions?.itemByName.get(activeName) : undefined;
142
+ const activeRequired = index < 0 ? null : activeDefinition ? !!activeDefinition.required : (active?.required ?? false);
143
+ const activeStatus = index < 0 ? null : (active?.status ?? (activeName ? 'unanswered' : null));
161
144
  const ordered = useMemo(() => definitions
162
- ? definitions.enabledItems.flatMap((entry) => {
145
+ ? definitions.enabledItems.flatMap(entry => {
163
146
  const match = registeredByName.get(entry.name);
164
147
  return match ? [match] : [];
165
148
  })
@@ -168,7 +151,7 @@ export function Questionnaire({ className, defaultItem, item, items, noValidate
168
151
  const current = index < 0 ? 0 : index + 1;
169
152
  const first = total > 0 && index === 0;
170
153
  const last = total > 0 && index === total - 1;
171
- const go = useCallback((name, target = "item") => {
154
+ const go = useCallback((name, target = 'item') => {
172
155
  if (name === activeName)
173
156
  return;
174
157
  pending.current = { name, target };
@@ -197,18 +180,18 @@ export function Questionnaire({ className, defaultItem, item, items, noValidate
197
180
  }
198
181
  return;
199
182
  }
200
- if (request.target === "invalid")
183
+ if (request.target === 'invalid')
201
184
  active?.focusInvalid();
202
185
  else
203
186
  active?.focus();
204
187
  pending.current = null;
205
188
  }, [active, activeName, controlled, index, sequence, go, total]);
206
189
  const registerItem = useCallback((entry) => {
207
- setRegistered((list) => [
208
- ...list.filter((other) => other.element !== entry.element && other.name !== entry.name),
190
+ setRegistered(list => [
191
+ ...list.filter(other => other.element !== entry.element && other.name !== entry.name),
209
192
  entry,
210
193
  ]);
211
- return () => setRegistered((list) => list.filter((other) => other !== entry));
194
+ return () => setRegistered(list => list.filter(other => other !== entry));
212
195
  }, []);
213
196
  const goPrevious = useCallback(() => {
214
197
  if (index <= 0)
@@ -255,16 +238,15 @@ export function Questionnaire({ className, defaultItem, item, items, noValidate
255
238
  entry.reset();
256
239
  const target = definitions
257
240
  ? initialItem(definitions, defaultItem)
258
- : (enabledRegistered.find((entry) => entry.name === defaultItem)?.name ??
259
- enabledRegistered[0]?.name);
241
+ : (enabledRegistered.find(entry => entry.name === defaultItem)?.name ?? enabledRegistered[0]?.name);
260
242
  if (target)
261
243
  go(target);
262
244
  }
263
245
  function handleSubmit(event) {
264
- const invalid = ordered.find((entry) => !entry.validate());
246
+ const invalid = ordered.find(entry => !entry.validate());
265
247
  if (invalid) {
266
248
  event.preventDefault();
267
- go(invalid.name, "invalid");
249
+ go(invalid.name, 'invalid');
268
250
  if (invalid.name === activeName) {
269
251
  invalid.focusInvalid();
270
252
  pending.current = null;
@@ -281,10 +263,7 @@ export function Questionnaire({ className, defaultItem, item, items, noValidate
281
263
  !active ||
282
264
  !(target instanceof Element))
283
265
  return;
284
- if (event.key === "Enter" &&
285
- (event.metaKey || event.ctrlKey) &&
286
- !event.altKey &&
287
- !event.shiftKey) {
266
+ if (event.key === 'Enter' && (event.metaKey || event.ctrlKey) && !event.altKey && !event.shiftKey) {
288
267
  event.preventDefault();
289
268
  if (!event.repeat)
290
269
  advance();
@@ -292,24 +271,22 @@ export function Questionnaire({ className, defaultItem, item, items, noValidate
292
271
  }
293
272
  if (event.metaKey || event.ctrlKey || event.altKey)
294
273
  return;
295
- if ((event.key === "ArrowUp" || event.key === "ArrowDown") &&
296
- active.moveAnswerFocus(target, event.key === "ArrowDown" ? "next" : "previous")) {
274
+ if ((event.key === 'ArrowUp' || event.key === 'ArrowDown') &&
275
+ active.moveAnswerFocus(target, event.key === 'ArrowDown' ? 'next' : 'previous')) {
297
276
  event.preventDefault();
298
277
  return;
299
278
  }
300
- if ((event.key === "ArrowLeft" || event.key === "ArrowRight") &&
301
- !isTextEntry(target) &&
302
- !isRadio(target)) {
279
+ if ((event.key === 'ArrowLeft' || event.key === 'ArrowRight') && !isTextEntry(target) && !isRadio(target)) {
303
280
  event.preventDefault();
304
281
  if (event.repeat)
305
282
  return;
306
- if (event.key === "ArrowLeft")
283
+ if (event.key === 'ArrowLeft')
307
284
  goPrevious();
308
- else if (active.status !== "unanswered")
285
+ else if (active.status !== 'unanswered')
309
286
  goNext();
310
287
  return;
311
288
  }
312
- if (event.key === "Enter") {
289
+ if (event.key === 'Enter') {
313
290
  const control = active.getAnswerByElement(target);
314
291
  if (!control)
315
292
  return;
@@ -328,7 +305,7 @@ export function Questionnaire({ className, defaultItem, item, items, noValidate
328
305
  if (event.repeat)
329
306
  return;
330
307
  control.element.focus();
331
- if (control.type === "choice")
308
+ if (control.type === 'choice')
332
309
  control.element.click();
333
310
  }
334
311
  const context = useMemo(() => ({
@@ -369,11 +346,11 @@ export function Questionnaire({ className, defaultItem, item, items, noValidate
369
346
  assignRef(ref, element);
370
347
  }, [ref]);
371
348
  const element = useRender({
372
- defaultTagName: "form",
349
+ defaultTagName: 'form',
373
350
  props: mergeProps({
374
- "data-slot": "questionnaire",
375
- "data-shortcuts": shortcutMode ?? undefined,
376
- className: cn("sprout-questionnaire", className),
351
+ 'data-slot': 'questionnaire',
352
+ 'data-shortcuts': shortcutMode ?? undefined,
353
+ className: cn('sprout-questionnaire', className),
377
354
  noValidate,
378
355
  onKeyDown: handleKeyDown,
379
356
  onReset: handleReset,
@@ -386,30 +363,30 @@ export function Questionnaire({ className, defaultItem, item, items, noValidate
386
363
  }
387
364
  /** "Question 2 of 3", announced politely as the step changes. */
388
365
  export function QuestionnaireProgress({ children, className, render, ...props }) {
389
- const { current, first, last, total } = useRoot("QuestionnaireProgress");
366
+ const { current, first, last, total } = useRoot('QuestionnaireProgress');
390
367
  const text = total ? `Question ${current} of ${total}` : undefined;
391
368
  return useRender({
392
- defaultTagName: "div",
369
+ defaultTagName: 'div',
393
370
  render,
394
371
  props: mergeProps({
395
- "data-slot": "questionnaire-progress",
396
- className: cn("sprout-questionnaire-progress", className),
397
- role: "progressbar",
398
- "aria-label": "Questionnaire progress",
399
- "aria-live": "polite",
400
- "aria-valuemin": total ? 1 : undefined,
401
- "aria-valuemax": total || undefined,
402
- "aria-valuenow": total ? current : undefined,
403
- "aria-valuetext": text,
372
+ 'data-slot': 'questionnaire-progress',
373
+ className: cn('sprout-questionnaire-progress', className),
374
+ role: 'progressbar',
375
+ 'aria-label': 'Questionnaire progress',
376
+ 'aria-live': 'polite',
377
+ 'aria-valuemin': total ? 1 : undefined,
378
+ 'aria-valuemax': total || undefined,
379
+ 'aria-valuenow': total ? current : undefined,
380
+ 'aria-valuetext': text,
404
381
  children: children ?? text,
405
382
  }, props),
406
383
  state: { current, first, last, total },
407
384
  });
408
385
  }
409
386
  /** One question. Only the current item is shown; the rest are hidden and inert. */
410
- export function QuestionnaireItem({ "aria-describedby": ariaDescribedBy, "aria-keyshortcuts": ariaKeyShortcuts, children, className, disabled = false, invalid = false, multiple = false, name, onStatusChange, ref, required = false, ...props }) {
411
- const root = useRoot("QuestionnaireItem");
412
- const { activeItemName, domVersion, first, last, itemDefinitionByName, nativeValidation, registerItem, shortcuts, } = root;
387
+ export function QuestionnaireItem({ 'aria-describedby': ariaDescribedBy, 'aria-keyshortcuts': ariaKeyShortcuts, children, className, disabled = false, invalid = false, multiple = false, name, onStatusChange, ref, required = false, ...props }) {
388
+ const root = useRoot('QuestionnaireItem');
389
+ const { activeItemName, domVersion, first, last, itemDefinitionByName, nativeValidation, registerItem, shortcuts } = root;
413
390
  const [element, setElement] = useState(null);
414
391
  const [controls, setControls] = useState([]);
415
392
  const [attempted, setAttempted] = useState(false);
@@ -426,30 +403,22 @@ export function QuestionnaireItem({ "aria-describedby": ariaDescribedBy, "aria-k
426
403
  const sorted = useMemo(() => [...controls].sort(byDocumentOrder),
427
404
  // eslint-disable-next-line react-hooks/exhaustive-deps
428
405
  [controls, domVersion]);
429
- const enabled = useMemo(() => sorted.filter((control) => !control.disabled), [sorted]);
430
- const answered = enabled.some((control) => selected.includes(control.id));
431
- const status = skipped
432
- ? "skipped"
433
- : answered
434
- ? "answered"
435
- : "unanswered";
436
- const skippedOptional = status === "skipped" && !required;
437
- const valid = disabled || skippedOptional || (!invalid && status === "answered");
406
+ const enabled = useMemo(() => sorted.filter(control => !control.disabled), [sorted]);
407
+ const answered = enabled.some(control => selected.includes(control.id));
408
+ const status = skipped ? 'skipped' : answered ? 'answered' : 'unanswered';
409
+ const skippedOptional = status === 'skipped' && !required;
410
+ const valid = disabled || skippedOptional || (!invalid && status === 'answered');
438
411
  const showInvalid = !disabled && !skippedOptional && (invalid || (attempted && !valid));
439
- const hasInputAnswer = enabled.some((control) => control.type === "input");
412
+ const hasInputAnswer = enabled.some(control => control.type === 'input');
440
413
  const lastStatus = useRef(status);
441
414
  const definition = itemDefinitionByName?.get(name);
442
- const shortcutByChoiceValue = useMemo(() => itemDefinitionByName
443
- ? shortcutsForDefinition(definition, shortcuts)
444
- : null, [definition, itemDefinitionByName, shortcuts]);
415
+ const shortcutByChoiceValue = useMemo(() => (itemDefinitionByName ? shortcutsForDefinition(definition, shortcuts) : null), [definition, itemDefinitionByName, shortcuts]);
445
416
  const shortcutByAnswerId = useMemo(() => {
446
417
  if (shortcutByChoiceValue)
447
418
  return new Map();
448
419
  const keys = shortcutKeys(shortcuts);
449
- const choices = enabled.filter((control) => control.type === "choice");
450
- return new Map(choices
451
- .slice(0, keys.length)
452
- .map((control, position) => [control.id, keys[position]]));
420
+ const choices = enabled.filter(control => control.type === 'choice');
421
+ return new Map(choices.slice(0, keys.length).map((control, position) => [control.id, keys[position]]));
453
422
  }, [enabled, shortcutByChoiceValue, shortcuts]);
454
423
  useLayoutEffect(() => {
455
424
  if (lastStatus.current === status)
@@ -458,16 +427,16 @@ export function QuestionnaireItem({ "aria-describedby": ariaDescribedBy, "aria-k
458
427
  onStatusChange?.(status);
459
428
  }, [onStatusChange, status]);
460
429
  const registerAnswerControl = useCallback((control) => {
461
- setControls((list) => [
462
- ...list.filter((other) => other.element !== control.element && other.id !== control.id),
430
+ setControls(list => [
431
+ ...list.filter(other => other.element !== control.element && other.id !== control.id),
463
432
  control,
464
433
  ]);
465
- return () => setControls((list) => list.filter((other) => other !== control));
434
+ return () => setControls(list => list.filter(other => other !== control));
466
435
  }, []);
467
436
  const select = useCallback((id, on) => {
468
- setSelected((list) => {
437
+ setSelected(list => {
469
438
  if (!on)
470
- return list.filter((other) => other !== id);
439
+ return list.filter(other => other !== id);
471
440
  if (!multiple)
472
441
  return [id];
473
442
  return list.includes(id) ? list : [...list, id];
@@ -484,19 +453,16 @@ export function QuestionnaireItem({ "aria-describedby": ariaDescribedBy, "aria-k
484
453
  }, [select]);
485
454
  const registerAnswerSelection = useCallback((id, initial) => {
486
455
  if (initial) {
487
- defaults.current = [
488
- ...defaults.current.filter((other) => other !== id),
489
- id,
490
- ];
491
- setSelected((list) => {
456
+ defaults.current = [...defaults.current.filter(other => other !== id), id];
457
+ setSelected(list => {
492
458
  if (multipleRef.current)
493
459
  return list.includes(id) ? list : [...list, id];
494
460
  return list.length ? list : [id];
495
461
  });
496
462
  }
497
463
  return () => {
498
- defaults.current = defaults.current.filter((other) => other !== id);
499
- setSelected((list) => list.filter((other) => other !== id));
464
+ defaults.current = defaults.current.filter(other => other !== id);
465
+ setSelected(list => list.filter(other => other !== id));
500
466
  };
501
467
  }, []);
502
468
  const setAnswerDefault = useCallback((id, on) => {
@@ -505,15 +471,15 @@ export function QuestionnaireItem({ "aria-describedby": ariaDescribedBy, "aria-k
505
471
  defaults.current = [...defaults.current, id];
506
472
  return;
507
473
  }
508
- defaults.current = defaults.current.filter((other) => other !== id);
474
+ defaults.current = defaults.current.filter(other => other !== id);
509
475
  }, []);
510
476
  const registerDescription = useCallback((id) => {
511
- setDescriptionIds((list) => (list.includes(id) ? list : [...list, id]));
512
- return () => setDescriptionIds((list) => list.filter((other) => other !== id));
477
+ setDescriptionIds(list => (list.includes(id) ? list : [...list, id]));
478
+ return () => setDescriptionIds(list => list.filter(other => other !== id));
513
479
  }, []);
514
480
  const registerError = useCallback((id) => {
515
- setErrorIds((list) => (list.includes(id) ? list : [...list, id]));
516
- return () => setErrorIds((list) => list.filter((other) => other !== id));
481
+ setErrorIds(list => (list.includes(id) ? list : [...list, id]));
482
+ return () => setErrorIds(list => list.filter(other => other !== id));
517
483
  }, []);
518
484
  const validate = useCallback(() => {
519
485
  setAttempted(true);
@@ -521,9 +487,7 @@ export function QuestionnaireItem({ "aria-describedby": ariaDescribedBy, "aria-k
521
487
  return false;
522
488
  if (!nativeValidation)
523
489
  return true;
524
- const failing = enabled.find((control) => isAnswered(control) &&
525
- control.element.willValidate &&
526
- !control.element.validity.valid);
490
+ const failing = enabled.find(control => isAnswered(control) && control.element.willValidate && !control.element.validity.valid);
527
491
  if (!failing)
528
492
  return true;
529
493
  failing.element.focus();
@@ -532,15 +496,15 @@ export function QuestionnaireItem({ "aria-describedby": ariaDescribedBy, "aria-k
532
496
  }, [enabled, nativeValidation, valid]);
533
497
  const focus = useCallback(() => element?.focus(), [element]);
534
498
  const focusInvalid = useCallback(() => {
535
- const filled = element?.querySelector("input[data-filled][name]:not(:disabled)");
536
- const firstField = element?.querySelector("input:not([type=hidden]):not(:disabled), textarea:not(:disabled)");
499
+ const filled = element?.querySelector('input[data-filled][name]:not(:disabled)');
500
+ const firstField = element?.querySelector('input:not([type=hidden]):not(:disabled), textarea:not(:disabled)');
537
501
  (filled ?? firstField ?? element)?.focus();
538
502
  }, [element]);
539
503
  const reset = useCallback(() => {
540
504
  setAttempted(false);
541
505
  setSkipped(false);
542
506
  setSelected(multiple ? [...defaults.current] : defaults.current.slice(0, 1));
543
- setResetVersion((version) => version + 1);
507
+ setResetVersion(version => version + 1);
544
508
  }, [multiple]);
545
509
  const skip = useCallback(() => {
546
510
  if (required)
@@ -553,38 +517,34 @@ export function QuestionnaireItem({ "aria-describedby": ariaDescribedBy, "aria-k
553
517
  previousMultiple.current = multiple;
554
518
  if (!wasMultiple || multiple)
555
519
  return;
556
- setSelected((list) => {
557
- const keep = enabled.find((control) => list.includes(control.id));
520
+ setSelected(list => {
521
+ const keep = enabled.find(control => list.includes(control.id));
558
522
  return keep ? [keep.id] : [];
559
523
  });
560
524
  }, [enabled, multiple]);
561
- const getAnswerByElement = useCallback((target) => enabled.find((control) => control.element === target) ?? null, [enabled]);
525
+ const getAnswerByElement = useCallback((target) => enabled.find(control => control.element === target) ?? null, [enabled]);
562
526
  const getAnswerByShortcut = useCallback((shortcut) => {
563
527
  if (shortcutByChoiceValue) {
564
528
  const value = [...shortcutByChoiceValue.entries()].find(([, key]) => key === shortcut)?.[0];
565
- return (enabled.find((control) => control.type === "choice" && control.value === value) ?? null);
529
+ return enabled.find(control => control.type === 'choice' && control.value === value) ?? null;
566
530
  }
567
531
  const id = [...shortcutByAnswerId.entries()].find(([, key]) => key === shortcut)?.[0];
568
- return enabled.find((control) => control.id === id) ?? null;
532
+ return enabled.find(control => control.id === id) ?? null;
569
533
  }, [enabled, shortcutByAnswerId, shortcutByChoiceValue]);
570
534
  const moveAnswerFocus = useCallback((target, direction) => {
571
- const position = enabled.findIndex((control) => control.element === target);
535
+ const position = enabled.findIndex(control => control.element === target);
572
536
  const currentControl = position < 0 ? null : (enabled[position] ?? null);
573
537
  if (!enabled.length ||
574
538
  (isTextEntry(target) && !isEmptyTextInput(currentControl)) ||
575
539
  (position < 0 && target !== element))
576
540
  return false;
577
541
  const next = position < 0
578
- ? (enabled.find(isAnswered) ??
579
- (direction === "next" ? enabled[0] : enabled[enabled.length - 1]))
580
- : enabled[(position + (direction === "next" ? 1 : -1) + enabled.length) %
581
- enabled.length];
582
- if (!next ||
583
- next.element === target ||
584
- (position >= 0 && isRadio(target) && isRadio(next.element)))
542
+ ? (enabled.find(isAnswered) ?? (direction === 'next' ? enabled[0] : enabled[enabled.length - 1]))
543
+ : enabled[(position + (direction === 'next' ? 1 : -1) + enabled.length) % enabled.length];
544
+ if (!next || next.element === target || (position >= 0 && isRadio(target) && isRadio(next.element)))
585
545
  return false;
586
546
  next.element.focus();
587
- if (next.type === "choice" && isRadio(next.element))
547
+ if (next.type === 'choice' && isRadio(next.element))
588
548
  next.element.click();
589
549
  return true;
590
550
  }, [element, enabled]);
@@ -597,9 +557,7 @@ export function QuestionnaireItem({ "aria-describedby": ariaDescribedBy, "aria-k
597
557
  disabled,
598
558
  required,
599
559
  status,
600
- choices: sorted.flatMap((control) => control.type === "choice"
601
- ? [{ value: control.value, disabled: control.ownDisabled }]
602
- : []),
560
+ choices: sorted.flatMap(control => control.type === 'choice' ? [{ value: control.value, disabled: control.ownDisabled }] : []),
603
561
  focus,
604
562
  focusInvalid,
605
563
  validate,
@@ -669,18 +627,16 @@ export function QuestionnaireItem({ "aria-describedby": ariaDescribedBy, "aria-k
669
627
  setElement(node);
670
628
  assignRef(ref, node);
671
629
  }, [ref]);
672
- const describedBy = [...descriptionIds, ...(showInvalid ? errorIds : []), ariaDescribedBy]
673
- .filter(Boolean)
674
- .join(" ") || undefined;
630
+ const describedBy = [...descriptionIds, ...(showInvalid ? errorIds : []), ariaDescribedBy].filter(Boolean).join(' ') || undefined;
675
631
  const itemShortcuts = [
676
632
  ariaKeyShortcuts,
677
- active ? "Meta+Enter Control+Enter" : undefined,
678
- active && enabled.length ? "ArrowUp ArrowDown" : undefined,
679
- active && !first ? "ArrowLeft" : undefined,
680
- active && !last && status !== "unanswered" ? "ArrowRight" : undefined,
633
+ active ? 'Meta+Enter Control+Enter' : undefined,
634
+ active && enabled.length ? 'ArrowUp ArrowDown' : undefined,
635
+ active && !first ? 'ArrowLeft' : undefined,
636
+ active && !last && status !== 'unanswered' ? 'ArrowRight' : undefined,
681
637
  ]
682
638
  .filter(Boolean)
683
- .join(" ") || undefined;
639
+ .join(' ') || undefined;
684
640
  const state = {
685
641
  active,
686
642
  disabled,
@@ -689,46 +645,46 @@ export function QuestionnaireItem({ "aria-describedby": ariaDescribedBy, "aria-k
689
645
  required,
690
646
  status,
691
647
  };
692
- return (_jsx(ItemContext.Provider, { value: context, children: _jsx("fieldset", { "data-slot": "questionnaire-item", "data-active": active ? "" : undefined, "data-disabled": disabled ? "" : undefined, "data-invalid": showInvalid ? "" : undefined, "data-multiple": multiple ? "" : undefined, "data-required": required ? "" : undefined, "data-status": state.status, ...props, ref: handleRef, className: cn("sprout-questionnaire-item", className), "aria-describedby": describedBy, "aria-invalid": showInvalid || undefined, "aria-keyshortcuts": itemShortcuts, disabled: disabled, hidden: !active, inert: !active, tabIndex: -1, children: children }) }));
648
+ return (_jsx(ItemContext.Provider, { value: context, children: _jsx("fieldset", { "data-slot": "questionnaire-item", "data-active": active ? '' : undefined, "data-disabled": disabled ? '' : undefined, "data-invalid": showInvalid ? '' : undefined, "data-multiple": multiple ? '' : undefined, "data-required": required ? '' : undefined, "data-status": state.status, ...props, ref: handleRef, className: cn('sprout-questionnaire-item', className), "aria-describedby": describedBy, "aria-invalid": showInvalid || undefined, "aria-keyshortcuts": itemShortcuts, disabled: disabled, hidden: !active, inert: !active, tabIndex: -1, children: children }) }));
693
649
  }
694
650
  /** The question, as the item's `legend`. */
695
651
  export function QuestionnaireTitle({ className, render, ...props }) {
696
- useItem("QuestionnaireTitle");
652
+ useItem('QuestionnaireTitle');
697
653
  return useRender({
698
- defaultTagName: "legend",
654
+ defaultTagName: 'legend',
699
655
  render,
700
656
  props: mergeProps({
701
- "data-slot": "questionnaire-title",
702
- className: cn("sprout-questionnaire-title", className),
657
+ 'data-slot': 'questionnaire-title',
658
+ className: cn('sprout-questionnaire-title', className),
703
659
  }, props),
704
660
  });
705
661
  }
706
662
  /** Help text under the question. The item references it with `aria-describedby`. */
707
663
  export function QuestionnaireDescription({ className, id, render, ...props }) {
708
- const { registerDescription } = useItem("QuestionnaireDescription");
664
+ const { registerDescription } = useItem('QuestionnaireDescription');
709
665
  const generated = useId();
710
666
  const resolved = id ?? generated;
711
667
  useLayoutEffect(() => registerDescription(resolved), [resolved, registerDescription]);
712
668
  return useRender({
713
- defaultTagName: "p",
669
+ defaultTagName: 'p',
714
670
  render,
715
671
  props: mergeProps({
716
- "data-slot": "questionnaire-description",
672
+ 'data-slot': 'questionnaire-description',
717
673
  id: resolved,
718
- className: cn("sprout-questionnaire-description", className),
674
+ className: cn('sprout-questionnaire-description', className),
719
675
  }, props),
720
676
  });
721
677
  }
722
678
  /** Stacks the item's choices. */
723
679
  export function QuestionnaireChoices({ className, render, ...props }) {
724
- useItem("QuestionnaireChoices");
725
- const { shortcuts } = useRoot("QuestionnaireChoices");
680
+ useItem('QuestionnaireChoices');
681
+ const { shortcuts } = useRoot('QuestionnaireChoices');
726
682
  return useRender({
727
- defaultTagName: "div",
683
+ defaultTagName: 'div',
728
684
  render,
729
685
  props: mergeProps({
730
- "data-slot": "questionnaire-choices",
731
- className: cn("sprout-questionnaire-choices", className),
686
+ 'data-slot': 'questionnaire-choices',
687
+ className: cn('sprout-questionnaire-choices', className),
732
688
  }, props),
733
689
  state: { shortcuts },
734
690
  });
@@ -738,19 +694,15 @@ export function QuestionnaireChoices({ className, render, ...props }) {
738
694
  * `multiple` items; the whole row is the hit area.
739
695
  */
740
696
  export function QuestionnaireChoice({ checked, children, className, defaultChecked = false, disabled: ownDisabled = false, onChange, render, value, ...props }) {
741
- const item = useItem("QuestionnaireChoice");
697
+ const item = useItem('QuestionnaireChoice');
742
698
  const { disabled: itemDisabled, hasInputAnswer, invalid, multiple, name, registerAnswerControl, registerAnswerSelection, required, resetVersion, selectedAnswerIds, setAnswerDefault, setAnswerSelectionFromInteraction, shortcutByAnswerId, shortcutByChoiceValue, status, syncControlledAnswerSelection, } = item;
743
699
  const id = useId();
744
700
  const [input, setInput] = useState(null);
745
701
  const initialChecked = useRef(defaultChecked);
746
702
  const controlled = checked !== undefined;
747
703
  const disabled = itemDisabled || ownDisabled;
748
- const isChecked = controlled
749
- ? status === "skipped"
750
- ? false
751
- : checked
752
- : selectedAnswerIds.includes(id);
753
- const type = multiple ? "checkbox" : "radio";
704
+ const isChecked = controlled ? (status === 'skipped' ? false : checked) : selectedAnswerIds.includes(id);
705
+ const type = multiple ? 'checkbox' : 'radio';
754
706
  const shortcut = shortcutByChoiceValue?.get(value) ?? shortcutByAnswerId.get(id) ?? null;
755
707
  useLayoutEffect(() => registerAnswerSelection(id, initialChecked.current), [id, registerAnswerSelection]);
756
708
  useLayoutEffect(() => setAnswerDefault(id, defaultChecked), [id, defaultChecked, setAnswerDefault]);
@@ -758,7 +710,7 @@ export function QuestionnaireChoice({ checked, children, className, defaultCheck
758
710
  if (!input)
759
711
  return;
760
712
  return registerAnswerControl({
761
- type: "choice",
713
+ type: 'choice',
762
714
  id,
763
715
  element: input,
764
716
  disabled,
@@ -785,7 +737,7 @@ export function QuestionnaireChoice({ checked, children, className, defaultCheck
785
737
  setAnswerSelectionFromInteraction(id, event.target.checked);
786
738
  return;
787
739
  }
788
- if (status === "skipped" && checked === event.target.checked)
740
+ if (status === 'skipped' && checked === event.target.checked)
789
741
  setAnswerSelectionFromInteraction(id, checked);
790
742
  }
791
743
  const state = {
@@ -796,29 +748,29 @@ export function QuestionnaireChoice({ checked, children, className, defaultCheck
796
748
  type,
797
749
  };
798
750
  return useRender({
799
- defaultTagName: "label",
751
+ defaultTagName: 'label',
800
752
  render,
801
753
  props: mergeProps({
802
- "data-slot": "questionnaire-choice",
803
- className: cn("sprout-questionnaire-choice", className),
804
- children: (_jsxs(_Fragment, { children: [_jsx("input", { "data-slot": "questionnaire-choice-input", className: "sprout-questionnaire-choice-input", ref: setInput, id: id, type: type, name: status === "skipped" ? undefined : name, value: value, checked: isChecked, disabled: disabled, required: required && !multiple && !hasInputAnswer, "aria-invalid": invalid || undefined, "aria-keyshortcuts": keyShortcuts(shortcut, !disabled && isChecked), "data-checked": isChecked ? "" : undefined, "data-unchecked": isChecked ? undefined : "", onChange: handleChange }), _jsxs("span", { "aria-hidden": "true", "data-slot": "questionnaire-choice-indicator", className: "sprout-questionnaire-choice-indicator", children: [_jsx("span", { className: "sprout-questionnaire-choice-dot" }), _jsx(Check, { className: "sprout-questionnaire-choice-check" })] }), _jsx("span", { "data-slot": "questionnaire-choice-label", className: "sprout-questionnaire-choice-label", children: children }), shortcut !== null && (_jsx(Kbd, { variant: "outline", "aria-hidden": "true", "data-slot": "questionnaire-choice-shortcut", className: "sprout-questionnaire-choice-shortcut", children: shortcut }))] })),
754
+ 'data-slot': 'questionnaire-choice',
755
+ className: cn('sprout-questionnaire-choice', className),
756
+ children: (_jsxs(_Fragment, { children: [_jsx("input", { "data-slot": "questionnaire-choice-input", className: "sprout-questionnaire-choice-input", ref: setInput, id: id, type: type, name: status === 'skipped' ? undefined : name, value: value, checked: isChecked, disabled: disabled, required: required && !multiple && !hasInputAnswer, "aria-invalid": invalid || undefined, "aria-keyshortcuts": keyShortcuts(shortcut, !disabled && isChecked), "data-checked": isChecked ? '' : undefined, "data-unchecked": isChecked ? undefined : '', onChange: handleChange }), _jsxs("span", { "aria-hidden": "true", "data-slot": "questionnaire-choice-indicator", className: "sprout-questionnaire-choice-indicator", children: [_jsx("span", { className: "sprout-questionnaire-choice-dot" }), _jsx(Check, { className: "sprout-questionnaire-choice-check" })] }), _jsx("span", { "data-slot": "questionnaire-choice-label", className: "sprout-questionnaire-choice-label", children: children }), shortcut !== null && (_jsx(Kbd, { variant: "outline", "aria-hidden": "true", "data-slot": "questionnaire-choice-shortcut", className: "sprout-questionnaire-choice-shortcut", children: shortcut }))] })),
805
757
  }, props),
806
758
  state,
807
759
  stateAttributesMapping: {
808
- checked: (on) => on ? { "data-checked": "" } : { "data-unchecked": "" },
760
+ checked: (on) => (on ? { 'data-checked': '' } : { 'data-unchecked': '' }),
809
761
  },
810
762
  });
811
763
  }
812
764
  /** A muted second line inside a choice. */
813
765
  export function QuestionnaireChoiceDescription({ className, ...props }) {
814
- return (_jsx("span", { "data-slot": "questionnaire-choice-description", className: cn("sprout-questionnaire-choice-description", className), ...props }));
766
+ return (_jsx("span", { "data-slot": "questionnaire-choice-description", className: cn('sprout-questionnaire-choice-description', className), ...props }));
815
767
  }
816
768
  /**
817
769
  * A typed answer. It counts as answered once it has text, and is only sent
818
770
  * with the form while it does.
819
771
  */
820
- export function QuestionnaireInput({ className, defaultValue, disabled: ownDisabled = false, onChange, ref, render, type = "text", value, ...props }) {
821
- const { disabled: itemDisabled, invalid, name, registerAnswerControl, registerAnswerSelection, resetVersion, selectedAnswerIds, setAnswerDefault, setAnswerSelectionFromInteraction, syncControlledAnswerSelection, } = useItem("QuestionnaireInput");
772
+ export function QuestionnaireInput({ className, defaultValue, disabled: ownDisabled = false, onChange, ref, render, type = 'text', value, ...props }) {
773
+ const { disabled: itemDisabled, invalid, name, registerAnswerControl, registerAnswerSelection, resetVersion, selectedAnswerIds, setAnswerDefault, setAnswerSelectionFromInteraction, syncControlledAnswerSelection, } = useItem('QuestionnaireInput');
822
774
  const id = useId();
823
775
  const element = useRef(null);
824
776
  const initialFilled = useRef(hasText(defaultValue));
@@ -836,7 +788,7 @@ export function QuestionnaireInput({ className, defaultValue, disabled: ownDisab
836
788
  if (!node)
837
789
  return;
838
790
  return registerAnswerControl({
839
- type: "input",
791
+ type: 'input',
840
792
  id,
841
793
  element: node,
842
794
  disabled,
@@ -849,15 +801,7 @@ export function QuestionnaireInput({ className, defaultValue, disabled: ownDisab
849
801
  }
850
802
  if (resetVersion > 0)
851
803
  setFilledState(defaultFilled);
852
- }, [
853
- controlled,
854
- valueFilled,
855
- value,
856
- defaultFilled,
857
- id,
858
- resetVersion,
859
- syncControlledAnswerSelection,
860
- ]);
804
+ }, [controlled, valueFilled, value, defaultFilled, id, resetVersion, syncControlledAnswerSelection]);
861
805
  useLayoutEffect(() => {
862
806
  const node = element.current;
863
807
  if (node && controlled)
@@ -876,16 +820,16 @@ export function QuestionnaireInput({ className, defaultValue, disabled: ownDisab
876
820
  assignRef(ref, node);
877
821
  }, [ref]);
878
822
  const input = useRender({
879
- defaultTagName: "input",
823
+ defaultTagName: 'input',
880
824
  render,
881
825
  props: mergeProps({
882
- "data-slot": "questionnaire-input",
883
- className: cn("sprout-input", "sprout-questionnaire-input", className),
884
- "aria-invalid": invalid || undefined,
885
- "aria-keyshortcuts": keyShortcuts(null, !disabled && filled && selected),
826
+ 'data-slot': 'questionnaire-input',
827
+ className: cn('sprout-input', 'sprout-questionnaire-input', className),
828
+ 'aria-invalid': invalid || undefined,
829
+ 'aria-keyshortcuts': keyShortcuts(null, !disabled && filled && selected),
886
830
  defaultValue: controlled ? undefined : defaultValue,
887
831
  disabled,
888
- form: selected ? undefined : "",
832
+ form: selected ? undefined : '',
889
833
  id,
890
834
  name: selected ? name : undefined,
891
835
  onChange: handleChange,
@@ -895,40 +839,37 @@ export function QuestionnaireInput({ className, defaultValue, disabled: ownDisab
895
839
  }, props),
896
840
  state: { disabled, filled, invalid },
897
841
  stateAttributesMapping: {
898
- filled: (on) => on ? { "data-filled": "" } : { "data-empty": "" },
842
+ filled: (on) => (on ? { 'data-filled': '' } : { 'data-empty': '' }),
899
843
  },
900
844
  });
901
845
  return (_jsx("div", { "data-slot": "questionnaire-input-wrapper", className: "sprout-questionnaire-input-wrapper", children: input }));
902
846
  }
903
847
  /** Shown after someone tries to move on without a valid answer. */
904
848
  export function QuestionnaireError({ children, className, id, render, ...props }) {
905
- const { invalid, registerError, required } = useItem("QuestionnaireError");
849
+ const { invalid, registerError, required } = useItem('QuestionnaireError');
906
850
  const generated = useId();
907
851
  const resolved = id ?? generated;
908
852
  useLayoutEffect(() => registerError(resolved), [resolved, registerError]);
909
853
  return useRender({
910
- defaultTagName: "p",
854
+ defaultTagName: 'p',
911
855
  render,
912
856
  props: mergeProps({
913
- "data-slot": "questionnaire-error",
914
- className: cn("sprout-questionnaire-error", className),
857
+ 'data-slot': 'questionnaire-error',
858
+ className: cn('sprout-questionnaire-error', className),
915
859
  id: resolved,
916
860
  hidden: !invalid,
917
- role: invalid ? "alert" : undefined,
918
- children: children ??
919
- (required
920
- ? "Choose an answer to continue."
921
- : "Choose an answer or skip this question."),
861
+ role: invalid ? 'alert' : undefined,
862
+ children: children ?? (required ? 'Choose an answer to continue.' : 'Choose an answer or skip this question.'),
922
863
  }, props),
923
864
  state: { invalid },
924
865
  });
925
866
  }
926
867
  /** Previous on the start side; Skip and Next or Submit on the end side. */
927
868
  export function QuestionnaireActions({ className, ...props }) {
928
- return (_jsx("div", { "data-slot": "questionnaire-actions", className: cn("sprout-questionnaire-actions", className), ...props }));
869
+ return _jsx("div", { "data-slot": "questionnaire-actions", className: cn('sprout-questionnaire-actions', className), ...props });
929
870
  }
930
- function useNavigationButton(slot, { children, className, disabled = false, onClick, render, size = "default", tabIndex, type, variant, ...props }, { label, visible, status, shortcut, action, }) {
931
- const resolvedVariant = variant ?? (slot === "next" || slot === "submit" ? "default" : "outline");
871
+ function useNavigationButton(slot, { children, className, disabled = false, onClick, render, size = 'default', tabIndex, type, variant, ...props }, { label, visible, status, shortcut, action, }) {
872
+ const resolvedVariant = variant ?? (slot === 'next' || slot === 'submit' ? 'default' : 'outline');
932
873
  const activeShortcut = visible && !disabled ? (shortcut ?? null) : null;
933
874
  function handleClick(event) {
934
875
  onClick?.(event);
@@ -936,34 +877,34 @@ function useNavigationButton(slot, { children, className, disabled = false, onCl
936
877
  action?.();
937
878
  }
938
879
  return useRender({
939
- defaultTagName: "button",
880
+ defaultTagName: 'button',
940
881
  render,
941
882
  props: mergeProps({
942
- "data-slot": `questionnaire-${slot}`,
943
- "data-size": size,
944
- "data-variant": resolvedVariant,
945
- className: cn(buttonVariants({ variant: resolvedVariant, size }), "sprout-questionnaire-action", `sprout-questionnaire-${slot}`, className),
946
- "aria-hidden": !visible || undefined,
947
- "aria-keyshortcuts": activeShortcut ?? undefined,
883
+ 'data-slot': `questionnaire-${slot}`,
884
+ 'data-size': size,
885
+ 'data-variant': resolvedVariant,
886
+ className: cn(buttonVariants({ variant: resolvedVariant, size }), 'sprout-questionnaire-action', `sprout-questionnaire-${slot}`, className),
887
+ 'aria-hidden': !visible || undefined,
888
+ 'aria-keyshortcuts': activeShortcut ?? undefined,
948
889
  children: children ?? label,
949
890
  disabled,
950
891
  hidden: !visible,
951
892
  inert: !visible,
952
893
  onClick: action ? handleClick : onClick,
953
894
  tabIndex: visible ? tabIndex : -1,
954
- type: type ?? (slot === "submit" ? "submit" : "button"),
895
+ type: type ?? (slot === 'submit' ? 'submit' : 'button'),
955
896
  }, props),
956
897
  state: { disabled, shortcut: activeShortcut, status, visible },
957
898
  stateAttributesMapping: {
958
- visible: (on) => on ? { "data-visible": "" } : { "data-hidden": "" },
899
+ visible: (on) => (on ? { 'data-visible': '' } : { 'data-hidden': '' }),
959
900
  },
960
901
  });
961
902
  }
962
903
  /** Goes back one item. Hidden on the first item. */
963
904
  export function QuestionnairePrevious(props) {
964
- const root = useRoot("QuestionnairePrevious");
965
- return useNavigationButton("previous", props, {
966
- label: "Previous",
905
+ const root = useRoot('QuestionnairePrevious');
906
+ return useNavigationButton('previous', props, {
907
+ label: 'Previous',
967
908
  visible: root.total > 1 && !root.first,
968
909
  status: root.activeItemStatus,
969
910
  action: root.goPrevious,
@@ -971,9 +912,9 @@ export function QuestionnairePrevious(props) {
971
912
  }
972
913
  /** Clears the answer and moves on. Shown only on optional items; submits on the last one. */
973
914
  export function QuestionnaireSkip(props) {
974
- const root = useRoot("QuestionnaireSkip");
975
- return useNavigationButton("skip", props, {
976
- label: "Skip",
915
+ const root = useRoot('QuestionnaireSkip');
916
+ return useNavigationButton('skip', props, {
917
+ label: 'Skip',
977
918
  visible: root.activeItemRequired === false,
978
919
  status: root.activeItemStatus,
979
920
  action: root.skipCurrent,
@@ -981,22 +922,22 @@ export function QuestionnaireSkip(props) {
981
922
  }
982
923
  /** Checks the answer and moves on. Hidden on the last item. */
983
924
  export function QuestionnaireNext(props) {
984
- const root = useRoot("QuestionnaireNext");
985
- return useNavigationButton("next", props, {
986
- label: "Next",
925
+ const root = useRoot('QuestionnaireNext');
926
+ return useNavigationButton('next', props, {
927
+ label: 'Next',
987
928
  visible: root.total > 1 && !root.last,
988
929
  status: root.activeItemStatus,
989
- shortcut: "Enter",
930
+ shortcut: 'Enter',
990
931
  action: root.goNext,
991
932
  });
992
933
  }
993
934
  /** Submits the form. Shown only on the last item. */
994
935
  export function QuestionnaireSubmit(props) {
995
- const root = useRoot("QuestionnaireSubmit");
996
- return useNavigationButton("submit", props, {
997
- label: "Submit",
936
+ const root = useRoot('QuestionnaireSubmit');
937
+ return useNavigationButton('submit', props, {
938
+ label: 'Submit',
998
939
  visible: root.total > 0 && root.last,
999
940
  status: root.activeItemStatus,
1000
- shortcut: "Enter",
941
+ shortcut: 'Enter',
1001
942
  });
1002
943
  }