@xemahq/ui-kernel 0.10.0 → 0.11.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 (377) hide show
  1. package/dist/lib/biome-host/agent-validation.d.ts.map +1 -1
  2. package/dist/lib/biome-host/agent-validation.js +26 -13
  3. package/dist/lib/biome-host/agent-validation.js.map +1 -1
  4. package/dist/lib/biome-host/biome-registry.d.ts.map +1 -1
  5. package/dist/lib/biome-host/biome-registry.js +27 -10
  6. package/dist/lib/biome-host/biome-registry.js.map +1 -1
  7. package/dist/lib/biome-host/biome-scope-hooks.d.ts.map +1 -1
  8. package/dist/lib/biome-host/biome-scope-hooks.js +2 -1
  9. package/dist/lib/biome-host/biome-scope-hooks.js.map +1 -1
  10. package/dist/lib/biome-host/biome-scoped-query.d.ts.map +1 -1
  11. package/dist/lib/biome-host/biome-scoped-query.js +5 -3
  12. package/dist/lib/biome-host/biome-scoped-query.js.map +1 -1
  13. package/dist/lib/biome-host/frontend-biome.d.ts +1 -1
  14. package/dist/lib/biome-host/frontend-biome.d.ts.map +1 -1
  15. package/dist/lib/biome-host/host-bridge.d.ts +1 -1
  16. package/dist/lib/biome-host/host-bridge.d.ts.map +1 -1
  17. package/dist/lib/biome-host/host-bridge.js.map +1 -1
  18. package/dist/lib/biome-host/i18n-hooks.d.ts.map +1 -1
  19. package/dist/lib/biome-host/i18n-hooks.js.map +1 -1
  20. package/dist/lib/biome-host/realtime-hooks.d.ts.map +1 -1
  21. package/dist/lib/biome-host/realtime-hooks.js.map +1 -1
  22. package/dist/lib/biome-host/session-contributions.d.ts +1 -1
  23. package/dist/lib/biome-host/session-contributions.d.ts.map +1 -1
  24. package/dist/lib/biome-host/use-mutation-with-error-toast.d.ts.map +1 -1
  25. package/dist/lib/biome-host/use-mutation-with-error-toast.js +3 -2
  26. package/dist/lib/biome-host/use-mutation-with-error-toast.js.map +1 -1
  27. package/dist/lib/biome-host/use-page-state.d.ts.map +1 -1
  28. package/dist/lib/biome-host/use-page-state.js +19 -10
  29. package/dist/lib/biome-host/use-page-state.js.map +1 -1
  30. package/dist/lib/capabilities/capability-provider.d.ts +1 -1
  31. package/dist/lib/capabilities/capability-provider.d.ts.map +1 -1
  32. package/dist/lib/capabilities/capability-provider.js +2 -2
  33. package/dist/lib/capabilities/capability-provider.js.map +1 -1
  34. package/dist/lib/capabilities/use-capability.d.ts +1 -1
  35. package/dist/lib/capabilities/use-capability.d.ts.map +1 -1
  36. package/dist/lib/capabilities/use-capability.js +2 -1
  37. package/dist/lib/capabilities/use-capability.js.map +1 -1
  38. package/dist/lib/contribution-registry/contribution-registry.d.ts.map +1 -1
  39. package/dist/lib/contribution-registry/contribution-registry.js +2 -1
  40. package/dist/lib/contribution-registry/contribution-registry.js.map +1 -1
  41. package/dist/lib/system-bus/deeplink.d.ts.map +1 -1
  42. package/dist/lib/system-bus/deeplink.js +4 -2
  43. package/dist/lib/system-bus/deeplink.js.map +1 -1
  44. package/dist/lib/system-bus/host-ports.d.ts +2 -2
  45. package/dist/lib/system-bus/host-ports.d.ts.map +1 -1
  46. package/dist/lib/system-bus/intent-registry.d.ts.map +1 -1
  47. package/dist/lib/system-bus/intent-registry.js +6 -3
  48. package/dist/lib/system-bus/intent-registry.js.map +1 -1
  49. package/dist/lib/system-bus/intents.d.ts +1 -1
  50. package/dist/lib/system-bus/intents.d.ts.map +1 -1
  51. package/dist/lib/system-bus/palette.d.ts +1 -1
  52. package/dist/lib/system-bus/palette.d.ts.map +1 -1
  53. package/dist/lib/system-bus/system-bus-builder.d.ts.map +1 -1
  54. package/dist/lib/system-bus/system-bus-builder.js +1 -1
  55. package/dist/lib/system-bus/system-bus-builder.js.map +1 -1
  56. package/dist/lib/system-bus/windows.d.ts +1 -1
  57. package/dist/lib/system-bus/windows.d.ts.map +1 -1
  58. package/dist/offline/outbox.d.ts +1 -0
  59. package/dist/offline/outbox.d.ts.map +1 -1
  60. package/dist/offline/outbox.js +4 -1
  61. package/dist/offline/outbox.js.map +1 -1
  62. package/dist/offline/react-hooks.d.ts +1 -1
  63. package/dist/offline/react-hooks.d.ts.map +1 -1
  64. package/dist/offline/react-hooks.js.map +1 -1
  65. package/dist/org-db/components/DbResultTable.d.ts.map +1 -1
  66. package/dist/org-db/components/DbResultTable.js +15 -6
  67. package/dist/org-db/components/DbResultTable.js.map +1 -1
  68. package/dist/registry/lib/agent-validation-host.d.ts.map +1 -1
  69. package/dist/registry/lib/agent-validation-host.js +1 -1
  70. package/dist/registry/lib/agent-validation-host.js.map +1 -1
  71. package/dist/registry/lib/biome-slot.d.ts.map +1 -1
  72. package/dist/registry/lib/biome-slot.js +5 -3
  73. package/dist/registry/lib/biome-slot.js.map +1 -1
  74. package/dist/registry/lib/primitives/SessionEventCard.d.ts.map +1 -1
  75. package/dist/registry/lib/primitives/SessionEventCard.js +14 -2
  76. package/dist/registry/lib/primitives/SessionEventCard.js.map +1 -1
  77. package/dist/registry/lib/primitives/SessionEventTimeline.d.ts.map +1 -1
  78. package/dist/registry/lib/primitives/SessionEventTimeline.js +6 -3
  79. package/dist/registry/lib/primitives/SessionEventTimeline.js.map +1 -1
  80. package/dist/registry/lib/primitives/SessionTabbedDrawer.d.ts.map +1 -1
  81. package/dist/registry/lib/primitives/SessionTabbedDrawer.js +10 -5
  82. package/dist/registry/lib/primitives/SessionTabbedDrawer.js.map +1 -1
  83. package/dist/registry/lib/session-context-provider.d.ts +1 -1
  84. package/dist/registry/lib/session-context-provider.d.ts.map +1 -1
  85. package/dist/registry/lib/session-context-provider.js.map +1 -1
  86. package/dist/registry/lib/session-selectors.d.ts.map +1 -1
  87. package/dist/registry/lib/session-selectors.js +35 -20
  88. package/dist/registry/lib/session-selectors.js.map +1 -1
  89. package/dist/session/comments/CommentRail.d.ts.map +1 -1
  90. package/dist/session/comments/CommentRail.js.map +1 -1
  91. package/dist/session/shell/SessionWorkspaceShell.d.ts.map +1 -1
  92. package/dist/session/shell/SessionWorkspaceShell.js.map +1 -1
  93. package/dist/session-kit/approvals/ApprovalCard.d.ts.map +1 -1
  94. package/dist/session-kit/approvals/ApprovalCard.js +6 -2
  95. package/dist/session-kit/approvals/ApprovalCard.js.map +1 -1
  96. package/dist/session-kit/approvals/ApprovalsCenter.d.ts.map +1 -1
  97. package/dist/session-kit/approvals/ApprovalsCenter.js +6 -3
  98. package/dist/session-kit/approvals/ApprovalsCenter.js.map +1 -1
  99. package/dist/session-kit/combobox/Combobox.d.ts.map +1 -1
  100. package/dist/session-kit/combobox/Combobox.js +20 -6
  101. package/dist/session-kit/combobox/Combobox.js.map +1 -1
  102. package/dist/session-kit/display/MD.d.ts.map +1 -1
  103. package/dist/session-kit/display/MD.js +7 -4
  104. package/dist/session-kit/display/MD.js.map +1 -1
  105. package/dist/ui/branding/app-branding-provider.d.ts.map +1 -1
  106. package/dist/ui/branding/app-branding-provider.js.map +1 -1
  107. package/dist/ui/branding/sanitize.d.ts.map +1 -1
  108. package/dist/ui/branding/sanitize.js +12 -6
  109. package/dist/ui/branding/sanitize.js.map +1 -1
  110. package/dist/ui/capture/document-preview.d.ts +1 -1
  111. package/dist/ui/capture/document-preview.d.ts.map +1 -1
  112. package/dist/ui/capture/document-preview.js +8 -6
  113. package/dist/ui/capture/document-preview.js.map +1 -1
  114. package/dist/ui/capture/field-spec-to-zod.d.ts.map +1 -1
  115. package/dist/ui/capture/field-spec-to-zod.js +45 -16
  116. package/dist/ui/capture/field-spec-to-zod.js.map +1 -1
  117. package/dist/ui/capture/field-spec-validate.d.ts.map +1 -1
  118. package/dist/ui/capture/field-spec-validate.js +79 -38
  119. package/dist/ui/capture/field-spec-validate.js.map +1 -1
  120. package/dist/ui/capture/field-spec.d.ts.map +1 -1
  121. package/dist/ui/capture/field-spec.js +17 -6
  122. package/dist/ui/capture/field-spec.js.map +1 -1
  123. package/dist/ui/capture/schema-field-input.d.ts.map +1 -1
  124. package/dist/ui/capture/schema-field-input.js +23 -18
  125. package/dist/ui/capture/schema-field-input.js.map +1 -1
  126. package/dist/ui/capture/schema-form.d.ts +1 -1
  127. package/dist/ui/capture/schema-form.d.ts.map +1 -1
  128. package/dist/ui/capture/schema-form.js +7 -6
  129. package/dist/ui/capture/schema-form.js.map +1 -1
  130. package/dist/ui/capture/use-prefill.d.ts.map +1 -1
  131. package/dist/ui/capture/use-prefill.js +32 -14
  132. package/dist/ui/capture/use-prefill.js.map +1 -1
  133. package/dist/ui/capture/use-schema-validation.d.ts +1 -1
  134. package/dist/ui/capture/use-schema-validation.d.ts.map +1 -1
  135. package/dist/ui/capture/use-schema-validation.js +13 -8
  136. package/dist/ui/capture/use-schema-validation.js.map +1 -1
  137. package/dist/ui/capture/use-wizard.d.ts.map +1 -1
  138. package/dist/ui/capture/use-wizard.js +23 -8
  139. package/dist/ui/capture/use-wizard.js.map +1 -1
  140. package/dist/ui/capture/value-format.d.ts.map +1 -1
  141. package/dist/ui/capture/value-format.js +6 -3
  142. package/dist/ui/capture/value-format.js.map +1 -1
  143. package/dist/ui/capture/wizard.d.ts.map +1 -1
  144. package/dist/ui/capture/wizard.js +3 -3
  145. package/dist/ui/capture/wizard.js.map +1 -1
  146. package/dist/ui/charts/bar-chart.d.ts +1 -1
  147. package/dist/ui/charts/bar-chart.d.ts.map +1 -1
  148. package/dist/ui/charts/bar-chart.js +1 -1
  149. package/dist/ui/charts/bar-chart.js.map +1 -1
  150. package/dist/ui/charts/chart-frame.d.ts +2 -2
  151. package/dist/ui/charts/chart-frame.d.ts.map +1 -1
  152. package/dist/ui/charts/chart-frame.js +4 -3
  153. package/dist/ui/charts/chart-frame.js.map +1 -1
  154. package/dist/ui/charts/chart-utils.d.ts.map +1 -1
  155. package/dist/ui/charts/chart-utils.js +32 -14
  156. package/dist/ui/charts/chart-utils.js.map +1 -1
  157. package/dist/ui/charts/donut-chart.d.ts +1 -1
  158. package/dist/ui/charts/donut-chart.d.ts.map +1 -1
  159. package/dist/ui/charts/donut-chart.js +7 -3
  160. package/dist/ui/charts/donut-chart.js.map +1 -1
  161. package/dist/ui/charts/line-chart.d.ts +1 -1
  162. package/dist/ui/charts/line-chart.d.ts.map +1 -1
  163. package/dist/ui/charts/line-chart.js +7 -4
  164. package/dist/ui/charts/line-chart.js.map +1 -1
  165. package/dist/ui/charts/sparkline.d.ts +1 -1
  166. package/dist/ui/charts/sparkline.d.ts.map +1 -1
  167. package/dist/ui/charts/sparkline.js +10 -6
  168. package/dist/ui/charts/sparkline.js.map +1 -1
  169. package/dist/ui/chrome/AsyncBoundary.d.ts +2 -2
  170. package/dist/ui/chrome/AsyncBoundary.d.ts.map +1 -1
  171. package/dist/ui/chrome/AsyncBoundary.js +3 -3
  172. package/dist/ui/chrome/AsyncBoundary.js.map +1 -1
  173. package/dist/ui/chrome/EmptyState.d.ts +19 -8
  174. package/dist/ui/chrome/EmptyState.d.ts.map +1 -1
  175. package/dist/ui/chrome/EmptyState.js +6 -4
  176. package/dist/ui/chrome/EmptyState.js.map +1 -1
  177. package/dist/ui/chrome/RecordCardList.d.ts +19 -0
  178. package/dist/ui/chrome/RecordCardList.d.ts.map +1 -0
  179. package/dist/ui/chrome/RecordCardList.js +12 -0
  180. package/dist/ui/chrome/RecordCardList.js.map +1 -0
  181. package/dist/ui/chrome/page-shell.d.ts.map +1 -1
  182. package/dist/ui/chrome/page-shell.js +9 -3
  183. package/dist/ui/chrome/page-shell.js.map +1 -1
  184. package/dist/ui/chrome/status-badge.d.ts.map +1 -1
  185. package/dist/ui/chrome/status-badge.js +1 -1
  186. package/dist/ui/chrome/status-badge.js.map +1 -1
  187. package/dist/ui/design-tokens.d.ts +4 -6
  188. package/dist/ui/design-tokens.d.ts.map +1 -1
  189. package/dist/ui/design-tokens.js +17 -11
  190. package/dist/ui/design-tokens.js.map +1 -1
  191. package/dist/ui/index.d.ts +1 -0
  192. package/dist/ui/index.d.ts.map +1 -1
  193. package/dist/ui/index.js +1 -0
  194. package/dist/ui/index.js.map +1 -1
  195. package/dist/ui/primitives/async-combobox.d.ts.map +1 -1
  196. package/dist/ui/primitives/async-combobox.js +4 -2
  197. package/dist/ui/primitives/async-combobox.js.map +1 -1
  198. package/dist/ui/primitives/badge.d.ts +2 -2
  199. package/dist/ui/primitives/badge.d.ts.map +1 -1
  200. package/dist/ui/primitives/badge.js +3 -3
  201. package/dist/ui/primitives/badge.js.map +1 -1
  202. package/dist/ui/primitives/button.d.ts +2 -2
  203. package/dist/ui/primitives/button.d.ts.map +1 -1
  204. package/dist/ui/primitives/button.js +5 -5
  205. package/dist/ui/primitives/button.js.map +1 -1
  206. package/dist/ui/primitives/overflow-tabs.d.ts.map +1 -1
  207. package/dist/ui/primitives/overflow-tabs.js +19 -12
  208. package/dist/ui/primitives/overflow-tabs.js.map +1 -1
  209. package/dist/ui/primitives/preview-device-frame.js +8 -4
  210. package/dist/ui/primitives/preview-device-frame.js.map +1 -1
  211. package/dist/ui/primitives/tag-multi-select.d.ts.map +1 -1
  212. package/dist/ui/primitives/tag-multi-select.js +10 -5
  213. package/dist/ui/primitives/tag-multi-select.js.map +1 -1
  214. package/dist/ui/primitives/url-preview-chrome.d.ts.map +1 -1
  215. package/dist/ui/primitives/url-preview-chrome.js.map +1 -1
  216. package/dist/vista/GenericCatalogueSurface.d.ts.map +1 -1
  217. package/dist/vista/GenericCatalogueSurface.js +5 -3
  218. package/dist/vista/GenericCatalogueSurface.js.map +1 -1
  219. package/dist/vista/VistaPanel.d.ts.map +1 -1
  220. package/dist/vista/VistaPanel.js +8 -4
  221. package/dist/vista/VistaPanel.js.map +1 -1
  222. package/dist/vista/html/CustomUiFrame.d.ts.map +1 -1
  223. package/dist/vista/html/CustomUiFrame.js +2 -1
  224. package/dist/vista/html/CustomUiFrame.js.map +1 -1
  225. package/dist/vista/html/custom-ui-frame-bridge.d.ts.map +1 -1
  226. package/dist/vista/html/custom-ui-frame-bridge.js +6 -3
  227. package/dist/vista/html/custom-ui-frame-bridge.js.map +1 -1
  228. package/dist/vista/html/custom-ui-intents.d.ts.map +1 -1
  229. package/dist/vista/html/custom-ui-intents.js +13 -15
  230. package/dist/vista/html/custom-ui-intents.js.map +1 -1
  231. package/dist/vista/surface-catalogue.d.ts.map +1 -1
  232. package/dist/vista/surface-catalogue.js +6 -3
  233. package/dist/vista/surface-catalogue.js.map +1 -1
  234. package/dist/vista/surfaces/FormSurface.d.ts.map +1 -1
  235. package/dist/vista/surfaces/FormSurface.js +20 -7
  236. package/dist/vista/surfaces/FormSurface.js.map +1 -1
  237. package/dist/vista/surfaces/TableSurface.d.ts.map +1 -1
  238. package/dist/vista/surfaces/TableSurface.js +2 -1
  239. package/dist/vista/surfaces/TableSurface.js.map +1 -1
  240. package/dist/vista/surfaces/blob-surfaces.d.ts.map +1 -1
  241. package/dist/vista/surfaces/blob-surfaces.js +7 -2
  242. package/dist/vista/surfaces/blob-surfaces.js.map +1 -1
  243. package/dist/vista/surfaces/elicitation-transport.d.ts.map +1 -1
  244. package/dist/vista/surfaces/elicitation-transport.js +14 -7
  245. package/dist/vista/surfaces/elicitation-transport.js.map +1 -1
  246. package/dist/vista/surfaces/file-surface-utils.d.ts.map +1 -1
  247. package/dist/vista/surfaces/file-surface-utils.js +8 -4
  248. package/dist/vista/surfaces/file-surface-utils.js.map +1 -1
  249. package/dist/vista/surfaces/register-surfaces.js +2 -1
  250. package/dist/vista/surfaces/register-surfaces.js.map +1 -1
  251. package/dist/vista/surfaces/text-surfaces.d.ts +1 -1
  252. package/dist/vista/surfaces/text-surfaces.d.ts.map +1 -1
  253. package/dist/vista/surfaces/text-surfaces.js +13 -7
  254. package/dist/vista/surfaces/text-surfaces.js.map +1 -1
  255. package/dist/vista/use-vista-tabs.d.ts.map +1 -1
  256. package/dist/vista/use-vista-tabs.js +8 -4
  257. package/dist/vista/use-vista-tabs.js.map +1 -1
  258. package/dist/vista/vista-code-renderer.d.ts.map +1 -1
  259. package/dist/vista/vista-code-renderer.js.map +1 -1
  260. package/dist/vista/vista-file-source.d.ts.map +1 -1
  261. package/dist/vista/vista-file-source.js +9 -5
  262. package/dist/vista/vista-file-source.js.map +1 -1
  263. package/dist/vista/vista-form-host.d.ts.map +1 -1
  264. package/dist/vista/vista-form-host.js +1 -1
  265. package/dist/vista/vista-form-host.js.map +1 -1
  266. package/dist/vista/vista-model.d.ts.map +1 -1
  267. package/dist/vista/vista-model.js +5 -3
  268. package/dist/vista/vista-model.js.map +1 -1
  269. package/dist/vista/vista-open-context.d.ts.map +1 -1
  270. package/dist/vista/vista-open-context.js +1 -1
  271. package/dist/vista/vista-open-context.js.map +1 -1
  272. package/dist/vista/vista-payloads.d.ts.map +1 -1
  273. package/dist/vista/vista-payloads.js +127 -63
  274. package/dist/vista/vista-payloads.js.map +1 -1
  275. package/dist/vista/vista-tabs-manifest.d.ts.map +1 -1
  276. package/dist/vista/vista-tabs-manifest.js +18 -9
  277. package/dist/vista/vista-tabs-manifest.js.map +1 -1
  278. package/dist/vista/vista-tools.d.ts.map +1 -1
  279. package/dist/vista/vista-tools.js +12 -6
  280. package/dist/vista/vista-tools.js.map +1 -1
  281. package/package.json +3 -3
  282. package/src/lib/biome-host/agent-validation.ts +37 -13
  283. package/src/lib/biome-host/biome-registry.ts +48 -13
  284. package/src/lib/biome-host/biome-scope-hooks.ts +3 -1
  285. package/src/lib/biome-host/biome-scoped-query.ts +7 -6
  286. package/src/lib/biome-host/frontend-biome.ts +1 -1
  287. package/src/lib/biome-host/host-bridge.ts +5 -4
  288. package/src/lib/biome-host/i18n-hooks.ts +1 -0
  289. package/src/lib/biome-host/realtime-hooks.ts +1 -0
  290. package/src/lib/biome-host/session-contributions.ts +1 -1
  291. package/src/lib/biome-host/use-mutation-with-error-toast.ts +4 -2
  292. package/src/lib/biome-host/use-page-state.ts +27 -10
  293. package/src/lib/capabilities/capability-provider.tsx +12 -5
  294. package/src/lib/capabilities/use-capability.ts +8 -4
  295. package/src/lib/contribution-registry/contribution-registry.ts +3 -1
  296. package/src/lib/system-bus/deeplink.ts +14 -4
  297. package/src/lib/system-bus/host-ports.ts +3 -7
  298. package/src/lib/system-bus/intent-registry.ts +12 -8
  299. package/src/lib/system-bus/intents.ts +6 -2
  300. package/src/lib/system-bus/palette.ts +2 -1
  301. package/src/lib/system-bus/system-bus-builder.ts +4 -2
  302. package/src/lib/system-bus/windows.ts +1 -1
  303. package/src/offline/outbox.test.ts +12 -3
  304. package/src/offline/outbox.ts +5 -1
  305. package/src/offline/react-hooks.ts +5 -2
  306. package/src/org-db/components/DbResultTable.tsx +48 -15
  307. package/src/registry/lib/agent-validation-host.ts +1 -2
  308. package/src/registry/lib/biome-slot.tsx +7 -4
  309. package/src/registry/lib/primitives/SessionEventCard.tsx +29 -5
  310. package/src/registry/lib/primitives/SessionEventTimeline.tsx +9 -3
  311. package/src/registry/lib/primitives/SessionTabbedDrawer.tsx +15 -5
  312. package/src/registry/lib/session-context-provider.tsx +1 -1
  313. package/src/registry/lib/session-selectors.ts +66 -27
  314. package/src/session/comments/CommentRail.tsx +2 -2
  315. package/src/session/shell/SessionWorkspaceShell.tsx +2 -2
  316. package/src/session-kit/approvals/ApprovalCard.tsx +7 -2
  317. package/src/session-kit/approvals/ApprovalsCenter.tsx +13 -4
  318. package/src/session-kit/combobox/Combobox.tsx +42 -11
  319. package/src/session-kit/display/MD.tsx +14 -5
  320. package/src/ui/branding/app-branding-provider.tsx +2 -3
  321. package/src/ui/branding/sanitize.ts +18 -6
  322. package/src/ui/capture/document-preview.tsx +84 -19
  323. package/src/ui/capture/field-spec-to-zod.ts +62 -14
  324. package/src/ui/capture/field-spec-validate.ts +132 -43
  325. package/src/ui/capture/field-spec.test.ts +2 -2
  326. package/src/ui/capture/field-spec.ts +41 -10
  327. package/src/ui/capture/schema-field-input.tsx +218 -38
  328. package/src/ui/capture/schema-form.tsx +54 -13
  329. package/src/ui/capture/use-prefill.ts +50 -17
  330. package/src/ui/capture/use-schema-validation.ts +45 -13
  331. package/src/ui/capture/use-wizard.ts +57 -11
  332. package/src/ui/capture/value-format.ts +14 -4
  333. package/src/ui/capture/wizard.tsx +9 -5
  334. package/src/ui/charts/bar-chart.tsx +8 -4
  335. package/src/ui/charts/chart-frame.tsx +18 -5
  336. package/src/ui/charts/chart-utils.ts +47 -15
  337. package/src/ui/charts/donut-chart.tsx +24 -6
  338. package/src/ui/charts/line-chart.tsx +34 -12
  339. package/src/ui/charts/sparkline.tsx +17 -9
  340. package/src/ui/chrome/AsyncBoundary.tsx +14 -6
  341. package/src/ui/chrome/EmptyState.tsx +116 -43
  342. package/src/ui/chrome/RecordCardList.tsx +98 -0
  343. package/src/ui/chrome/page-shell.tsx +32 -8
  344. package/src/ui/chrome/status-badge.tsx +8 -4
  345. package/src/ui/design-tokens.ts +39 -13
  346. package/src/ui/index.ts +5 -0
  347. package/src/ui/primitives/async-combobox.tsx +7 -3
  348. package/src/ui/primitives/badge.tsx +14 -5
  349. package/src/ui/primitives/button.tsx +13 -6
  350. package/src/ui/primitives/overflow-tabs.tsx +46 -16
  351. package/src/ui/primitives/preview-device-frame.tsx +12 -4
  352. package/src/ui/primitives/tag-multi-select.tsx +30 -9
  353. package/src/ui/primitives/url-preview-chrome.tsx +1 -0
  354. package/src/vista/GenericCatalogueSurface.tsx +7 -5
  355. package/src/vista/VistaPanel.tsx +12 -4
  356. package/src/vista/html/CustomUiFrame.spec.tsx +3 -1
  357. package/src/vista/html/CustomUiFrame.tsx +3 -1
  358. package/src/vista/html/custom-ui-frame-bridge.ts +9 -3
  359. package/src/vista/html/custom-ui-intents.spec.ts +3 -1
  360. package/src/vista/html/custom-ui-intents.ts +19 -15
  361. package/src/vista/surface-catalogue.ts +9 -3
  362. package/src/vista/surfaces/FormSurface.tsx +27 -10
  363. package/src/vista/surfaces/TableSurface.tsx +4 -3
  364. package/src/vista/surfaces/blob-surfaces.tsx +13 -3
  365. package/src/vista/surfaces/elicitation-transport.ts +21 -7
  366. package/src/vista/surfaces/file-surface-utils.ts +11 -4
  367. package/src/vista/surfaces/register-surfaces.tsx +3 -1
  368. package/src/vista/surfaces/text-surfaces.tsx +21 -8
  369. package/src/vista/use-vista-tabs.ts +12 -4
  370. package/src/vista/vista-code-renderer.tsx +6 -5
  371. package/src/vista/vista-file-source.tsx +15 -14
  372. package/src/vista/vista-form-host.tsx +3 -8
  373. package/src/vista/vista-model.ts +10 -3
  374. package/src/vista/vista-open-context.tsx +3 -8
  375. package/src/vista/vista-payloads.ts +186 -63
  376. package/src/vista/vista-tabs-manifest.ts +28 -13
  377. package/src/vista/vista-tools.ts +18 -6
@@ -17,15 +17,19 @@ import { Eye, EyeOff, Plus, Trash2 } from 'lucide-react';
17
17
  import { useCallback, useRef, useState, type ReactNode } from 'react';
18
18
 
19
19
  import { cn } from '../cn';
20
+ import {
21
+ applyCaptureTransform,
22
+ CaptureFieldType,
23
+ type CaptureFieldSpec,
24
+ type CaptureValues,
25
+ } from './field-spec';
26
+ import { asString } from './value-format';
20
27
  import { Button } from '../primitives/button';
21
28
  import { Checkbox } from '../primitives/checkbox';
22
29
  import { Input } from '../primitives/input';
23
30
  import { Label } from '../primitives/label';
24
31
  import { Textarea } from '../primitives/textarea';
25
32
 
26
- import { applyCaptureTransform, CaptureFieldType, type CaptureFieldSpec, type CaptureValues } from './field-spec';
27
- import { asString } from './value-format';
28
-
29
33
  const SELECT_CLASS =
30
34
  'mt-1 flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-body-1 text-foreground ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50';
31
35
 
@@ -51,7 +55,9 @@ export interface SchemaFieldInputProps {
51
55
  }
52
56
 
53
57
  /** Native `type` for the single-line text-ish capture types. */
54
- function nativeInputType(type: CaptureFieldSpec['type']): 'text' | 'email' | 'url' {
58
+ function nativeInputType(
59
+ type: CaptureFieldSpec['type'],
60
+ ): 'text' | 'email' | 'url' {
55
61
  switch (type) {
56
62
  case CaptureFieldType.Email:
57
63
  return 'email';
@@ -69,17 +75,38 @@ export function SchemaFieldInput(props: SchemaFieldInputProps) {
69
75
  // The ONE place a captured string is normalized. Composites (object/list)
70
76
  // emit records/arrays and pass through untouched.
71
77
  const emit = (next: unknown): void =>
72
- onChange(typeof next === 'string' ? applyCaptureTransform(next, field.transform) : next);
78
+ onChange(
79
+ typeof next === 'string'
80
+ ? applyCaptureTransform(next, field.transform)
81
+ : next,
82
+ );
73
83
 
74
84
  // DECLARED secrecy wins over the field type: a secret is always write-only
75
85
  // and masked, whatever shape it has. Never inferred from `type`.
76
86
  if (field.isSecret === true) {
77
- return <SecretFieldInput field={field} value={value} onChange={emit} disabled={disabled} inputId={inputId} />;
87
+ return (
88
+ <SecretFieldInput
89
+ field={field}
90
+ value={value}
91
+ onChange={emit}
92
+ disabled={disabled}
93
+ inputId={inputId}
94
+ />
95
+ );
78
96
  }
79
97
 
80
98
  switch (field.type) {
81
99
  case CaptureFieldType.Text:
82
- return <Textarea id={inputId} value={asString(value)} onChange={(e) => emit(e.target.value)} disabled={disabled} rows={4} placeholder={field.placeholder} />;
100
+ return (
101
+ <Textarea
102
+ id={inputId}
103
+ value={asString(value)}
104
+ onChange={(e) => emit(e.target.value)}
105
+ disabled={disabled}
106
+ rows={4}
107
+ placeholder={field.placeholder}
108
+ />
109
+ );
83
110
  case CaptureFieldType.Json:
84
111
  return (
85
112
  <Textarea
@@ -99,29 +126,76 @@ export function SchemaFieldInput(props: SchemaFieldInputProps) {
99
126
  id={inputId}
100
127
  type="number"
101
128
  value={asString(value)}
102
- onChange={(e) => emit(e.target.value === '' ? '' : Number(e.target.value))}
129
+ onChange={(e) =>
130
+ emit(e.target.value === '' ? '' : Number(e.target.value))
131
+ }
103
132
  disabled={disabled}
104
133
  placeholder={field.placeholder}
105
134
  />
106
135
  );
107
136
  case CaptureFieldType.Decimal:
108
137
  // NUMERIC carried verbatim as text — never Number()-coerced (precision).
109
- return <Input id={inputId} type="text" inputMode="decimal" value={asString(value)} onChange={(e) => emit(e.target.value)} disabled={disabled} placeholder={field.placeholder ?? '0.00'} />;
138
+ return (
139
+ <Input
140
+ id={inputId}
141
+ type="text"
142
+ inputMode="decimal"
143
+ value={asString(value)}
144
+ onChange={(e) => emit(e.target.value)}
145
+ disabled={disabled}
146
+ placeholder={field.placeholder ?? '0.00'}
147
+ />
148
+ );
110
149
  case CaptureFieldType.User:
111
- return <Input id={inputId} value={asString(value)} onChange={(e) => emit(e.target.value)} disabled={disabled} placeholder={field.placeholder ?? 'subject id'} />;
150
+ return (
151
+ <Input
152
+ id={inputId}
153
+ value={asString(value)}
154
+ onChange={(e) => emit(e.target.value)}
155
+ disabled={disabled}
156
+ placeholder={field.placeholder ?? 'subject id'}
157
+ />
158
+ );
112
159
  case CaptureFieldType.Boolean:
113
160
  return (
114
161
  <div className="mt-1">
115
- <Checkbox id={inputId} checked={value === true} onCheckedChange={(checked) => emit(checked === true)} disabled={disabled} />
162
+ <Checkbox
163
+ id={inputId}
164
+ checked={value === true}
165
+ onCheckedChange={(checked) => emit(checked === true)}
166
+ disabled={disabled}
167
+ />
116
168
  </div>
117
169
  );
118
170
  case CaptureFieldType.Date:
119
- return <Input id={inputId} type="date" value={asString(value)} onChange={(e) => emit(e.target.value)} disabled={disabled} />;
171
+ return (
172
+ <Input
173
+ id={inputId}
174
+ type="date"
175
+ value={asString(value)}
176
+ onChange={(e) => emit(e.target.value)}
177
+ disabled={disabled}
178
+ />
179
+ );
120
180
  case CaptureFieldType.Datetime:
121
- return <Input id={inputId} type="datetime-local" value={asString(value)} onChange={(e) => emit(e.target.value)} disabled={disabled} />;
181
+ return (
182
+ <Input
183
+ id={inputId}
184
+ type="datetime-local"
185
+ value={asString(value)}
186
+ onChange={(e) => emit(e.target.value)}
187
+ disabled={disabled}
188
+ />
189
+ );
122
190
  case CaptureFieldType.Enum:
123
191
  return (
124
- <select id={inputId} className={SELECT_CLASS} value={asString(value)} onChange={(e) => emit(e.target.value)} disabled={disabled}>
192
+ <select
193
+ id={inputId}
194
+ className={SELECT_CLASS}
195
+ value={asString(value)}
196
+ onChange={(e) => emit(e.target.value)}
197
+ disabled={disabled}
198
+ >
125
199
  <option value="">— select —</option>
126
200
  {(field.enumValues ?? []).map((v) => (
127
201
  <option key={v} value={v}>
@@ -132,9 +206,17 @@ export function SchemaFieldInput(props: SchemaFieldInputProps) {
132
206
  );
133
207
  case CaptureFieldType.Reference:
134
208
  return renderReference ? (
135
- <>{renderReference({ field, value, onChange: emit, disabled, inputId })}</>
209
+ <>
210
+ {renderReference({ field, value, onChange: emit, disabled, inputId })}
211
+ </>
136
212
  ) : (
137
- <Input id={inputId} value={asString(value)} onChange={(e) => emit(e.target.value)} disabled={disabled} placeholder={field.placeholder ?? 'reference id'} />
213
+ <Input
214
+ id={inputId}
215
+ value={asString(value)}
216
+ onChange={(e) => emit(e.target.value)}
217
+ disabled={disabled}
218
+ placeholder={field.placeholder ?? 'reference id'}
219
+ />
138
220
  );
139
221
  case CaptureFieldType.Object:
140
222
  return <ObjectInput {...props} />;
@@ -147,7 +229,16 @@ export function SchemaFieldInput(props: SchemaFieldInputProps) {
147
229
  return <AudioFieldInput {...props} />;
148
230
  // string / email / url (and any unknown) — single-line input.
149
231
  default:
150
- return <Input id={inputId} type={nativeInputType(field.type)} value={asString(value)} onChange={(e) => emit(e.target.value)} disabled={disabled} placeholder={field.placeholder} />;
232
+ return (
233
+ <Input
234
+ id={inputId}
235
+ type={nativeInputType(field.type)}
236
+ value={asString(value)}
237
+ onChange={(e) => emit(e.target.value)}
238
+ disabled={disabled}
239
+ placeholder={field.placeholder}
240
+ />
241
+ );
151
242
  }
152
243
  }
153
244
 
@@ -174,7 +265,9 @@ function SecretFieldInput({
174
265
  inputId: string;
175
266
  }>) {
176
267
  const [reveal, setReveal] = useState(false);
177
- const multiline = field.type === CaptureFieldType.Json || field.type === CaptureFieldType.Text;
268
+ const multiline =
269
+ field.type === CaptureFieldType.Json ||
270
+ field.type === CaptureFieldType.Text;
178
271
 
179
272
  if (multiline && reveal) {
180
273
  return (
@@ -214,7 +307,10 @@ function SecretFieldInput({
214
307
  );
215
308
  }
216
309
 
217
- function RevealToggle({ reveal, onToggle }: Readonly<{ reveal: boolean; onToggle: () => void }>) {
310
+ function RevealToggle({
311
+ reveal,
312
+ onToggle,
313
+ }: Readonly<{ reveal: boolean; onToggle: () => void }>) {
218
314
  return (
219
315
  <Button
220
316
  type="button"
@@ -245,7 +341,13 @@ function readAsDataUrl(file: Blob, onDone: (dataUrl: string) => void): void {
245
341
  * the camera directly. The value is a data-URL so it stays JSON-serializable and
246
342
  * flows unchanged through the record model + offline outbox.
247
343
  */
248
- function MediaFieldInput({ field, value, onChange, disabled, path }: SchemaFieldInputProps) {
344
+ function MediaFieldInput({
345
+ field,
346
+ value,
347
+ onChange,
348
+ disabled,
349
+ path,
350
+ }: SchemaFieldInputProps) {
249
351
  const inputId = `field-${path}`;
250
352
  const current = asString(value);
251
353
  const isImage = field.type === CaptureFieldType.Image;
@@ -269,11 +371,23 @@ function MediaFieldInput({ field, value, onChange, disabled, path }: SchemaField
269
371
  {current ? (
270
372
  <div className="flex items-center gap-2">
271
373
  {isImage && current.startsWith('data:image') ? (
272
- <img src={current} alt={field.label} className="max-h-32 rounded-md border border-input" />
374
+ <img
375
+ src={current}
376
+ alt={field.label}
377
+ className="max-h-32 rounded-md border border-input"
378
+ />
273
379
  ) : (
274
- <span className="truncate text-body-2 text-muted-foreground">Attached</span>
380
+ <span className="truncate text-body-2 text-muted-foreground">
381
+ Attached
382
+ </span>
275
383
  )}
276
- <Button type="button" variant="ghost" size="sm" onClick={() => onChange('')} disabled={disabled}>
384
+ <Button
385
+ type="button"
386
+ variant="ghost"
387
+ size="sm"
388
+ onClick={() => onChange('')}
389
+ disabled={disabled}
390
+ >
277
391
  Clear
278
392
  </Button>
279
393
  </div>
@@ -286,7 +400,12 @@ function MediaFieldInput({ field, value, onChange, disabled, path }: SchemaField
286
400
  * `audio` capture — records a voice memo via MediaRecorder and stores it as a
287
401
  * data-URL. Browser APIs are touched only inside the record handler (SSR-safe).
288
402
  */
289
- function AudioFieldInput({ value, onChange, disabled, path }: SchemaFieldInputProps) {
403
+ function AudioFieldInput({
404
+ value,
405
+ onChange,
406
+ disabled,
407
+ path,
408
+ }: SchemaFieldInputProps) {
290
409
  const inputId = `field-${path}`;
291
410
  const current = asString(value);
292
411
  const [recording, setRecording] = useState(false);
@@ -310,7 +429,9 @@ function AudioFieldInput({ value, onChange, disabled, path }: SchemaFieldInputPr
310
429
  track.stop();
311
430
  }
312
431
  readAsDataUrl(
313
- new Blob(chunksRef.current, { type: recorder.mimeType || 'audio/webm' }),
432
+ new Blob(chunksRef.current, {
433
+ type: recorder.mimeType || 'audio/webm',
434
+ }),
314
435
  onChange,
315
436
  );
316
437
  };
@@ -332,16 +453,34 @@ function AudioFieldInput({ value, onChange, disabled, path }: SchemaFieldInputPr
332
453
  <div className="mt-1 space-y-2">
333
454
  <div className="flex items-center gap-2">
334
455
  {recording ? (
335
- <Button type="button" variant="secondary" size="sm" onClick={stop} disabled={disabled}>
456
+ <Button
457
+ type="button"
458
+ variant="secondary"
459
+ size="sm"
460
+ onClick={stop}
461
+ disabled={disabled}
462
+ >
336
463
  Stop
337
464
  </Button>
338
465
  ) : (
339
- <Button type="button" variant="secondary" size="sm" onClick={() => void start()} disabled={disabled}>
466
+ <Button
467
+ type="button"
468
+ variant="secondary"
469
+ size="sm"
470
+ onClick={() => void start()}
471
+ disabled={disabled}
472
+ >
340
473
  {current ? 'Re-record' : 'Record'}
341
474
  </Button>
342
475
  )}
343
476
  {current ? (
344
- <Button type="button" variant="ghost" size="sm" onClick={() => onChange('')} disabled={disabled}>
477
+ <Button
478
+ type="button"
479
+ variant="ghost"
480
+ size="sm"
481
+ onClick={() => onChange('')}
482
+ disabled={disabled}
483
+ >
345
484
  Clear
346
485
  </Button>
347
486
  ) : null}
@@ -368,15 +507,29 @@ function NestedField(props: SchemaFieldInputProps) {
368
507
  {field.label}
369
508
  {field.required ? <span className="text-destructive"> *</span> : null}
370
509
  </Label>
371
- {field.description ? <p className="mb-1 text-caption text-ink-3">{field.description}</p> : null}
510
+ {field.description ? (
511
+ <p className="mb-1 text-caption text-ink-3">{field.description}</p>
512
+ ) : null}
372
513
  <SchemaFieldInput {...props} />
373
- {error ? <p className="mt-1 text-caption text-destructive">{error}</p> : null}
514
+ {error ? (
515
+ <p className="mt-1 text-caption text-destructive">{error}</p>
516
+ ) : null}
374
517
  </div>
375
518
  );
376
519
  }
377
520
 
378
- function ObjectInput({ field, value, onChange, disabled, path, errors, renderReference }: SchemaFieldInputProps) {
379
- const record = (value && typeof value === 'object' && !Array.isArray(value) ? value : {}) as CaptureValues;
521
+ function ObjectInput({
522
+ field,
523
+ value,
524
+ onChange,
525
+ disabled,
526
+ path,
527
+ errors,
528
+ renderReference,
529
+ }: SchemaFieldInputProps) {
530
+ const record = (
531
+ value && typeof value === 'object' && !Array.isArray(value) ? value : {}
532
+ ) as CaptureValues;
380
533
  const fields = field.fields ?? [];
381
534
  return (
382
535
  <div className="mt-1 space-y-3 rounded-lg border border-rule bg-paper-elev/40 p-3">
@@ -396,24 +549,44 @@ function ObjectInput({ field, value, onChange, disabled, path, errors, renderRef
396
549
  );
397
550
  }
398
551
 
399
- function ListInput({ field, value, onChange, disabled, path, errors, renderReference }: SchemaFieldInputProps) {
552
+ function ListInput({
553
+ field,
554
+ value,
555
+ onChange,
556
+ disabled,
557
+ path,
558
+ errors,
559
+ renderReference,
560
+ }: SchemaFieldInputProps) {
400
561
  const items = (Array.isArray(value) ? value : []) as CaptureValues[];
401
562
  const fields = field.fields ?? [];
402
563
  const atMax = typeof field.max === 'number' && items.length >= field.max;
403
564
 
404
- const setItem = (index: number, next: CaptureValues) => onChange(items.map((it, i) => (i === index ? next : it)));
405
- const removeItem = (index: number) => onChange(items.filter((_, i) => i !== index));
565
+ const setItem = (index: number, next: CaptureValues) =>
566
+ onChange(items.map((it, i) => (i === index ? next : it)));
567
+ const removeItem = (index: number) =>
568
+ onChange(items.filter((_, i) => i !== index));
406
569
  const addItem = () => onChange([...items, {}]);
407
570
 
408
571
  return (
409
572
  <div className="mt-1 space-y-2">
410
573
  {items.map((item, index) => (
411
- <div key={index} className="relative space-y-3 rounded-lg border border-rule bg-paper-elev/40 p-3">
574
+ <div
575
+ key={index}
576
+ className="relative space-y-3 rounded-lg border border-rule bg-paper-elev/40 p-3"
577
+ >
412
578
  <div className="flex items-center justify-between">
413
579
  <span className="text-caption font-medium text-ink-3">
414
580
  {field.label} #{index + 1}
415
581
  </span>
416
- <Button type="button" variant="ghost" size="icon" onClick={() => removeItem(index)} disabled={disabled} aria-label={`Remove ${field.label} ${index + 1}`}>
582
+ <Button
583
+ type="button"
584
+ variant="ghost"
585
+ size="icon"
586
+ onClick={() => removeItem(index)}
587
+ disabled={disabled}
588
+ aria-label={`Remove ${field.label} ${index + 1}`}
589
+ >
417
590
  <Trash2 className="h-4 w-4" />
418
591
  </Button>
419
592
  </div>
@@ -431,7 +604,14 @@ function ListInput({ field, value, onChange, disabled, path, errors, renderRefer
431
604
  ))}
432
605
  </div>
433
606
  ))}
434
- <Button type="button" variant="outline" size="sm" onClick={addItem} disabled={disabled || atMax} className={cn(items.length === 0 && 'w-full')}>
607
+ <Button
608
+ type="button"
609
+ variant="outline"
610
+ size="sm"
611
+ onClick={addItem}
612
+ disabled={disabled || atMax}
613
+ className={cn(items.length === 0 && 'w-full')}
614
+ >
435
615
  <Plus className="mr-1.5 h-3.5 w-3.5" />
436
616
  Add {field.label}
437
617
  </Button>
@@ -15,12 +15,17 @@ import { Sparkles } from 'lucide-react';
15
15
  import { type ReactNode } from 'react';
16
16
 
17
17
  import { cn } from '../cn';
18
+ import {
19
+ type CaptureFieldSpec,
20
+ type CaptureSchema,
21
+ type CaptureSection,
22
+ type CaptureValues,
23
+ toSections,
24
+ } from './field-spec';
25
+ import { SchemaFieldInput, type RenderReference } from './schema-field-input';
18
26
  import { Badge } from '../primitives/badge';
19
27
  import { Label } from '../primitives/label';
20
28
 
21
- import { type CaptureFieldSpec, type CaptureSchema, type CaptureSection, type CaptureValues, toSections } from './field-spec';
22
- import { SchemaFieldInput, type RenderReference } from './schema-field-input';
23
-
24
29
  export interface SchemaFormProps {
25
30
  /** Flat schema. Mutually exclusive with `sections`. */
26
31
  readonly fields?: readonly CaptureFieldSpec[];
@@ -44,7 +49,9 @@ export interface SchemaFormProps {
44
49
  }
45
50
 
46
51
  function toSet(keys: SchemaFormProps['suggestedKeys']): ReadonlySet<string> {
47
- if (!keys) return new Set();
52
+ if (!keys) {
53
+ return new Set();
54
+ }
48
55
  return keys instanceof Set ? keys : new Set(keys as readonly string[]);
49
56
  }
50
57
 
@@ -54,20 +61,43 @@ function toSet(keys: SchemaFormProps['suggestedKeys']): ReadonlySet<string> {
54
61
  * const { errors } = useSchemaValidation(fields, values);
55
62
  * <SchemaForm fields={fields} values={values} onChange={setValues} errors={errors} />
56
63
  */
57
- export function SchemaForm({ fields, sections, schema, values, onChange, errors, suggestedKeys, disabled, renderReference, className, footer }: SchemaFormProps) {
58
- const resolved: readonly CaptureSection[] = toSections(sections ?? (fields ? fields : schema) ?? []);
64
+ export function SchemaForm({
65
+ fields,
66
+ sections,
67
+ schema,
68
+ values,
69
+ onChange,
70
+ errors,
71
+ suggestedKeys,
72
+ disabled,
73
+ renderReference,
74
+ className,
75
+ footer,
76
+ }: SchemaFormProps) {
77
+ const resolved: readonly CaptureSection[] = toSections(
78
+ sections ?? (fields ? fields : schema) ?? [],
79
+ );
59
80
  const suggested = toSet(suggestedKeys);
60
81
 
61
- const setField = (key: string, value: unknown) => onChange({ ...values, [key]: value });
82
+ const setField = (key: string, value: unknown) =>
83
+ onChange({ ...values, [key]: value });
62
84
 
63
85
  return (
64
86
  <div className={cn('space-y-6', className)}>
65
87
  {resolved.map((section) => (
66
- <fieldset key={section.key} className="space-y-3 border-0 p-0" disabled={disabled}>
88
+ <fieldset
89
+ key={section.key}
90
+ className="space-y-3 border-0 p-0"
91
+ disabled={disabled}
92
+ >
67
93
  {section.title ? (
68
94
  <legend className="mb-1 text-subtitle font-semibold text-ink">
69
95
  {section.title}
70
- {section.description ? <span className="mt-0.5 block text-caption font-normal text-ink-3">{section.description}</span> : null}
96
+ {section.description ? (
97
+ <span className="mt-0.5 block text-caption font-normal text-ink-3">
98
+ {section.description}
99
+ </span>
100
+ ) : null}
71
101
  </legend>
72
102
  ) : null}
73
103
  {section.fields.map((field) => {
@@ -78,15 +108,24 @@ export function SchemaForm({ fields, sections, schema, values, onChange, errors,
78
108
  <div className="flex items-center gap-2">
79
109
  <Label htmlFor={`field-${field.key}`}>
80
110
  {field.label}
81
- {field.required ? <span className="text-destructive"> *</span> : null}
111
+ {field.required ? (
112
+ <span className="text-destructive"> *</span>
113
+ ) : null}
82
114
  </Label>
83
115
  {isSuggested ? (
84
- <Badge variant="outline" className="gap-1 border-primary/30 bg-primary/10 px-1.5 py-0 text-caption text-primary">
116
+ <Badge
117
+ variant="outline"
118
+ className="gap-1 border-primary/30 bg-primary/10 px-1.5 py-0 text-caption text-primary"
119
+ >
85
120
  <Sparkles className="h-3 w-3" /> AI suggested
86
121
  </Badge>
87
122
  ) : null}
88
123
  </div>
89
- {field.description ? <p className="mb-1 text-caption text-ink-3">{field.description}</p> : null}
124
+ {field.description ? (
125
+ <p className="mb-1 text-caption text-ink-3">
126
+ {field.description}
127
+ </p>
128
+ ) : null}
90
129
  <SchemaFieldInput
91
130
  field={field}
92
131
  value={values[field.key]}
@@ -96,7 +135,9 @@ export function SchemaForm({ fields, sections, schema, values, onChange, errors,
96
135
  errors={errors}
97
136
  renderReference={renderReference}
98
137
  />
99
- {error ? <p className="mt-1 text-caption text-destructive">{error}</p> : null}
138
+ {error ? (
139
+ <p className="mt-1 text-caption text-destructive">{error}</p>
140
+ ) : null}
100
141
  </div>
101
142
  );
102
143
  })}
@@ -57,8 +57,12 @@ export function usePrefill<T extends CaptureValues = CaptureValues>(
57
57
  ): UsePrefillResult<T> {
58
58
  const { fetchDefaults, initialValues, enabled = true } = options;
59
59
 
60
- const [values, setValuesState] = useState<T>(() => ({ ...(initialValues ?? ({} as T)) }));
61
- const [suggested, setSuggested] = useState<ReadonlySet<string>>(() => new Set());
60
+ const [values, setValuesState] = useState<T>(() => ({
61
+ ...(initialValues ?? ({} as T)),
62
+ }));
63
+ const [suggested, setSuggested] = useState<ReadonlySet<string>>(
64
+ () => new Set(),
65
+ );
62
66
  const [loading, setLoading] = useState(false);
63
67
  const [error, setError] = useState<unknown>(null);
64
68
 
@@ -72,7 +76,9 @@ export function usePrefill<T extends CaptureValues = CaptureValues>(
72
76
  touched.current.add(key);
73
77
  setValuesState((prev) => ({ ...prev, [key]: value }));
74
78
  setSuggested((prev) => {
75
- if (!prev.has(key)) return prev;
79
+ if (!prev.has(key)) {
80
+ return prev;
81
+ }
76
82
  const next = new Set(prev);
77
83
  next.delete(key);
78
84
  return next;
@@ -82,9 +88,7 @@ export function usePrefill<T extends CaptureValues = CaptureValues>(
82
88
  const setValues = useCallback((updater: Partial<T> | ((prev: T) => T)) => {
83
89
  setValuesState((prev) => {
84
90
  const next =
85
- typeof updater === 'function'
86
- ? updater(prev)
87
- : { ...prev, ...updater };
91
+ typeof updater === 'function' ? updater(prev) : { ...prev, ...updater };
88
92
  const changed = new Set<string>();
89
93
  for (const k of Object.keys(next)) {
90
94
  if (next[k] !== prev[k]) {
@@ -94,9 +98,13 @@ export function usePrefill<T extends CaptureValues = CaptureValues>(
94
98
  }
95
99
  if (changed.size > 0) {
96
100
  setSuggested((prevSug) => {
97
- if (![...changed].some((k) => prevSug.has(k))) return prevSug;
101
+ if (![...changed].some((k) => prevSug.has(k))) {
102
+ return prevSug;
103
+ }
98
104
  const n = new Set(prevSug);
99
- for (const k of changed) n.delete(k);
105
+ for (const k of changed) {
106
+ n.delete(k);
107
+ }
100
108
  return n;
101
109
  });
102
110
  }
@@ -110,14 +118,17 @@ export function usePrefill<T extends CaptureValues = CaptureValues>(
110
118
  setError(null);
111
119
  void fetchDefaults()
112
120
  .then((defaults) => {
113
- if (id !== requestId.current) return; // superseded — drop
121
+ if (id !== requestId.current) {
122
+ return;
123
+ } // superseded — drop
114
124
  const applied: string[] = [];
115
125
  setValuesState((prev) => {
116
126
  const next = { ...prev };
117
127
  for (const [key, value] of Object.entries(defaults)) {
118
128
  // Only fill keys the user hasn't touched and that are still empty.
119
129
  const current = prev[key];
120
- const isEmpty = current === undefined || current === null || current === '';
130
+ const isEmpty =
131
+ current === undefined || current === null || current === '';
121
132
  if (!touched.current.has(key) && isEmpty && value !== undefined) {
122
133
  (next as CaptureValues)[key] = value;
123
134
  applied.push(key);
@@ -126,28 +137,50 @@ export function usePrefill<T extends CaptureValues = CaptureValues>(
126
137
  return next;
127
138
  });
128
139
  setSuggested((prev) => {
129
- if (applied.length === 0) return prev;
140
+ if (applied.length === 0) {
141
+ return prev;
142
+ }
130
143
  const n = new Set(prev);
131
- for (const k of applied) n.add(k);
144
+ for (const k of applied) {
145
+ n.add(k);
146
+ }
132
147
  return n;
133
148
  });
134
149
  })
135
150
  .catch((e: unknown) => {
136
- if (id !== requestId.current) return;
151
+ if (id !== requestId.current) {
152
+ return;
153
+ }
137
154
  setError(e);
138
155
  })
139
156
  .finally(() => {
140
- if (id === requestId.current) setLoading(false);
157
+ if (id === requestId.current) {
158
+ setLoading(false);
159
+ }
141
160
  });
142
161
  }, [fetchDefaults]);
143
162
 
144
163
  useEffect(() => {
145
- if (enabled) run();
164
+ if (enabled) {
165
+ run();
166
+ }
146
167
  // Run once on mount / when re-enabled; `reload()` is the explicit re-fetch.
147
168
  // eslint-disable-next-line react-hooks/exhaustive-deps
148
169
  }, [enabled]);
149
170
 
150
- const isSuggested = useCallback((key: string) => suggested.has(key), [suggested]);
171
+ const isSuggested = useCallback(
172
+ (key: string) => suggested.has(key),
173
+ [suggested],
174
+ );
151
175
 
152
- return { values, setValue, setValues, suggestedKeys: suggested, isSuggested, loading, error, reload: run };
176
+ return {
177
+ values,
178
+ setValue,
179
+ setValues,
180
+ suggestedKeys: suggested,
181
+ isSuggested,
182
+ loading,
183
+ error,
184
+ reload: run,
185
+ };
153
186
  }