@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
@@ -3,10 +3,10 @@ import { ChevronsUpDown, Loader2, Search } from 'lucide-react';
3
3
  import { useEffect, useRef, useState, type ReactNode } from 'react';
4
4
 
5
5
  import { cn } from '../cn';
6
- import { useDebouncedValue } from '../hooks/use-debounced-value';
7
6
  import { Button } from './button';
8
7
  import { Input } from './input';
9
8
  import { Popover, PopoverContent, PopoverTrigger } from './popover';
9
+ import { useDebouncedValue } from '../hooks/use-debounced-value';
10
10
 
11
11
  export interface AsyncComboboxProps<T> {
12
12
  /** Unique key prefix for query caching to avoid collisions between combobox instances. */
@@ -99,7 +99,9 @@ export function AsyncCombobox<T>({
99
99
  };
100
100
 
101
101
  const showTypeToSearchHint =
102
- !isLoading && minSearchLength > 0 && debouncedSearch.length < minSearchLength;
102
+ !isLoading &&
103
+ minSearchLength > 0 &&
104
+ debouncedSearch.length < minSearchLength;
103
105
  const showEmptyMessage = !isLoading && searchEnabled && results.length === 0;
104
106
 
105
107
  return (
@@ -156,7 +158,9 @@ export function AsyncCombobox<T>({
156
158
  )}
157
159
 
158
160
  {showEmptyMessage && (
159
- <p className="text-body-1 text-ink-3 text-center py-4">{emptyMessage}</p>
161
+ <p className="text-body-1 text-ink-3 text-center py-4">
162
+ {emptyMessage}
163
+ </p>
160
164
  )}
161
165
 
162
166
  {!isLoading &&
@@ -1,16 +1,25 @@
1
- import type { VariantProps } from "class-variance-authority";
2
- import * as React from "react";
1
+ import * as React from 'react';
3
2
 
4
3
  import { cn } from '../cn';
5
4
  import { badgeVariants } from './badge-variants';
6
5
 
7
- export interface BadgeProps extends React.HTMLAttributes<HTMLSpanElement>, VariantProps<typeof badgeVariants> {}
6
+ import type { VariantProps } from 'class-variance-authority';
7
+
8
+ export interface BadgeProps
9
+ extends React.HTMLAttributes<HTMLSpanElement>,
10
+ VariantProps<typeof badgeVariants> {}
8
11
 
9
12
  const Badge = React.forwardRef<HTMLSpanElement, BadgeProps>(
10
13
  ({ className, variant, ...props }, ref) => {
11
- return <span ref={ref} className={cn(badgeVariants({ variant }), className)} {...props} />;
14
+ return (
15
+ <span
16
+ ref={ref}
17
+ className={cn(badgeVariants({ variant }), className)}
18
+ {...props}
19
+ />
20
+ );
12
21
  },
13
22
  );
14
- Badge.displayName = "Badge";
23
+ Badge.displayName = 'Badge';
15
24
 
16
25
  export { Badge };
@@ -1,10 +1,11 @@
1
- import { Slot } from "@radix-ui/react-slot";
2
- import type { VariantProps } from "class-variance-authority";
3
- import * as React from "react";
1
+ import { Slot } from '@radix-ui/react-slot';
2
+ import * as React from 'react';
4
3
 
5
4
  import { cn } from '../cn';
6
5
  import { buttonVariants } from './button-variants';
7
6
 
7
+ import type { VariantProps } from 'class-variance-authority';
8
+
8
9
  export interface ButtonProps
9
10
  extends React.ButtonHTMLAttributes<HTMLButtonElement>,
10
11
  VariantProps<typeof buttonVariants> {
@@ -13,10 +14,16 @@ export interface ButtonProps
13
14
 
14
15
  const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
15
16
  ({ className, variant, size, asChild = false, ...props }, ref) => {
16
- const Comp = asChild ? Slot : "button";
17
- return <Comp className={cn(buttonVariants({ variant, size, className }))} ref={ref} {...props} />;
17
+ const Comp = asChild ? Slot : 'button';
18
+ return (
19
+ <Comp
20
+ className={cn(buttonVariants({ variant, size, className }))}
21
+ ref={ref}
22
+ {...props}
23
+ />
24
+ );
18
25
  },
19
26
  );
20
- Button.displayName = "Button";
27
+ Button.displayName = 'Button';
21
28
 
22
29
  export { Button };
@@ -83,7 +83,9 @@ export function OverflowTabs({
83
83
  // Measure container width and react to resizes.
84
84
  useEffect(() => {
85
85
  const el = containerRef.current;
86
- if (!el) return;
86
+ if (!el) {
87
+ return;
88
+ }
87
89
  const ro = new ResizeObserver((entries) => {
88
90
  const w = entries[0]?.contentRect.width ?? el.clientWidth;
89
91
  setContainerWidth(w);
@@ -97,7 +99,9 @@ export function OverflowTabs({
97
99
  // when the tab list itself changes (new tabs, label edits).
98
100
  useLayoutEffect(() => {
99
101
  const el = measureRef.current;
100
- if (!el) return;
102
+ if (!el) {
103
+ return;
104
+ }
101
105
  const children = Array.from(el.children) as HTMLElement[];
102
106
  setTabWidths(children.map((c) => c.getBoundingClientRect().width));
103
107
  }, [tabs]);
@@ -118,36 +122,53 @@ export function OverflowTabs({
118
122
  const vis: OverflowTab[] = [];
119
123
  const over: OverflowTab[] = [];
120
124
  let used = 0;
121
- for (let i = 0; i < tabs.length; i++) {
122
- const w = tabWidths[i] + (vis.length > 0 ? gap : 0);
125
+ for (const [i, tab] of tabs.entries()) {
126
+ const natural = tabWidths[i];
127
+ if (natural === undefined) {
128
+ // Unreachable: the length-parity guard above already returned. Kept as a
129
+ // real check because the alternative — treating a missing measurement as
130
+ // 0px — would lay tabs out against a budget they don't actually fit.
131
+ // Fall back to the same all-visible layout the parity guard renders.
132
+ return { visible: tabs, overflow: [] as readonly OverflowTab[] };
133
+ }
134
+ const w = natural + (vis.length > 0 ? gap : 0);
123
135
  // A pinned tab is never collapsed — it stays visible whatever the budget
124
136
  // says, so a panel's permanent first tab can't hide behind "More…".
125
- if (tabs[i].pinned === true || used + w <= budget) {
126
- vis.push(tabs[i]);
137
+ if (tab.pinned === true || used + w <= budget) {
138
+ vis.push(tab);
127
139
  used += w;
128
140
  } else {
129
- over.push(tabs[i]);
141
+ over.push(tab);
130
142
  }
131
143
  }
132
144
  // Force the active tab into the visible set if it ended up in overflow.
133
- const activeIdx = tabs.findIndex((t) => t.value === value);
134
- if (activeIdx !== -1) {
135
- const activeTab = tabs[activeIdx];
145
+ // `find` (not `findIndex` + lookup) so the hit is typed as present.
146
+ const activeTab = tabs.find((t) => t.value === value);
147
+ if (activeTab !== undefined) {
136
148
  const inVisible = vis.some((t) => t.value === activeTab.value);
137
149
  if (!inVisible) {
138
150
  // Swap the last visible for the active one to keep the budget OK.
139
151
  const dropped = vis.pop();
140
- if (dropped) over.unshift(dropped);
152
+ if (dropped) {
153
+ over.unshift(dropped);
154
+ }
141
155
  vis.push(activeTab);
142
156
  const removeIdx = over.findIndex((t) => t.value === activeTab.value);
143
- if (removeIdx !== -1) over.splice(removeIdx, 1);
157
+ if (removeIdx !== -1) {
158
+ over.splice(removeIdx, 1);
159
+ }
144
160
  }
145
161
  }
146
162
  return { visible: vis, overflow: over };
147
163
  }, [tabs, tabWidths, containerWidth, gap, moreTriggerWidth, value]);
148
164
 
149
165
  return (
150
- <div className={cn('relative -mb-px flex items-end border-b border-rule', className)}>
166
+ <div
167
+ className={cn(
168
+ 'relative -mb-px flex items-end border-b border-rule',
169
+ className,
170
+ )}
171
+ >
151
172
  {/* Off-screen measurement layer — renders ALL tabs so widths are real. */}
152
173
  <div
153
174
  ref={measureRef}
@@ -156,7 +177,12 @@ export function OverflowTabs({
156
177
  style={{ visibility: 'hidden' }}
157
178
  >
158
179
  {tabs.map((t) => (
159
- <TabPill key={`measure-${t.value}`} tab={t} active={false} onClick={() => undefined} />
180
+ <TabPill
181
+ key={`measure-${t.value}`}
182
+ tab={t}
183
+ active={false}
184
+ onClick={() => undefined}
185
+ />
160
186
  ))}
161
187
  </div>
162
188
 
@@ -199,11 +225,15 @@ export function OverflowTabs({
199
225
  <DropdownMenuItem
200
226
  key={t.value}
201
227
  onClick={() => onChange(t.value)}
202
- className={cn(t.value === value && 'bg-accent/60 text-foreground')}
228
+ className={cn(
229
+ t.value === value && 'bg-accent/60 text-foreground',
230
+ )}
203
231
  >
204
232
  <span className="flex-1 truncate">{t.label}</span>
205
233
  {t.count !== undefined && (
206
- <span className="ml-2 text-caption tabular-nums text-ink-4">{t.count}</span>
234
+ <span className="ml-2 text-caption tabular-nums text-ink-4">
235
+ {t.count}
236
+ </span>
207
237
  )}
208
238
  {t.indicator && (
209
239
  <span
@@ -96,10 +96,14 @@ function ScaledBezel({ bezel, children }: ScaledBezelProps) {
96
96
 
97
97
  useLayoutEffect(() => {
98
98
  const el = containerRef.current;
99
- if (!el) return;
99
+ if (!el) {
100
+ return;
101
+ }
100
102
  const compute = (): void => {
101
103
  const { clientWidth, clientHeight } = el;
102
- if (clientWidth === 0 || clientHeight === 0) return;
104
+ if (clientWidth === 0 || clientHeight === 0) {
105
+ return;
106
+ }
103
107
  // Leave a tiny margin so the shadow is not clipped.
104
108
  const margin = 24;
105
109
  const availW = Math.max(0, clientWidth - margin);
@@ -163,10 +167,14 @@ function ResponsiveViewport({
163
167
 
164
168
  useLayoutEffect(() => {
165
169
  const el = containerRef.current;
166
- if (!el) return;
170
+ if (!el) {
171
+ return;
172
+ }
167
173
  const compute = (): void => {
168
174
  const { clientWidth, clientHeight } = el;
169
- if (clientWidth === 0 || clientHeight === 0) return;
175
+ if (clientWidth === 0 || clientHeight === 0) {
176
+ return;
177
+ }
170
178
  const margin = 24;
171
179
  const availW = Math.max(0, clientWidth - margin);
172
180
  const availH = Math.max(0, clientHeight - margin);
@@ -30,7 +30,10 @@ export interface TagMultiSelectProps {
30
30
  disabled?: boolean;
31
31
  }
32
32
 
33
- const CHIP_CLASSES: Record<NonNullable<TagMultiSelectProps['chipVariant']>, string> = {
33
+ const CHIP_CLASSES: Record<
34
+ NonNullable<TagMultiSelectProps['chipVariant']>,
35
+ string
36
+ > = {
34
37
  default: 'bg-primary/10 text-primary border-primary/20',
35
38
  secondary: 'bg-secondary text-secondary-foreground border-secondary',
36
39
  success: 'bg-success/10 text-success border-success/20',
@@ -63,7 +66,9 @@ export function TagMultiSelect({
63
66
 
64
67
  const filteredOptions = useMemo(() => {
65
68
  const q = search.trim().toLowerCase();
66
- if (!q) return options;
69
+ if (!q) {
70
+ return options;
71
+ }
67
72
  return options.filter(
68
73
  (o) =>
69
74
  o.label.toLowerCase().includes(q) ||
@@ -93,7 +98,9 @@ export function TagMultiSelect({
93
98
  };
94
99
 
95
100
  const addCustom = () => {
96
- if (!canAddCustom) return;
101
+ if (!canAddCustom) {
102
+ return;
103
+ }
97
104
  onChange([...value, normalizedSearch]);
98
105
  setSearch('');
99
106
  inputRef.current?.focus();
@@ -104,8 +111,13 @@ export function TagMultiSelect({
104
111
  e.preventDefault();
105
112
  if (canAddCustom) {
106
113
  addCustom();
107
- } else if (filteredOptions.length === 1) {
108
- toggle(filteredOptions[0].value);
114
+ } else {
115
+ // Enter with exactly one remaining match selects it.
116
+ const onlyMatch =
117
+ filteredOptions.length === 1 ? filteredOptions[0] : undefined;
118
+ if (onlyMatch !== undefined) {
119
+ toggle(onlyMatch.value);
120
+ }
109
121
  }
110
122
  }
111
123
  };
@@ -137,7 +149,9 @@ export function TagMultiSelect({
137
149
  variant="outline"
138
150
  className={cn('text-body-1 gap-1 pr-1', chipClass)}
139
151
  >
140
- <span className="truncate max-w-[160px]">{opt?.label ?? val}</span>
152
+ <span className="truncate max-w-[160px]">
153
+ {opt?.label ?? val}
154
+ </span>
141
155
  <button
142
156
  type="button"
143
157
  onClick={(e) => remove(val, e)}
@@ -183,7 +197,9 @@ export function TagMultiSelect({
183
197
  <ScrollArea className="max-h-56">
184
198
  <div className="p-1">
185
199
  {filteredOptions.length === 0 && !canAddCustom && (
186
- <p className="text-body-1 text-ink-3 text-center py-3">{emptyMessage}</p>
200
+ <p className="text-body-1 text-ink-3 text-center py-3">
201
+ {emptyMessage}
202
+ </p>
187
203
  )}
188
204
 
189
205
  {filteredOptions.map((opt) => {
@@ -209,7 +225,9 @@ export function TagMultiSelect({
209
225
  {selected && <Check className="h-4 w-4" />}
210
226
  </span>
211
227
  <span className="flex-1 min-w-0">
212
- <span className="font-medium block truncate">{opt.label}</span>
228
+ <span className="font-medium block truncate">
229
+ {opt.label}
230
+ </span>
213
231
  {opt.hint && (
214
232
  <span className="text-body-1 text-ink-3 block truncate">
215
233
  {opt.hint}
@@ -228,7 +246,10 @@ export function TagMultiSelect({
228
246
  >
229
247
  <Plus className="h-4 w-4 text-ink-3" />
230
248
  <span>
231
- Add <span className="font-mono font-medium">{normalizedSearch}</span>
249
+ Add{' '}
250
+ <span className="font-mono font-medium">
251
+ {normalizedSearch}
252
+ </span>
232
253
  </span>
233
254
  </button>
234
255
  )}
@@ -9,6 +9,7 @@
9
9
  * implementation.
10
10
  */
11
11
  import { RotateCw } from 'lucide-react';
12
+
12
13
  import type { ReactElement, ReactNode } from 'react';
13
14
 
14
15
  const TRAFFIC_LIGHTS = ['#e5645a', '#e8b13d', '#5bb35b'] as const;
@@ -30,11 +30,15 @@ interface GenericSurfaceField {
30
30
  }
31
31
 
32
32
  function stringify(value: unknown): string {
33
- if (typeof value === 'string') return value;
33
+ if (typeof value === 'string') {
34
+ return value;
35
+ }
34
36
  if (typeof value === 'number' || typeof value === 'boolean') {
35
37
  return String(value);
36
38
  }
37
- if (value === null || value === undefined) return '—';
39
+ if (value === null || value === undefined) {
40
+ return '—';
41
+ }
38
42
  try {
39
43
  return JSON.stringify(value);
40
44
  } catch {
@@ -43,9 +47,7 @@ function stringify(value: unknown): string {
43
47
  }
44
48
 
45
49
  function isPlainObject(value: unknown): value is Record<string, unknown> {
46
- return (
47
- typeof value === 'object' && value !== null && !Array.isArray(value)
48
- );
50
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
49
51
  }
50
52
 
51
53
  /**
@@ -114,10 +114,16 @@ export function VistaTabBar({
114
114
  indicator?: boolean;
115
115
  icon?: OverflowTab['icon'];
116
116
  } = { value: tab.tabId, label: tab.title };
117
- if (tab.pinned === true) entry.pinned = true;
118
- if (indicatorTabIds?.includes(tab.tabId) === true) entry.indicator = true;
117
+ if (tab.pinned === true) {
118
+ entry.pinned = true;
119
+ }
120
+ if (indicatorTabIds?.includes(tab.tabId) === true) {
121
+ entry.indicator = true;
122
+ }
119
123
  const icon = surfaceKindIcon(tab.kind);
120
- if (icon !== undefined) entry.icon = icon;
124
+ if (icon !== undefined) {
125
+ entry.icon = icon;
126
+ }
121
127
  return entry;
122
128
  });
123
129
  return (
@@ -143,7 +149,9 @@ export function VistaSurfaceBody({
143
149
  tab,
144
150
  }: Readonly<{ tab: VistaTab }>): ReactElement {
145
151
  const resolution = vistaSurfaceRegistry.resolve(tab);
146
- if (resolution.matched) return resolution.rendered;
152
+ if (resolution.matched) {
153
+ return resolution.rendered;
154
+ }
147
155
  return (
148
156
  <SurfaceFallbackCard
149
157
  kind={resolution.kind}
@@ -34,7 +34,9 @@ const STYLE_CSS = ':root{--x:1}';
34
34
  function parseIframe(markup: string): Element {
35
35
  const doc = new DOMParser().parseFromString(markup, 'text/html');
36
36
  const iframe = doc.querySelector('iframe');
37
- if (!iframe) throw new Error('no iframe rendered');
37
+ if (!iframe) {
38
+ throw new Error('no iframe rendered');
39
+ }
38
40
  return iframe;
39
41
  }
40
42
 
@@ -153,7 +153,9 @@ export function CustomUiFrame<TIntent>({
153
153
  // re-render, per the HostProps contract). Before ready, the frameReady
154
154
  // handler above pushes the current props — so no update is lost.
155
155
  useEffect(() => {
156
- if (!readyRef.current) return;
156
+ if (!readyRef.current) {
157
+ return;
158
+ }
157
159
  iframeRef.current?.contentWindow?.postMessage(
158
160
  hostPropsMessage(componentProps),
159
161
  '*',
@@ -52,10 +52,14 @@ export function classifyFrameMessage<TIntent>(
52
52
  ): ClassifiedFrameMessage<TIntent> {
53
53
  // Gate 1: source identity. Reject if we have no frame yet or the message did
54
54
  // not come from THIS frame's window.
55
- if (frameWindow === null || event.source !== frameWindow) return IGNORED;
55
+ if (frameWindow === null || event.source !== frameWindow) {
56
+ return IGNORED;
57
+ }
56
58
 
57
59
  const data = event.data;
58
- if (data === null || typeof data !== 'object') return IGNORED;
60
+ if (data === null || typeof data !== 'object') {
61
+ return IGNORED;
62
+ }
59
63
  const envelope = data as {
60
64
  protocol?: unknown;
61
65
  type?: unknown;
@@ -64,7 +68,9 @@ export function classifyFrameMessage<TIntent>(
64
68
  };
65
69
 
66
70
  // Gate 2: protocol version.
67
- if (envelope.protocol !== CUSTOM_UI_FRAME_PROTOCOL) return IGNORED;
71
+ if (envelope.protocol !== CUSTOM_UI_FRAME_PROTOCOL) {
72
+ return IGNORED;
73
+ }
68
74
 
69
75
  // Gate 3: closed message-type set.
70
76
  switch (envelope.type) {
@@ -104,7 +104,9 @@ describe('createNavigateIntentSet', () => {
104
104
  kind: CustomUiIntentKind.Navigate,
105
105
  href: '/apps/x',
106
106
  });
107
- if (intent === null) throw new Error('expected a parsed navigate intent');
107
+ if (intent === null) {
108
+ throw new Error('expected a parsed navigate intent');
109
+ }
108
110
  set.perform(intent);
109
111
  expect(navigate).toHaveBeenCalledWith({
110
112
  kind: CustomUiIntentKind.Navigate,
@@ -72,13 +72,19 @@ export interface CustomUiIntentHandlers {
72
72
  */
73
73
  function isHostRelativePath(href: string): boolean {
74
74
  // Must be rooted at '/'.
75
- if (!href.startsWith('/')) return false;
75
+ if (!href.startsWith('/')) {
76
+ return false;
77
+ }
76
78
  // A backslash is a protocol-relative/scheme trick after WHATWG normalisation
77
79
  // ("/\\evil.com" -> //evil.com -> foreign origin); whitespace / control
78
80
  // chars can also confuse the parser. Reject any before resolving.
79
- if (href.includes('\\')) return false;
81
+ if (href.includes('\\')) {
82
+ return false;
83
+ }
80
84
  // eslint-disable-next-line no-control-regex
81
- if (/[\u0000-\u0020\u007f]/.test(href)) return false;
85
+ if (/[\u0000-\u0020\u007f]/.test(href)) {
86
+ return false;
87
+ }
82
88
  let resolved: URL;
83
89
  try {
84
90
  resolved = new URL(href, window.location.origin);
@@ -96,12 +102,18 @@ function isHostRelativePath(href: string): boolean {
96
102
  * an out-of-policy value all return `null` — the caller rejects it.
97
103
  */
98
104
  export function parseCustomUiIntent(raw: unknown): CustomUiIntent | null {
99
- if (raw === null || typeof raw !== 'object') return null;
105
+ if (raw === null || typeof raw !== 'object') {
106
+ return null;
107
+ }
100
108
  const candidate = raw as { kind?: unknown; href?: unknown };
101
109
  switch (candidate.kind) {
102
110
  case CustomUiIntentKind.Navigate:
103
- if (typeof candidate.href !== 'string') return null;
104
- if (!isHostRelativePath(candidate.href)) return null;
111
+ if (typeof candidate.href !== 'string') {
112
+ return null;
113
+ }
114
+ if (!isHostRelativePath(candidate.href)) {
115
+ return null;
116
+ }
105
117
  return { kind: CustomUiIntentKind.Navigate, href: candidate.href };
106
118
  default:
107
119
  return null;
@@ -118,15 +130,7 @@ export function performCustomUiIntent(
118
130
  intent: CustomUiIntent,
119
131
  handlers: CustomUiIntentHandlers,
120
132
  ): void {
121
- switch (intent.kind) {
122
- case CustomUiIntentKind.Navigate:
123
- handlers[CustomUiIntentKind.Navigate](intent);
124
- return;
125
- default: {
126
- const exhaustive: never = intent.kind;
127
- throw new Error(`Unhandled custom-UI intent kind: ${String(exhaustive)}`);
128
- }
129
- }
133
+ handlers[CustomUiIntentKind.Navigate](intent);
130
134
  }
131
135
 
132
136
  /** The built-in intent set: host-relative navigation and nothing else. */
@@ -55,16 +55,22 @@ export function __resetSurfaceCatalogueSyncForTests(): void {
55
55
  export async function syncSurfaceCatalogue(
56
56
  fetchCatalogue: SurfaceCatalogueFetcher,
57
57
  ): Promise<void> {
58
- if (synced) return;
58
+ if (synced) {
59
+ return;
60
+ }
59
61
  synced = true;
60
62
  try {
61
63
  const entries = await fetchCatalogue();
62
64
  for (const entry of entries) {
63
65
  // Only biome-contributed kinds need registering here; first-party kinds
64
66
  // are already registered by the static builtins.
65
- if (entry.source !== SurfaceKindSource.Biome) continue;
67
+ if (entry.source !== SurfaceKindSource.Biome) {
68
+ continue;
69
+ }
66
70
  // Never shadow a biome's own (or an already-registered) renderer.
67
- if (vistaSurfaceRegistry.has(entry.kind)) continue;
71
+ if (vistaSurfaceRegistry.has(entry.kind)) {
72
+ continue;
73
+ }
68
74
  vistaSurfaceRegistry.register(entry.kind, {
69
75
  version: entry.version,
70
76
  validate: (payload) =>
@@ -48,10 +48,7 @@ import { captureValuesToStringMap } from '../../ui/capture/submit-values';
48
48
  import { useSchemaValidation } from '../../ui/capture/use-schema-validation';
49
49
  import { cn } from '../../ui/cn';
50
50
  import { Button } from '../../ui/primitives/button';
51
- import {
52
- useVistaFormHost,
53
- type VistaFormOutcome,
54
- } from '../vista-form-context';
51
+ import { useVistaFormHost, type VistaFormOutcome } from '../vista-form-context';
55
52
 
56
53
  import type { CaptureValues } from '../../ui/capture/field-spec';
57
54
  import type { VistaFormPayload } from '../vista-payloads';
@@ -117,9 +114,13 @@ export function FormSurface(payload: Readonly<VistaFormPayload>): ReactElement {
117
114
  }, []);
118
115
 
119
116
  const handleSubmit = useCallback((): void => {
120
- if (host === null) return;
117
+ if (host === null) {
118
+ return;
119
+ }
121
120
  setShowFieldErrors(true);
122
- if (!isValid) return;
121
+ if (!isValid) {
122
+ return;
123
+ }
123
124
  setServiceError(null);
124
125
  setPhase(FormPhase.Working);
125
126
  // The values object is a PARAMETER here and nowhere else. It is never
@@ -138,7 +139,9 @@ export function FormSurface(payload: Readonly<VistaFormPayload>): ReactElement {
138
139
  }, [host, isValid, payload.fields, payload.ref, settle, failed, values]);
139
140
 
140
141
  const handleCheckStatus = useCallback((): void => {
141
- if (host === null) return;
142
+ if (host === null) {
143
+ return;
144
+ }
142
145
  setServiceError(null);
143
146
  setPhase(FormPhase.Working);
144
147
  void host
@@ -167,10 +170,24 @@ export function FormSurface(payload: Readonly<VistaFormPayload>): ReactElement {
167
170
  // an event, not a timer — there is no polling loop and no timeout.
168
171
  const isLaunch = payload.launch !== undefined;
169
172
  useEffect(() => {
170
- if (!isLaunch || phase === FormPhase.Settled || host === null) return;
173
+ if (!isLaunch || phase === FormPhase.Settled || host === null) {
174
+ return;
175
+ }
171
176
  const onFocus = (): void => handleCheckStatus();
172
- globalThis.addEventListener?.('focus', onFocus);
173
- return () => globalThis.removeEventListener?.('focus', onFocus);
177
+ const addEventListener: unknown = Reflect.get(globalThis, 'addEventListener');
178
+ if (typeof addEventListener !== 'function') {
179
+ return;
180
+ }
181
+ Reflect.apply(addEventListener, globalThis, ['focus', onFocus]);
182
+ return () => {
183
+ const removeEventListener: unknown = Reflect.get(
184
+ globalThis,
185
+ 'removeEventListener',
186
+ );
187
+ if (typeof removeEventListener === 'function') {
188
+ Reflect.apply(removeEventListener, globalThis, ['focus', onFocus]);
189
+ }
190
+ };
174
191
  // `handleCheckStatus` is stable per (host, payload) and re-subscribing on a
175
192
  // phase change is intended: a settled surface stops listening.
176
193
  }, [isLaunch, phase, host, handleCheckStatus]);
@@ -9,9 +9,10 @@
9
9
  import type { VistaTablePayload } from '../vista-payloads';
10
10
  import type { ReactElement } from 'react';
11
11
 
12
-
13
12
  function cellText(value: unknown): string {
14
- if (value === null || value === undefined) return '';
13
+ if (value === null || value === undefined) {
14
+ return '';
15
+ }
15
16
  if (typeof value === 'object') {
16
17
  try {
17
18
  return JSON.stringify(value);
@@ -62,7 +63,7 @@ export function TableSurface({
62
63
  <tr
63
64
  // Rows carry no identity in the generic contract; position is the
64
65
  // only stable key available.
65
-
66
+
66
67
  key={rowIndex}
67
68
  >
68
69
  {columns.map((column, columnIndex) => (