@rezi-ui/core 0.1.0-alpha.60 → 0.1.0-alpha.63

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 (345) hide show
  1. package/dist/app/createApp/breadcrumbs.d.ts +38 -0
  2. package/dist/app/createApp/breadcrumbs.d.ts.map +1 -0
  3. package/dist/app/createApp/breadcrumbs.js +65 -0
  4. package/dist/app/createApp/breadcrumbs.js.map +1 -0
  5. package/dist/app/createApp/config.d.ts +25 -0
  6. package/dist/app/createApp/config.d.ts.map +1 -0
  7. package/dist/app/createApp/config.js +130 -0
  8. package/dist/app/createApp/config.js.map +1 -0
  9. package/dist/app/createApp/eventLoop.d.ts +95 -0
  10. package/dist/app/createApp/eventLoop.d.ts.map +1 -0
  11. package/dist/app/createApp/eventLoop.js +384 -0
  12. package/dist/app/createApp/eventLoop.js.map +1 -0
  13. package/dist/app/createApp/guards.d.ts +21 -0
  14. package/dist/app/createApp/guards.d.ts.map +1 -0
  15. package/dist/app/createApp/guards.js +54 -0
  16. package/dist/app/createApp/guards.js.map +1 -0
  17. package/dist/app/createApp/keybindings.d.ts +28 -0
  18. package/dist/app/createApp/keybindings.d.ts.map +1 -0
  19. package/dist/app/createApp/keybindings.js +113 -0
  20. package/dist/app/createApp/keybindings.js.map +1 -0
  21. package/dist/app/createApp/renderLoop.d.ts +64 -0
  22. package/dist/app/createApp/renderLoop.d.ts.map +1 -0
  23. package/dist/app/createApp/renderLoop.js +305 -0
  24. package/dist/app/createApp/renderLoop.js.map +1 -0
  25. package/dist/app/createApp.d.ts +3 -39
  26. package/dist/app/createApp.d.ts.map +1 -1
  27. package/dist/app/createApp.js +403 -1205
  28. package/dist/app/createApp.js.map +1 -1
  29. package/dist/app/widgetRenderer/constraintState.d.ts +98 -0
  30. package/dist/app/widgetRenderer/constraintState.d.ts.map +1 -0
  31. package/dist/app/widgetRenderer/constraintState.js +563 -0
  32. package/dist/app/widgetRenderer/constraintState.js.map +1 -0
  33. package/dist/app/widgetRenderer/fileNodeCache.d.ts +2 -0
  34. package/dist/app/widgetRenderer/fileNodeCache.d.ts.map +1 -1
  35. package/dist/app/widgetRenderer/fileNodeCache.js +31 -0
  36. package/dist/app/widgetRenderer/fileNodeCache.js.map +1 -1
  37. package/dist/app/widgetRenderer/filePickerRouting.d.ts +12 -1
  38. package/dist/app/widgetRenderer/filePickerRouting.d.ts.map +1 -1
  39. package/dist/app/widgetRenderer/filePickerRouting.js +63 -14
  40. package/dist/app/widgetRenderer/filePickerRouting.js.map +1 -1
  41. package/dist/app/widgetRenderer/focusState.d.ts +46 -0
  42. package/dist/app/widgetRenderer/focusState.d.ts.map +1 -0
  43. package/dist/app/widgetRenderer/focusState.js +122 -0
  44. package/dist/app/widgetRenderer/focusState.js.map +1 -0
  45. package/dist/app/widgetRenderer/keyboardRouting.d.ts.map +1 -1
  46. package/dist/app/widgetRenderer/keyboardRouting.js.map +1 -1
  47. package/dist/app/widgetRenderer/mouseRouting.d.ts +5 -0
  48. package/dist/app/widgetRenderer/mouseRouting.d.ts.map +1 -1
  49. package/dist/app/widgetRenderer/mouseRouting.js +78 -8
  50. package/dist/app/widgetRenderer/mouseRouting.js.map +1 -1
  51. package/dist/app/widgetRenderer/overlayShortcuts.d.ts.map +1 -1
  52. package/dist/app/widgetRenderer/overlayShortcuts.js +14 -4
  53. package/dist/app/widgetRenderer/overlayShortcuts.js.map +1 -1
  54. package/dist/app/widgetRenderer/overlayState.d.ts +198 -0
  55. package/dist/app/widgetRenderer/overlayState.d.ts.map +1 -0
  56. package/dist/app/widgetRenderer/overlayState.js +590 -0
  57. package/dist/app/widgetRenderer/overlayState.js.map +1 -0
  58. package/dist/app/widgetRenderer/routeEngineEvent.d.ts +189 -0
  59. package/dist/app/widgetRenderer/routeEngineEvent.d.ts.map +1 -0
  60. package/dist/app/widgetRenderer/routeEngineEvent.js +527 -0
  61. package/dist/app/widgetRenderer/routeEngineEvent.js.map +1 -0
  62. package/dist/app/widgetRenderer.d.ts +2 -1
  63. package/dist/app/widgetRenderer.d.ts.map +1 -1
  64. package/dist/app/widgetRenderer.js +334 -1707
  65. package/dist/app/widgetRenderer.js.map +1 -1
  66. package/dist/forms/internal/arrayState.d.ts +35 -0
  67. package/dist/forms/internal/arrayState.d.ts.map +1 -0
  68. package/dist/forms/internal/arrayState.js +238 -0
  69. package/dist/forms/internal/arrayState.js.map +1 -0
  70. package/dist/forms/internal/bindings.d.ts +46 -0
  71. package/dist/forms/internal/bindings.d.ts.map +1 -0
  72. package/dist/forms/internal/bindings.js +161 -0
  73. package/dist/forms/internal/bindings.js.map +1 -0
  74. package/dist/forms/internal/dev.d.ts +4 -0
  75. package/dist/forms/internal/dev.d.ts.map +1 -0
  76. package/dist/forms/internal/dev.js +21 -0
  77. package/dist/forms/internal/dev.js.map +1 -0
  78. package/dist/forms/internal/state.d.ts +52 -0
  79. package/dist/forms/internal/state.d.ts.map +1 -0
  80. package/dist/forms/internal/state.js +240 -0
  81. package/dist/forms/internal/state.js.map +1 -0
  82. package/dist/forms/internal/submit.d.ts +43 -0
  83. package/dist/forms/internal/submit.d.ts.map +1 -0
  84. package/dist/forms/internal/submit.js +165 -0
  85. package/dist/forms/internal/submit.js.map +1 -0
  86. package/dist/forms/internal/wizard.d.ts +53 -0
  87. package/dist/forms/internal/wizard.d.ts.map +1 -0
  88. package/dist/forms/internal/wizard.js +311 -0
  89. package/dist/forms/internal/wizard.js.map +1 -0
  90. package/dist/forms/useForm.d.ts.map +1 -1
  91. package/dist/forms/useForm.js +90 -1117
  92. package/dist/forms/useForm.js.map +1 -1
  93. package/dist/index.d.ts +1 -1
  94. package/dist/index.d.ts.map +1 -1
  95. package/dist/index.js +1 -1
  96. package/dist/index.js.map +1 -1
  97. package/dist/keybindings/manager.d.ts.map +1 -1
  98. package/dist/keybindings/manager.js.map +1 -1
  99. package/dist/keybindings/parser.d.ts.map +1 -1
  100. package/dist/keybindings/parser.js +10 -5
  101. package/dist/keybindings/parser.js.map +1 -1
  102. package/dist/layout/dropdownGeometry.d.ts +8 -0
  103. package/dist/layout/dropdownGeometry.d.ts.map +1 -1
  104. package/dist/layout/dropdownGeometry.js +40 -0
  105. package/dist/layout/dropdownGeometry.js.map +1 -1
  106. package/dist/layout/engine/layoutEngine.js +1 -1
  107. package/dist/layout/engine/layoutEngine.js.map +1 -1
  108. package/dist/layout/kinds/overlays.d.ts.map +1 -1
  109. package/dist/layout/kinds/stack.d.ts +1 -3
  110. package/dist/layout/kinds/stack.d.ts.map +1 -1
  111. package/dist/layout/kinds/stack.js +11 -1523
  112. package/dist/layout/kinds/stack.js.map +1 -1
  113. package/dist/layout/kinds/stackParts/axis.d.ts +32 -0
  114. package/dist/layout/kinds/stackParts/axis.d.ts.map +1 -0
  115. package/dist/layout/kinds/stackParts/axis.js +61 -0
  116. package/dist/layout/kinds/stackParts/axis.js.map +1 -0
  117. package/dist/layout/kinds/stackParts/constraintPlan.d.ts +18 -0
  118. package/dist/layout/kinds/stackParts/constraintPlan.d.ts.map +1 -0
  119. package/dist/layout/kinds/stackParts/constraintPlan.js +434 -0
  120. package/dist/layout/kinds/stackParts/constraintPlan.js.map +1 -0
  121. package/dist/layout/kinds/stackParts/layout.d.ts +6 -0
  122. package/dist/layout/kinds/stackParts/layout.d.ts.map +1 -0
  123. package/dist/layout/kinds/stackParts/layout.js +376 -0
  124. package/dist/layout/kinds/stackParts/layout.js.map +1 -0
  125. package/dist/layout/kinds/stackParts/measure.d.ts +6 -0
  126. package/dist/layout/kinds/stackParts/measure.d.ts.map +1 -0
  127. package/dist/layout/kinds/stackParts/measure.js +212 -0
  128. package/dist/layout/kinds/stackParts/measure.js.map +1 -0
  129. package/dist/layout/kinds/stackParts/shared.d.ts +31 -0
  130. package/dist/layout/kinds/stackParts/shared.d.ts.map +1 -0
  131. package/dist/layout/kinds/stackParts/shared.js +94 -0
  132. package/dist/layout/kinds/stackParts/shared.js.map +1 -0
  133. package/dist/layout/kinds/stackParts/wrap.d.ts +26 -0
  134. package/dist/layout/kinds/stackParts/wrap.d.ts.map +1 -0
  135. package/dist/layout/kinds/stackParts/wrap.js +374 -0
  136. package/dist/layout/kinds/stackParts/wrap.js.map +1 -0
  137. package/dist/layout/validate/interactive.d.ts +106 -0
  138. package/dist/layout/validate/interactive.d.ts.map +1 -0
  139. package/dist/layout/validate/interactive.js +430 -0
  140. package/dist/layout/validate/interactive.js.map +1 -0
  141. package/dist/layout/validate/layoutConstraints.d.ts +51 -0
  142. package/dist/layout/validate/layoutConstraints.d.ts.map +1 -0
  143. package/dist/layout/validate/layoutConstraints.js +100 -0
  144. package/dist/layout/validate/layoutConstraints.js.map +1 -0
  145. package/dist/layout/validate/primitives.d.ts +31 -0
  146. package/dist/layout/validate/primitives.d.ts.map +1 -0
  147. package/dist/layout/validate/primitives.js +299 -0
  148. package/dist/layout/validate/primitives.js.map +1 -0
  149. package/dist/layout/validate/shared.d.ts +23 -0
  150. package/dist/layout/validate/shared.d.ts.map +1 -0
  151. package/dist/layout/validate/shared.js +32 -0
  152. package/dist/layout/validate/shared.js.map +1 -0
  153. package/dist/layout/validate/spacing.d.ts +21 -0
  154. package/dist/layout/validate/spacing.d.ts.map +1 -0
  155. package/dist/layout/validate/spacing.js +33 -0
  156. package/dist/layout/validate/spacing.js.map +1 -0
  157. package/dist/layout/validateProps.d.ts +5 -159
  158. package/dist/layout/validateProps.d.ts.map +1 -1
  159. package/dist/layout/validateProps.js +1 -832
  160. package/dist/layout/validateProps.js.map +1 -1
  161. package/dist/pipeline.js +1 -1
  162. package/dist/pipeline.js.map +1 -1
  163. package/dist/renderer/renderToDrawlist/renderTree.d.ts +1 -1
  164. package/dist/renderer/renderToDrawlist/renderTree.d.ts.map +1 -1
  165. package/dist/renderer/renderToDrawlist/renderTree.js +3 -3
  166. package/dist/renderer/renderToDrawlist/renderTree.js.map +1 -1
  167. package/dist/renderer/renderToDrawlist/types.d.ts +2 -0
  168. package/dist/renderer/renderToDrawlist/types.d.ts.map +1 -1
  169. package/dist/renderer/renderToDrawlist/widgets/containers.d.ts.map +1 -1
  170. package/dist/renderer/renderToDrawlist/widgets/containers.js +1 -1
  171. package/dist/renderer/renderToDrawlist/widgets/containers.js.map +1 -1
  172. package/dist/renderer/renderToDrawlist/widgets/files.d.ts +2 -1
  173. package/dist/renderer/renderToDrawlist/widgets/files.d.ts.map +1 -1
  174. package/dist/renderer/renderToDrawlist/widgets/files.js +30 -3
  175. package/dist/renderer/renderToDrawlist/widgets/files.js.map +1 -1
  176. package/dist/renderer/renderToDrawlist/widgets/overlays.d.ts +1 -1
  177. package/dist/renderer/renderToDrawlist/widgets/overlays.d.ts.map +1 -1
  178. package/dist/renderer/renderToDrawlist/widgets/overlays.js +26 -6
  179. package/dist/renderer/renderToDrawlist/widgets/overlays.js.map +1 -1
  180. package/dist/renderer/renderToDrawlist/widgets/renderFormWidgets.d.ts.map +1 -1
  181. package/dist/renderer/renderToDrawlist/widgets/renderFormWidgets.js +52 -18
  182. package/dist/renderer/renderToDrawlist/widgets/renderFormWidgets.js.map +1 -1
  183. package/dist/renderer/renderToDrawlist.d.ts +0 -8
  184. package/dist/renderer/renderToDrawlist.d.ts.map +1 -1
  185. package/dist/renderer/renderToDrawlist.js +1 -9
  186. package/dist/renderer/renderToDrawlist.js.map +1 -1
  187. package/dist/runtime/commit/composite.d.ts +11 -0
  188. package/dist/runtime/commit/composite.d.ts.map +1 -0
  189. package/dist/runtime/commit/composite.js +238 -0
  190. package/dist/runtime/commit/composite.js.map +1 -0
  191. package/dist/runtime/commit/container.d.ts +7 -0
  192. package/dist/runtime/commit/container.d.ts.map +1 -0
  193. package/dist/runtime/commit/container.js +350 -0
  194. package/dist/runtime/commit/container.js.map +1 -0
  195. package/dist/runtime/commit/equality.d.ts +20 -0
  196. package/dist/runtime/commit/equality.d.ts.map +1 -0
  197. package/dist/runtime/commit/equality.js +436 -0
  198. package/dist/runtime/commit/equality.js.map +1 -0
  199. package/dist/runtime/commit/errorBoundary.d.ts +7 -0
  200. package/dist/runtime/commit/errorBoundary.d.ts.map +1 -0
  201. package/dist/runtime/commit/errorBoundary.js +53 -0
  202. package/dist/runtime/commit/errorBoundary.js.map +1 -0
  203. package/dist/runtime/commit/shared.d.ts +138 -0
  204. package/dist/runtime/commit/shared.d.ts.map +1 -0
  205. package/dist/runtime/commit/shared.js +11 -0
  206. package/dist/runtime/commit/shared.js.map +1 -0
  207. package/dist/runtime/commit/transitions.d.ts +9 -0
  208. package/dist/runtime/commit/transitions.d.ts.map +1 -0
  209. package/dist/runtime/commit/transitions.js +93 -0
  210. package/dist/runtime/commit/transitions.js.map +1 -0
  211. package/dist/runtime/commit/validation.d.ts +16 -0
  212. package/dist/runtime/commit/validation.d.ts.map +1 -0
  213. package/dist/runtime/commit/validation.js +157 -0
  214. package/dist/runtime/commit/validation.js.map +1 -0
  215. package/dist/runtime/commit.d.ts +7 -117
  216. package/dist/runtime/commit.d.ts.map +1 -1
  217. package/dist/runtime/commit.js +13 -1394
  218. package/dist/runtime/commit.js.map +1 -1
  219. package/dist/runtime/localState.d.ts +4 -0
  220. package/dist/runtime/localState.d.ts.map +1 -1
  221. package/dist/runtime/localState.js.map +1 -1
  222. package/dist/runtime/widgetMeta/collector.d.ts +77 -0
  223. package/dist/runtime/widgetMeta/collector.d.ts.map +1 -0
  224. package/dist/runtime/widgetMeta/collector.js +293 -0
  225. package/dist/runtime/widgetMeta/collector.js.map +1 -0
  226. package/dist/runtime/widgetMeta/focusContainers.d.ts +44 -0
  227. package/dist/runtime/widgetMeta/focusContainers.d.ts.map +1 -0
  228. package/dist/runtime/widgetMeta/focusContainers.js +190 -0
  229. package/dist/runtime/widgetMeta/focusContainers.js.map +1 -0
  230. package/dist/runtime/widgetMeta/focusInfo.d.ts +19 -0
  231. package/dist/runtime/widgetMeta/focusInfo.d.ts.map +1 -0
  232. package/dist/runtime/widgetMeta/focusInfo.js +172 -0
  233. package/dist/runtime/widgetMeta/focusInfo.js.map +1 -0
  234. package/dist/runtime/widgetMeta/helpers.d.ts +47 -0
  235. package/dist/runtime/widgetMeta/helpers.d.ts.map +1 -0
  236. package/dist/runtime/widgetMeta/helpers.js +182 -0
  237. package/dist/runtime/widgetMeta/helpers.js.map +1 -0
  238. package/dist/runtime/widgetMeta.d.ts +12 -175
  239. package/dist/runtime/widgetMeta.d.ts.map +1 -1
  240. package/dist/runtime/widgetMeta.js +6 -847
  241. package/dist/runtime/widgetMeta.js.map +1 -1
  242. package/dist/ui/capabilities.d.ts.map +1 -1
  243. package/dist/ui/designTokens.d.ts.map +1 -1
  244. package/dist/widgets/accordion.d.ts.map +1 -1
  245. package/dist/widgets/accordion.js +8 -13
  246. package/dist/widgets/accordion.js.map +1 -1
  247. package/dist/widgets/factories/advanced.d.ts +20 -0
  248. package/dist/widgets/factories/advanced.d.ts.map +1 -0
  249. package/dist/widgets/factories/advanced.js +75 -0
  250. package/dist/widgets/factories/advanced.js.map +1 -0
  251. package/dist/widgets/factories/basic.d.ts +14 -0
  252. package/dist/widgets/factories/basic.d.ts.map +1 -0
  253. package/dist/widgets/factories/basic.js +44 -0
  254. package/dist/widgets/factories/basic.js.map +1 -0
  255. package/dist/widgets/factories/feedback.d.ts +20 -0
  256. package/dist/widgets/factories/feedback.d.ts.map +1 -0
  257. package/dist/widgets/factories/feedback.js +102 -0
  258. package/dist/widgets/factories/feedback.js.map +1 -0
  259. package/dist/widgets/factories/helpers.d.ts +41 -0
  260. package/dist/widgets/factories/helpers.d.ts.map +1 -0
  261. package/dist/widgets/factories/helpers.js +72 -0
  262. package/dist/widgets/factories/helpers.js.map +1 -0
  263. package/dist/widgets/factories/interactive.d.ts +15 -0
  264. package/dist/widgets/factories/interactive.d.ts.map +1 -0
  265. package/dist/widgets/factories/interactive.js +46 -0
  266. package/dist/widgets/factories/interactive.js.map +1 -0
  267. package/dist/widgets/factories/layoutShell.d.ts +22 -0
  268. package/dist/widgets/factories/layoutShell.d.ts.map +1 -0
  269. package/dist/widgets/factories/layoutShell.js +190 -0
  270. package/dist/widgets/factories/layoutShell.js.map +1 -0
  271. package/dist/widgets/factories/media.d.ts +14 -0
  272. package/dist/widgets/factories/media.d.ts.map +1 -0
  273. package/dist/widgets/factories/media.js +25 -0
  274. package/dist/widgets/factories/media.js.map +1 -0
  275. package/dist/widgets/factories/navigation.d.ts +10 -0
  276. package/dist/widgets/factories/navigation.d.ts.map +1 -0
  277. package/dist/widgets/factories/navigation.js +24 -0
  278. package/dist/widgets/factories/navigation.js.map +1 -0
  279. package/dist/widgets/field.d.ts +6 -1
  280. package/dist/widgets/field.d.ts.map +1 -1
  281. package/dist/widgets/field.js +8 -2
  282. package/dist/widgets/field.js.map +1 -1
  283. package/dist/widgets/filePicker.d.ts +5 -0
  284. package/dist/widgets/filePicker.d.ts.map +1 -0
  285. package/dist/widgets/filePicker.js +136 -0
  286. package/dist/widgets/filePicker.js.map +1 -0
  287. package/dist/widgets/protocol.d.ts +0 -6
  288. package/dist/widgets/protocol.d.ts.map +1 -1
  289. package/dist/widgets/protocol.js +0 -6
  290. package/dist/widgets/protocol.js.map +1 -1
  291. package/dist/widgets/select.js +1 -1
  292. package/dist/widgets/select.js.map +1 -1
  293. package/dist/widgets/splitPane.d.ts.map +1 -1
  294. package/dist/widgets/splitPane.js.map +1 -1
  295. package/dist/widgets/table.d.ts.map +1 -1
  296. package/dist/widgets/table.js +43 -1
  297. package/dist/widgets/table.js.map +1 -1
  298. package/dist/widgets/tree.d.ts.map +1 -1
  299. package/dist/widgets/types/advanced.d.ts +611 -0
  300. package/dist/widgets/types/advanced.d.ts.map +1 -0
  301. package/dist/widgets/types/advanced.js +2 -0
  302. package/dist/widgets/types/advanced.js.map +1 -0
  303. package/dist/widgets/types/base.d.ts +933 -0
  304. package/dist/widgets/types/base.d.ts.map +1 -0
  305. package/dist/widgets/types/base.js +2 -0
  306. package/dist/widgets/types/base.js.map +1 -0
  307. package/dist/widgets/types/forms.d.ts +136 -0
  308. package/dist/widgets/types/forms.d.ts.map +1 -0
  309. package/dist/widgets/types/forms.js +2 -0
  310. package/dist/widgets/types/forms.js.map +1 -0
  311. package/dist/widgets/types/navigation.d.ts +83 -0
  312. package/dist/widgets/types/navigation.d.ts.map +1 -0
  313. package/dist/widgets/types/navigation.js +2 -0
  314. package/dist/widgets/types/navigation.js.map +1 -0
  315. package/dist/widgets/types/overlaysShell.d.ts +223 -0
  316. package/dist/widgets/types/overlaysShell.d.ts.map +1 -0
  317. package/dist/widgets/types/overlaysShell.js +2 -0
  318. package/dist/widgets/types/overlaysShell.js.map +1 -0
  319. package/dist/widgets/types/table.d.ts +104 -0
  320. package/dist/widgets/types/table.d.ts.map +1 -0
  321. package/dist/widgets/types/table.js +2 -0
  322. package/dist/widgets/types/table.js.map +1 -0
  323. package/dist/widgets/types/tree.d.ts +64 -0
  324. package/dist/widgets/types/tree.d.ts.map +1 -0
  325. package/dist/widgets/types/tree.js +2 -0
  326. package/dist/widgets/types/tree.js.map +1 -0
  327. package/dist/widgets/types.d.ts +14 -2123
  328. package/dist/widgets/types.d.ts.map +1 -1
  329. package/dist/widgets/ui.d.ts +37 -843
  330. package/dist/widgets/ui.d.ts.map +1 -1
  331. package/dist/widgets/ui.js +37 -1262
  332. package/dist/widgets/ui.js.map +1 -1
  333. package/package.json +2 -2
  334. package/dist/constraints/aggregation.d.ts +0 -17
  335. package/dist/constraints/aggregation.d.ts.map +0 -1
  336. package/dist/constraints/aggregation.js +0 -59
  337. package/dist/constraints/aggregation.js.map +0 -1
  338. package/dist/renderer/renderToDrawlist/overflowCulling.d.ts +0 -3
  339. package/dist/renderer/renderToDrawlist/overflowCulling.d.ts.map +0 -1
  340. package/dist/renderer/renderToDrawlist/overflowCulling.js +0 -81
  341. package/dist/renderer/renderToDrawlist/overflowCulling.js.map +0 -1
  342. package/dist/widgets/tests/protocol.test.d.ts +0 -2
  343. package/dist/widgets/tests/protocol.test.d.ts.map +0 -1
  344. package/dist/widgets/tests/protocol.test.js +0 -120
  345. package/dist/widgets/tests/protocol.test.js.map +0 -1
@@ -1,728 +1,13 @@
1
1
  /**
2
- * packages/core/src/widgets/ui.ts — Widget factory functions.
3
- *
4
- * Why: Provides a convenient API for building VNode trees without manually
5
- * constructing discriminated union objects. Each function returns a properly
6
- * typed VNode for the corresponding widget.
7
- *
8
- * @see docs/widgets/index.md
9
- */
10
- import { routerBreadcrumb as buildRouterBreadcrumb, routerTabs as buildRouterTabs, } from "../router/helpers.js";
11
- import { createAccordionWidgetVNode } from "./accordion.js";
12
- import { createBreadcrumbWidgetVNode } from "./breadcrumb.js";
13
- import { createPaginationWidgetVNode } from "./pagination.js";
14
- import { createTabsWidgetVNode } from "./tabs.js";
15
- function isUiChildren(value) {
16
- return Array.isArray(value);
17
- }
18
- function filterChildren(children) {
19
- const out = [];
20
- for (const child of children) {
21
- if (child === false || child === null || child === undefined)
22
- continue;
23
- if (isUiChildren(child)) {
24
- out.push(...filterChildren(child));
25
- continue;
26
- }
27
- out.push(child);
28
- }
29
- return out;
30
- }
31
- function maybeReverseChildren(children, reverse) {
32
- if (reverse !== true || children.length <= 1)
33
- return children;
34
- return Object.freeze([...children].reverse());
35
- }
36
- function isTextProps(v) {
37
- return (typeof v === "object" &&
38
- v !== null &&
39
- ("style" in v ||
40
- "id" in v ||
41
- "key" in v ||
42
- "variant" in v ||
43
- "textOverflow" in v ||
44
- "maxWidth" in v ||
45
- "wrap" in v));
46
- }
47
- function resolveButtonIntent(props) {
48
- if (props.intent === undefined || props.dsVariant !== undefined)
49
- return props;
50
- switch (props.intent) {
51
- case "primary":
52
- return { ...props, dsVariant: "solid", dsTone: props.dsTone ?? "primary" };
53
- case "secondary":
54
- return { ...props, dsVariant: "soft", dsTone: props.dsTone ?? "default" };
55
- case "danger":
56
- return { ...props, dsVariant: "outline", dsTone: props.dsTone ?? "danger" };
57
- case "success":
58
- return { ...props, dsVariant: "soft", dsTone: props.dsTone ?? "success" };
59
- case "warning":
60
- return { ...props, dsVariant: "soft", dsTone: props.dsTone ?? "warning" };
61
- case "link":
62
- return {
63
- ...props,
64
- dsVariant: "ghost",
65
- dsTone: props.dsTone ?? "default",
66
- dsSize: props.dsSize ?? "sm",
67
- };
68
- }
69
- }
70
- function resolveBoxPreset(props) {
71
- const { preset, ...rest } = props;
72
- if (preset === undefined)
73
- return props;
74
- switch (preset) {
75
- case "card":
76
- return { preset, border: "rounded", p: 1, ...rest };
77
- case "surface":
78
- return { preset, border: "none", p: 1, ...rest };
79
- case "well":
80
- return { preset, border: "single", p: 1, ...rest };
81
- case "elevated":
82
- return { preset, border: "single", p: 1, shadow: { density: "light" }, ...rest };
83
- }
84
- }
85
- const EMPTY_TEXT_PROPS = Object.freeze({});
86
- function text(content, styleOrProps) {
87
- if (styleOrProps === undefined)
88
- return { kind: "text", text: content, props: EMPTY_TEXT_PROPS };
89
- if (isTextProps(styleOrProps))
90
- return { kind: "text", text: content, props: styleOrProps };
91
- return { kind: "text", text: content, props: { style: styleOrProps } };
92
- }
93
- function box(props = {}, children = []) {
94
- return { kind: "box", props: resolveBoxPreset(props), children: filterChildren(children) };
95
- }
96
- function row(props = {}, children = []) {
97
- const resolved = props.gap === undefined ? { gap: DEFAULT_STACK_GAP, ...props } : props;
98
- const filtered = filterChildren(children);
99
- return {
100
- kind: "row",
101
- props: resolved,
102
- children: maybeReverseChildren(filtered, resolved.reverse),
103
- };
104
- }
105
- function column(props = {}, children = []) {
106
- const resolved = props.gap === undefined ? { gap: DEFAULT_STACK_GAP, ...props } : props;
107
- const filtered = filterChildren(children);
108
- return {
109
- kind: "column",
110
- props: resolved,
111
- children: maybeReverseChildren(filtered, resolved.reverse),
112
- };
113
- }
114
- function themed(themeOverride, children = []) {
115
- return { kind: "themed", props: { theme: themeOverride }, children: filterChildren(children) };
116
- }
117
- function grid(props, ...children) {
118
- return { kind: "grid", props, children: filterChildren(children) };
119
- }
120
- const DEFAULT_STACK_GAP = 1;
121
- function spacer(props = {}) {
122
- return { kind: "spacer", props };
123
- }
124
- function divider(props = {}) {
125
- return { kind: "divider", props };
126
- }
127
- /**
128
- * Create an icon widget.
129
- *
130
- * @param iconPath - Icon path (e.g., "status.check", "arrow.right")
131
- * @param props - Optional icon props
132
- *
133
- * @example
134
- * ```ts
135
- * ui.icon("status.check")
136
- * ui.icon("arrow.right", { style: { fg: rgb(0, 255, 0) } })
137
- * ui.icon("ui.search", { fallback: true })
138
- * ```
139
- */
140
- function icon(iconPath, props = {}) {
141
- return { kind: "icon", props: { icon: iconPath, ...props } };
142
- }
143
- /**
144
- * Create a spinner widget (animated loading indicator).
145
- *
146
- * @param props - Spinner props
147
- *
148
- * @example
149
- * ```ts
150
- * ui.spinner()
151
- * ui.spinner({ variant: "dots", label: "Loading..." })
152
- * ```
153
- */
154
- function spinner(props = {}) {
155
- return { kind: "spinner", props };
156
- }
157
- /**
158
- * Create a progress bar widget.
159
- *
160
- * @param value - Progress value from 0 to 1
161
- * @param props - Optional progress bar props
162
- *
163
- * @example
164
- * ```ts
165
- * ui.progress(0.75)
166
- * ui.progress(0.5, { variant: "blocks", showPercent: true })
167
- * ui.progress(0.3, { label: "Downloading:", width: 20 })
168
- * ```
169
- */
170
- function progress(value, props = {}) {
171
- return { kind: "progress", props: { value, ...props } };
172
- }
173
- /**
174
- * Create a skeleton loading placeholder.
175
- *
176
- * @param width - Width in cells
177
- * @param props - Optional skeleton props
178
- *
179
- * @example
180
- * ```ts
181
- * ui.skeleton(20)
182
- * ui.skeleton(10, { height: 3, variant: "rect" })
183
- * ```
184
- */
185
- function skeleton(width, props = {}) {
186
- return { kind: "skeleton", props: { width, ...props } };
187
- }
188
- /**
189
- * Create a rich text widget with multiple styled spans.
190
- *
191
- * @param spans - Array of text spans with optional styles
192
- *
193
- * @example
194
- * ```ts
195
- * ui.richText([
196
- * { text: "Error: ", style: { fg: rgb(255, 0, 0), bold: true } },
197
- * { text: "File not found" },
198
- * ])
199
- * ```
200
- */
201
- function richText(spans, props = {}) {
202
- return { kind: "richText", props: { spans, ...props } };
203
- }
204
- /**
205
- * Create a keyboard shortcut display widget.
206
- *
207
- * @param keys - Key or keys to display
208
- * @param props - Optional kbd props
209
- *
210
- * @example
211
- * ```ts
212
- * ui.kbd("Ctrl+S")
213
- * ui.kbd(["Ctrl", "Shift", "P"])
214
- * ui.kbd("Cmd+K", { separator: " " })
215
- * ```
216
- */
217
- function kbd(keys, props = {}) {
218
- return { kind: "kbd", props: { keys, ...props } };
219
- }
220
- function keybindingSequenceToKbdInput(sequence) {
221
- const normalized = sequence.trim();
222
- if (normalized.length === 0)
223
- return "";
224
- const parts = normalized.split(/\s+/);
225
- if (parts.length <= 1)
226
- return normalized;
227
- return Object.freeze(parts);
228
- }
229
- function keybindingComparator(a, b) {
230
- const byMode = a.mode.localeCompare(b.mode);
231
- if (byMode !== 0)
232
- return byMode;
233
- return a.sequence.localeCompare(b.sequence);
234
- }
235
- /**
236
- * Render keybindings as a formatted help table.
237
- *
238
- * Accepts output from `app.getBindings()` directly.
239
- */
240
- function keybindingHelp(bindings, options = {}) {
241
- const title = options.title ?? "Keyboard Shortcuts";
242
- const emptyText = options.emptyText ?? "No shortcuts registered.";
243
- const showMode = options.showMode ??
244
- (() => {
245
- const firstMode = bindings[0]?.mode;
246
- if (firstMode === undefined)
247
- return false;
248
- return bindings.some((binding) => binding.mode !== firstMode);
249
- })();
250
- const rows = options.sort === false ? [...bindings] : [...bindings].sort(keybindingComparator);
251
- return column({
252
- gap: 1,
253
- ...(options.key === undefined ? {} : { key: options.key }),
254
- }, [
255
- text(title, { style: { bold: true } }),
256
- divider({ char: "·" }),
257
- rows.length > 0
258
- ? column({ gap: 0 }, rows.map((binding, i) => {
259
- const keyTokens = keybindingSequenceToKbdInput(binding.sequence);
260
- const sequenceNode = Array.isArray(keyTokens)
261
- ? kbd(keyTokens, { separator: " " })
262
- : kbd(keyTokens);
263
- const descriptionNode = binding.description === undefined
264
- ? text("No description", { dim: true })
265
- : text(binding.description);
266
- return row({
267
- key: `keybinding-help-${binding.mode}-${binding.sequence}-${String(i)}`,
268
- gap: 1,
269
- items: "center",
270
- wrap: true,
271
- }, [
272
- sequenceNode,
273
- showMode ? text(`[${binding.mode}]`, { dim: true }) : null,
274
- descriptionNode,
275
- ]);
276
- }))
277
- : text(emptyText, { dim: true }),
278
- ]);
279
- }
280
- /**
281
- * Create a badge widget.
282
- *
283
- * @param text - Badge text
284
- * @param props - Optional badge props
285
- *
286
- * @example
287
- * ```ts
288
- * ui.badge("New")
289
- * ui.badge("Error", { variant: "error" })
290
- * ui.badge("3", { variant: "info" })
291
- * ```
292
- */
293
- function badge(text, props = {}) {
294
- return { kind: "badge", props: { text, ...props } };
295
- }
296
- /**
297
- * Create a status indicator widget.
298
- *
299
- * @param status - Status type (online, offline, away, busy, unknown)
300
- * @param props - Optional status props
301
- *
302
- * @example
303
- * ```ts
304
- * ui.status("online")
305
- * ui.status("busy", { label: "In a meeting" })
306
- * ui.status("away", { showLabel: true })
307
- * ```
308
- */
309
- function status(status, props = {}) {
310
- return { kind: "status", props: { status, ...props } };
311
- }
312
- /**
313
- * Create a tag widget.
314
- *
315
- * @param text - Tag text
316
- * @param props - Optional tag props
317
- *
318
- * @example
319
- * ```ts
320
- * ui.tag("TypeScript")
321
- * ui.tag("Bug", { variant: "error" })
322
- * ui.tag("Feature", { variant: "info", removable: true })
323
- * ```
324
- */
325
- function tag(text, props = {}) {
326
- return { kind: "tag", props: { text, ...props } };
327
- }
328
- /**
329
- * Create a gauge widget.
330
- *
331
- * @param value - Value from 0 to 1
332
- * @param props - Optional gauge props
333
- *
334
- * @example
335
- * ```ts
336
- * ui.gauge(0.75)
337
- * ui.gauge(0.42, { label: "CPU" })
338
- * ui.gauge(0.9, {
339
- * label: "Memory",
340
- * thresholds: [
341
- * { value: 0.8, variant: "warning" },
342
- * { value: 0.95, variant: "error" }
343
- * ]
344
- * })
345
- * ```
346
- */
347
- function gauge(value, props = {}) {
348
- return { kind: "gauge", props: { value, ...props } };
349
- }
350
- /**
351
- * Create an empty state widget.
352
- *
353
- * @param title - Main title text
354
- * @param props - Optional empty state props
355
- *
356
- * @example
357
- * ```ts
358
- * ui.empty("No results")
359
- * ui.empty("No messages", {
360
- * icon: "ui.mail",
361
- * description: "Messages will appear here",
362
- * action: ui.button({ id: "compose", label: "Compose" })
363
- * })
364
- * ```
365
- */
366
- function empty(title, props = {}) {
367
- return { kind: "empty", props: { title, ...props } };
368
- }
369
- /**
370
- * Create an error display widget.
371
- *
372
- * @param message - Error message
373
- * @param props - Optional error display props
374
- *
375
- * @example
376
- * ```ts
377
- * ui.errorDisplay("Failed to load data")
378
- * ui.errorDisplay("Connection failed", {
379
- * title: "Network Error",
380
- * onRetry: () => refetch()
381
- * })
382
- * ui.errorDisplay("Unexpected error", {
383
- * stack: error.stack,
384
- * showStack: true
385
- * })
386
- * ```
387
- */
388
- function errorDisplay(message, props = {}) {
389
- return { kind: "errorDisplay", props: { message, ...props } };
390
- }
391
- /**
392
- * Create an error boundary widget.
393
- *
394
- * @param props - Boundary config with protected children and fallback renderer
395
- *
396
- * @example
397
- * ```ts
398
- * ui.errorBoundary({
399
- * children: RiskyWidget(),
400
- * fallback: (error) =>
401
- * ui.column({}, [
402
- * ui.errorDisplay(error.message, { title: error.code }),
403
- * ui.button({ id: "retry", label: "Retry", onPress: error.retry }),
404
- * ]),
405
- * })
406
- * ```
407
- */
408
- function errorBoundary(props) {
409
- return { kind: "errorBoundary", props };
410
- }
411
- /**
412
- * Create a callout/alert widget.
413
- *
414
- * @param message - Callout message
415
- * @param props - Optional callout props
416
- *
417
- * @example
418
- * ```ts
419
- * ui.callout("This action cannot be undone", { variant: "warning" })
420
- * ui.callout("Changes saved successfully", { variant: "success" })
421
- * ui.callout("New feature available", {
422
- * variant: "info",
423
- * title: "What's New"
424
- * })
425
- * ```
426
- */
427
- function callout(message, props = {}) {
428
- return { kind: "callout", props: { message, ...props } };
429
- }
430
- function link(props) {
431
- return { kind: "link", props };
432
- }
433
- function canvas(props) {
434
- return { kind: "canvas", props };
435
- }
436
- function image(props) {
437
- return { kind: "image", props };
438
- }
439
- function lineChart(props) {
440
- return { kind: "lineChart", props };
441
- }
442
- function scatter(props) {
443
- return { kind: "scatter", props };
444
- }
445
- function heatmap(props) {
446
- return { kind: "heatmap", props };
447
- }
448
- /**
449
- * Create a sparkline widget (mini inline chart using block characters).
450
- *
451
- * @param data - Array of numeric data points
452
- * @param props - Optional sparkline props
453
- *
454
- * @example
455
- * ```ts
456
- * ui.sparkline([10, 20, 15, 30, 25])
457
- * ui.sparkline(cpuHistory, { width: 10 })
458
- * ui.sparkline(prices, { min: 0, max: 100 })
459
- * ```
460
- */
461
- function sparkline(data, props = {}) {
462
- return { kind: "sparkline", props: { data, ...props } };
463
- }
464
- /**
465
- * Create a bar chart widget.
466
- *
467
- * @param data - Array of bar chart items
468
- * @param props - Optional bar chart props
469
- *
470
- * @example
471
- * ```ts
472
- * ui.barChart([
473
- * { label: "TypeScript", value: 60 },
474
- * { label: "JavaScript", value: 30 },
475
- * { label: "Python", value: 10 },
476
- * ])
477
- * ui.barChart(stats, { orientation: "vertical", showValues: true })
478
- * ```
479
- */
480
- function barChart(data, props = {}) {
481
- return { kind: "barChart", props: { data, ...props } };
482
- }
483
- /**
484
- * Create a mini chart widget for compact multi-value display.
485
- *
486
- * @param values - Array of labeled values
487
- * @param props - Optional mini chart props
488
- *
489
- * @example
490
- * ```ts
491
- * ui.miniChart([
492
- * { label: "CPU", value: 42, max: 100 },
493
- * { label: "MEM", value: 78, max: 100 },
494
- * ])
495
- * ui.miniChart(metrics, { variant: "pills" })
496
- * ```
497
- */
498
- function miniChart(values, props = {}) {
499
- return { kind: "miniChart", props: { values, ...props } };
500
- }
501
- function button(props) {
502
- return { kind: "button", props: resolveButtonIntent(props) };
503
- }
504
- function input(props) {
505
- return { kind: "input", props };
506
- }
507
- function textarea(props) {
508
- return {
509
- kind: "input",
510
- props: {
511
- ...props,
512
- multiline: true,
513
- rows: props.rows ?? 3,
514
- wordWrap: props.wordWrap ?? true,
515
- },
516
- };
517
- }
518
- function focusAnnouncer(props = {}) {
519
- return { kind: "focusAnnouncer", props };
520
- }
521
- function focusZone(props, children = []) {
522
- return { kind: "focusZone", props, children: filterChildren(children) };
523
- }
524
- function focusTrap(props, children = []) {
525
- return { kind: "focusTrap", props, children: filterChildren(children) };
526
- }
527
- function virtualList(props) {
528
- return { kind: "virtualList", props: props };
529
- }
530
- function layers(propsOrChildren, children = []) {
531
- if (isUiChildren(propsOrChildren)) {
532
- return { kind: "layers", props: {}, children: filterChildren(propsOrChildren) };
533
- }
534
- return { kind: "layers", props: propsOrChildren, children: filterChildren(children) };
535
- }
536
- function panel(titleOrOptions, children = []) {
537
- const options = typeof titleOrOptions === "string" ? { title: titleOrOptions } : titleOrOptions;
538
- const resolvedChildren = filterChildren(children);
539
- const inner = resolvedChildren.length <= 1
540
- ? resolvedChildren
541
- : [column({ gap: options.gap ?? 1 }, resolvedChildren)];
542
- return box({
543
- ...(options.id === undefined ? {} : { id: options.id }),
544
- ...(options.key === undefined ? {} : { key: options.key }),
545
- preset: "card",
546
- ...(options.title === undefined ? {} : { title: options.title }),
547
- border: options.variant ?? "rounded",
548
- p: options.p ?? 1,
549
- ...(options.style === undefined ? {} : { style: options.style }),
550
- }, inner);
551
- }
552
- function form(optionsOrChildren, children = []) {
553
- if (isUiChildren(optionsOrChildren)) {
554
- return column({ gap: 1 }, optionsOrChildren);
555
- }
556
- const options = optionsOrChildren;
557
- return column({
558
- ...(options.id === undefined ? {} : { id: options.id }),
559
- ...(options.key === undefined ? {} : { key: options.key }),
560
- gap: options.gap ?? 1,
561
- }, children);
562
- }
563
- function actions(optionsOrChildren, children = []) {
564
- if (isUiChildren(optionsOrChildren)) {
565
- return row({ justify: "end", gap: 1 }, optionsOrChildren);
566
- }
567
- const options = optionsOrChildren;
568
- return row({
569
- ...(options.id === undefined ? {} : { id: options.id }),
570
- ...(options.key === undefined ? {} : { key: options.key }),
571
- justify: "end",
572
- gap: options.gap ?? 1,
573
- }, children);
574
- }
575
- function center(child, options = {}) {
576
- return column({
577
- ...(options.id === undefined ? {} : { id: options.id }),
578
- ...(options.key === undefined ? {} : { key: options.key }),
579
- width: "full",
580
- height: "full",
581
- align: "center",
582
- justify: "center",
583
- ...(options.p === undefined ? {} : { p: options.p }),
584
- }, [child]);
585
- }
586
- function page(options) {
587
- const { id, key, header, body, footer, gap, p, width, height, ...layoutConstraints } = options;
588
- return column({
589
- ...(id === undefined ? {} : { id }),
590
- ...(key === undefined ? {} : { key }),
591
- width: width ?? "full",
592
- height: height ?? "full",
593
- ...layoutConstraints,
594
- gap: gap ?? 1,
595
- ...(p === undefined ? {} : { p }),
596
- }, [header ?? null, box({ border: "none", flex: 1 }, [body]), footer ?? null]);
597
- }
598
- function appShell(options) {
599
- const { id, key, header, sidebar, body, footer, gap, p, ...layoutConstraints } = options;
600
- const headerNode = header ? box({ border: "rounded", px: 1, py: 0 }, [header]) : null;
601
- const bodyNode = sidebar
602
- ? row({ gap: 1, items: "stretch" }, [
603
- box({ border: "rounded", width: sidebar.width ?? 25, p: 1 }, [sidebar.content]),
604
- box({ flex: 1 }, [body]),
605
- ])
606
- : body;
607
- const footerNode = footer ? row({ gap: 1, items: "center", wrap: true }, [footer]) : null;
608
- return page({
609
- ...(id === undefined ? {} : { id }),
610
- ...(key === undefined ? {} : { key }),
611
- header: headerNode,
612
- body: bodyNode,
613
- footer: footerNode,
614
- gap: gap ?? 1,
615
- p: p ?? 1,
616
- ...layoutConstraints,
617
- });
618
- }
619
- function card(optionsOrTitle, children = []) {
620
- const options = typeof optionsOrTitle === "string" ? { title: optionsOrTitle } : optionsOrTitle;
621
- const bodyChildren = filterChildren(children);
622
- const headerActions = options.actions ?? [];
623
- const cardChildren = [];
624
- if (options.title !== undefined || headerActions.length > 0) {
625
- cardChildren.push(row({ gap: 1, items: "center", wrap: true }, [
626
- ...(options.title === undefined ? [] : [text(options.title, { variant: "heading" })]),
627
- ...(headerActions.length === 0 ? [] : [spacer({ flex: 1 }), ...headerActions]),
628
- ]));
629
- }
630
- if (options.subtitle !== undefined) {
631
- cardChildren.push(text(options.subtitle, { dim: true }));
632
- }
633
- cardChildren.push(...bodyChildren);
634
- return box({
635
- ...(options.id === undefined ? {} : { id: options.id }),
636
- ...(options.key === undefined ? {} : { key: options.key }),
637
- preset: "card",
638
- border: options.border ?? "rounded",
639
- p: options.p ?? 1,
640
- ...(options.style === undefined ? {} : { style: options.style }),
641
- }, [column({ gap: options.gap ?? 1 }, cardChildren)]);
642
- }
643
- function toolbar(optionsOrChildren, children = []) {
644
- if (isUiChildren(optionsOrChildren)) {
645
- return row({ gap: 1, items: "center", wrap: true }, optionsOrChildren);
646
- }
647
- const options = optionsOrChildren;
648
- return row({
649
- ...(options.id === undefined ? {} : { id: options.id }),
650
- ...(options.key === undefined ? {} : { key: options.key }),
651
- gap: options.gap ?? 1,
652
- items: "center",
653
- wrap: true,
654
- }, children);
655
- }
656
- function statusBar(options) {
657
- return row({
658
- ...(options.id === undefined ? {} : { id: options.id }),
659
- ...(options.key === undefined ? {} : { key: options.key }),
660
- width: "full",
661
- items: "center",
662
- ...(options.style === undefined ? {} : { style: options.style }),
663
- }, [...(options.left ?? []), spacer({ flex: 1 }), ...(options.right ?? [])]);
664
- }
665
- function header(options) {
666
- return box({
667
- ...(options.id === undefined ? {} : { id: options.id }),
668
- ...(options.key === undefined ? {} : { key: options.key }),
669
- border: "rounded",
670
- px: 1,
671
- py: 0,
672
- }, [
673
- row({ gap: 1, items: "center", wrap: true }, [
674
- text(options.title, { variant: "heading" }),
675
- options.subtitle ? text(options.subtitle, { dim: true }) : null,
676
- spacer({ flex: 1 }),
677
- ...(options.actions ?? []),
678
- ]),
679
- ]);
680
- }
681
- function sidebar(options) {
682
- const buttonNodes = options.items.map((item) => button({
683
- id: `${options.id ?? "sidebar"}-${item.id}`,
684
- label: item.icon ? `${item.icon} ${item.label}` : item.label,
685
- onPress: () => {
686
- options.onSelect?.(item.id);
687
- },
688
- dsVariant: options.selected === item.id ? "soft" : "ghost",
689
- dsTone: options.selected === item.id ? "primary" : "default",
690
- }));
691
- return box({
692
- ...(options.id === undefined ? {} : { id: options.id }),
693
- ...(options.key === undefined ? {} : { key: options.key }),
694
- border: "rounded",
695
- width: options.width ?? 25,
696
- p: 1,
697
- }, [
698
- column({ gap: 1 }, [
699
- options.title ? text(options.title, { variant: "heading" }) : null,
700
- column({ gap: 0 }, buttonNodes),
701
- ]),
702
- ]);
703
- }
704
- function masterDetail(options) {
705
- return row({
706
- ...(options.id === undefined ? {} : { id: options.id }),
707
- ...(options.key === undefined ? {} : { key: options.key }),
708
- gap: options.gap ?? 1,
709
- items: "stretch",
710
- }, [
711
- box({ width: options.masterWidth ?? 30 }, [options.master]),
712
- box({ flex: 1 }, [options.detail]),
713
- ]);
714
- }
715
- /**
716
- * Widget factory functions for building VNode trees.
717
- *
718
- * @example
719
- * ```ts
720
- * ui.column({ p: 1 }, [
721
- * ui.text("Hello"),
722
- * ui.button({ id: "ok", label: "OK" }),
723
- * ])
724
- * ```
725
- */
2
+ * packages/core/src/widgets/ui.ts — Widget factory public facade.
3
+ */
4
+ import { codeEditor, commandPalette, dialog, diffViewer, dropdown, filePicker, fileTreeExplorer, layer, logsConsole, modal, panelGroup, resizablePanel, splitPane, table, toastContainer, toolApprovalDialog, tree, } from "./factories/advanced.js";
5
+ import { box, column, divider, grid, row, spacer, text, themed } from "./factories/basic.js";
6
+ import { badge, callout, empty, errorBoundary, errorDisplay, gauge, icon, kbd, keybindingHelp, link, progress, richText, skeleton, spinner, status, tag, } from "./factories/feedback.js";
7
+ import { button, checkbox, field, focusAnnouncer, focusTrap, focusZone, input, radioGroup, select, slider, textarea, virtualList, } from "./factories/interactive.js";
8
+ import { actions, appShell, card, center, form, header, layers, masterDetail, page, panel, sidebar, statusBar, toolbar, } from "./factories/layoutShell.js";
9
+ import { barChart, canvas, heatmap, image, lineChart, miniChart, scatter, sparkline, } from "./factories/media.js";
10
+ import { accordion, breadcrumb, pagination, routerBreadcrumb, routerTabs, tabs, } from "./factories/navigation.js";
726
11
  export const ui = {
727
12
  text,
728
13
  box,
@@ -776,543 +61,33 @@ export const ui = {
776
61
  header,
777
62
  sidebar,
778
63
  masterDetail,
779
- /**
780
- * Create a declarative dialog with arbitrary actions.
781
- * Sugar over `ui.modal(...)` for common confirmation/message flows.
782
- *
783
- * @example
784
- * ```ts
785
- * ui.dialog({
786
- * id: "save",
787
- * title: "Unsaved Changes",
788
- * message: "Save before closing?",
789
- * actions: [
790
- * { label: "Save", intent: "primary", onPress: save },
791
- * { label: "Don't Save", intent: "danger", onPress: discard },
792
- * { label: "Cancel", onPress: cancel },
793
- * ],
794
- * })
795
- * ```
796
- */
797
- dialog(props) {
798
- const { message, actions, onClose, ...modalProps } = props;
799
- return {
800
- kind: "modal",
801
- props: {
802
- ...modalProps,
803
- ...(onClose !== undefined ? { onClose } : {}),
804
- content: typeof message === "string" ? text(message) : message,
805
- actions: actions.map((action, index) => {
806
- const intentProps = action.intent === undefined ? {} : { intent: action.intent };
807
- return button({
808
- id: action.id ?? `${modalProps.id}-action-${String(index)}`,
809
- label: action.label,
810
- onPress: action.onPress,
811
- ...intentProps,
812
- ...(action.disabled === true ? { disabled: true } : {}),
813
- ...(action.focusable === false ? { focusable: false } : {}),
814
- });
815
- }),
816
- },
817
- };
818
- },
819
- /**
820
- * Create a modal overlay.
821
- * Renders centered with optional backdrop and focus trap.
822
- *
823
- * @example
824
- * ```ts
825
- * ui.modal({
826
- * id: "confirm",
827
- * title: "Confirm Action",
828
- * content: ui.text("Are you sure?"),
829
- * actions: [
830
- * ui.button({ id: "yes", label: "Yes" }),
831
- * ui.button({ id: "no", label: "No" }),
832
- * ],
833
- * onClose: () => app.update({ showModal: false }),
834
- * })
835
- * ```
836
- */
837
- modal(props) {
838
- return { kind: "modal", props };
839
- },
840
- /**
841
- * Create a dropdown menu positioned relative to an anchor.
842
- * Automatically flips when near screen edge.
843
- *
844
- * @example
845
- * ```ts
846
- * ui.dropdown({
847
- * id: "file-menu",
848
- * anchorId: "file-button",
849
- * position: "below-start",
850
- * items: [
851
- * { id: "new", label: "New", shortcut: "Ctrl+N" },
852
- * { id: "open", label: "Open", shortcut: "Ctrl+O" },
853
- * { id: "divider", label: "", divider: true },
854
- * { id: "exit", label: "Exit" },
855
- * ],
856
- * onSelect: (item) => handleAction(item.id),
857
- * onClose: () => app.update({ menuOpen: false }),
858
- * })
859
- * ```
860
- */
861
- dropdown(props) {
862
- return { kind: "dropdown", props };
863
- },
864
- /**
865
- * Create a generic layer in the layer stack.
866
- * Use for custom overlays that need z-order control.
867
- *
868
- * @example
869
- * ```ts
870
- * ui.layer({
871
- * id: "tooltip",
872
- * content: ui.text("Tooltip text"),
873
- * zIndex: 100,
874
- * })
875
- * ```
876
- */
877
- layer(props) {
878
- return { kind: "layer", props };
879
- },
880
- /**
881
- * Create a table widget for displaying tabular data.
882
- * Supports sorting, selection, and virtualization for large datasets.
883
- *
884
- * @example
885
- * ```ts
886
- * ui.table({
887
- * id: "files",
888
- * columns: [
889
- * { key: "name", header: "Name", flex: 1, sortable: true, overflow: "middle" },
890
- * { key: "size", header: "Size", width: 10, align: "right", overflow: "clip" },
891
- * { key: "actions", header: "", width: 8, render: (_, row) =>
892
- * ui.button({ id: `del-${row.id}`, label: "Del" }) },
893
- * ],
894
- * data: files,
895
- * getRowKey: (f) => f.id,
896
- * selection: state.selected,
897
- * selectionMode: "multi",
898
- * onSelectionChange: (keys) => app.update({ selected: keys }),
899
- * sortColumn: state.sortCol,
900
- * sortDirection: state.sortDir,
901
- * onSort: (col, dir) => app.update({ sortCol: col, sortDir: dir }),
902
- * stripeStyle: { odd: rgb(30, 33, 41) },
903
- * borderStyle: { variant: "double", color: rgb(130, 140, 150) },
904
- * })
905
- * ```
906
- */
907
- table(props) {
908
- return { kind: "table", props: props };
909
- },
910
- /**
911
- * Create a tree widget for displaying hierarchical data.
912
- * Supports expand/collapse, selection, and lazy loading.
913
- *
914
- * @example
915
- * ```ts
916
- * ui.tree<FileNode>({
917
- * id: "file-tree",
918
- * data: fileSystem,
919
- * getKey: (n) => n.path,
920
- * getChildren: (n) => n.children,
921
- * hasChildren: (n) => n.type === "directory",
922
- * expanded: state.expandedPaths,
923
- * selected: state.selectedPath,
924
- * onChange: (node, exp) => app.update(s => ({
925
- * expandedPaths: exp
926
- * ? [...s.expandedPaths, node.path]
927
- * : s.expandedPaths.filter(p => p !== node.path)
928
- * })),
929
- * onSelect: (n) => app.update({ selectedPath: n.path }),
930
- * onPress: (n) => n.type === "file" && openFile(n.path),
931
- * renderNode: (node, depth, state) => ui.row({ gap: 1 }, [
932
- * ui.text(state.expanded ? "▼" : state.hasChildren ? "▶" : " "),
933
- * ui.text(node.type === "directory" ? "📁" : "📄"),
934
- * ui.text(node.name),
935
- * ]),
936
- * showLines: true,
937
- * })
938
- * ```
939
- */
940
- tree(props) {
941
- return { kind: "tree", props: props };
942
- },
943
- /* ========== Form Widgets (GitHub issue #119) ========== */
944
- /**
945
- * Create a field wrapper for form inputs.
946
- * Displays label, error message, and optional hint.
947
- *
948
- * @example
949
- * ```ts
950
- * ui.field({
951
- * label: "Username",
952
- * required: true,
953
- * error: form.touched.username && form.errors.username,
954
- * hint: "Enter your email address",
955
- * children: ui.input(form.bind("username")),
956
- * })
957
- * ```
958
- */
959
- field(props) {
960
- return { kind: "field", props, children: Object.freeze([props.children]) };
961
- },
962
- /**
963
- * Create a select dropdown widget.
964
- * Supports keyboard navigation with ArrowUp/Down and Enter.
965
- *
966
- * @example
967
- * ```ts
968
- * ui.select({
969
- * id: "country",
970
- * value: form.values.country,
971
- * options: [
972
- * { value: "us", label: "United States" },
973
- * { value: "uk", label: "United Kingdom" },
974
- * { value: "ca", label: "Canada" },
975
- * ],
976
- * onChange: form.handleChange("country"),
977
- * placeholder: "Select a country...",
978
- * })
979
- * ```
980
- */
981
- select(props) {
982
- return { kind: "select", props };
983
- },
984
- /**
985
- * Create a slider widget.
986
- * Supports keyboard adjustment with Left/Right (or Up/Down), Home/End, and PageUp/PageDown.
987
- *
988
- * @example
989
- * ```ts
990
- * ui.slider({
991
- * id: "volume",
992
- * value: state.volume,
993
- * min: 0,
994
- * max: 100,
995
- * step: 5,
996
- * onChange: (value) => app.update({ volume: value }),
997
- * })
998
- * ```
999
- */
1000
- slider(props) {
1001
- return { kind: "slider", props };
1002
- },
1003
- /**
1004
- * Create a checkbox widget.
1005
- * Toggles with Space key.
1006
- *
1007
- * @example
1008
- * ```ts
1009
- * ui.checkbox({
1010
- * id: "remember",
1011
- * checked: form.values.remember,
1012
- * label: "Remember me",
1013
- * onChange: (c) => form.setFieldValue("remember", c),
1014
- * })
1015
- * ```
1016
- */
1017
- checkbox(props) {
1018
- return { kind: "checkbox", props };
1019
- },
1020
- /**
1021
- * Create a radio group widget.
1022
- * Supports keyboard navigation with ArrowUp/Down for selection.
1023
- *
1024
- * @example
1025
- * ```ts
1026
- * ui.radioGroup({
1027
- * id: "plan",
1028
- * value: form.values.plan,
1029
- * options: [
1030
- * { value: "free", label: "Free" },
1031
- * { value: "pro", label: "Pro" },
1032
- * { value: "enterprise", label: "Enterprise" },
1033
- * ],
1034
- * onChange: form.handleChange("plan"),
1035
- * direction: "vertical",
1036
- * })
1037
- * ```
1038
- */
1039
- radioGroup(props) {
1040
- return { kind: "radioGroup", props };
1041
- },
1042
- /* ========== Navigation Widgets ========== */
1043
- /**
1044
- * Create a tabs widget.
1045
- * Supports Left/Right tab switching and scoped content focus.
1046
- */
1047
- tabs(props) {
1048
- return createTabsWidgetVNode(props);
1049
- },
1050
- /**
1051
- * Create breadcrumbs from current router history.
1052
- */
1053
- routerBreadcrumb(router, routes, props = {}) {
1054
- return buildRouterBreadcrumb(router, routes, props);
1055
- },
1056
- /**
1057
- * Create tabs from registered routes with current route selection.
1058
- */
1059
- routerTabs(router, routes, props = {}) {
1060
- return buildRouterTabs(router, routes, props);
1061
- },
1062
- /**
1063
- * Create an accordion widget.
1064
- * Supports Up/Down header navigation and Enter/Space toggles.
1065
- */
1066
- accordion(props) {
1067
- return createAccordionWidgetVNode(props);
1068
- },
1069
- /**
1070
- * Create a breadcrumb widget.
1071
- * The last item is rendered as the current page (non-clickable).
1072
- */
1073
- breadcrumb(props) {
1074
- return createBreadcrumbWidgetVNode(props);
1075
- },
1076
- /**
1077
- * Create a pagination widget.
1078
- * Supports Left/Right navigation and optional Home/End first/last jumps.
1079
- */
1080
- pagination(props) {
1081
- return createPaginationWidgetVNode(props);
1082
- },
1083
- /* ========== Advanced Widgets (GitHub issue #136) ========== */
1084
- /**
1085
- * Create a command palette widget for quick-access command execution.
1086
- * Supports search, keyboard navigation, and multiple command sources.
1087
- *
1088
- * @example
1089
- * ```ts
1090
- * ui.commandPalette({
1091
- * id: "cmd-palette",
1092
- * open: state.paletteOpen,
1093
- * query: state.query,
1094
- * sources: [
1095
- * { id: "cmds", name: "Commands", prefix: ">", getItems: getCommands },
1096
- * { id: "files", name: "Files", getItems: searchFiles },
1097
- * ],
1098
- * selectedIndex: state.selectedIndex,
1099
- * onChange: (q) => app.update({ query: q }),
1100
- * onSelect: (item) => executeCommand(item),
1101
- * onClose: () => app.update({ paletteOpen: false }),
1102
- * })
1103
- * ```
1104
- */
1105
- commandPalette(props) {
1106
- return { kind: "commandPalette", props };
1107
- },
1108
- /**
1109
- * Create a file picker widget for browsing workspace files.
1110
- * Supports expand/collapse, multi-select, and git status indicators.
1111
- *
1112
- * @example
1113
- * ```ts
1114
- * ui.filePicker({
1115
- * id: "file-picker",
1116
- * rootPath: "/workspace",
1117
- * data: fileTree,
1118
- * selectedPath: state.selectedFile,
1119
- * expandedPaths: state.expanded,
1120
- * modifiedPaths: state.gitModified,
1121
- * onSelect: (path) => app.update({ selectedFile: path }),
1122
- * onChange: (path, exp) => toggleExpanded(path, exp),
1123
- * onPress: (path) => openFile(path),
1124
- * })
1125
- * ```
1126
- */
1127
- filePicker(props) {
1128
- return { kind: "filePicker", props };
1129
- },
1130
- /**
1131
- * Create a file tree explorer widget.
1132
- * Provides tree view with expand/collapse and custom node rendering.
1133
- *
1134
- * @example
1135
- * ```ts
1136
- * ui.fileTreeExplorer({
1137
- * id: "explorer",
1138
- * data: fileTree,
1139
- * expanded: state.expanded,
1140
- * selected: state.selected,
1141
- * showIcons: true,
1142
- * showStatus: true,
1143
- * onChange: (node, exp) => toggleNode(node, exp),
1144
- * onSelect: (node) => selectNode(node),
1145
- * onPress: (node) => openNode(node),
1146
- * })
1147
- * ```
1148
- */
1149
- fileTreeExplorer(props) {
1150
- return { kind: "fileTreeExplorer", props };
1151
- },
1152
- /**
1153
- * Create a split pane widget with draggable dividers.
1154
- * Supports horizontal/vertical splits with resize constraints.
1155
- *
1156
- * @example
1157
- * ```ts
1158
- * ui.splitPane({
1159
- * id: "main-split",
1160
- * direction: "horizontal",
1161
- * sizes: [25, 50, 25],
1162
- * minSizes: [20, 30, 20],
1163
- * onChange: (sizes) => app.update({ panelSizes: sizes }),
1164
- * }, [
1165
- * FileExplorer(),
1166
- * Editor(),
1167
- * LogsPanel(),
1168
- * ])
1169
- * ```
1170
- */
1171
- splitPane(props, children = []) {
1172
- return { kind: "splitPane", props, children };
1173
- },
1174
- /**
1175
- * Create a panel group container for resizable panels.
1176
- * Manages layout and resize state for child panels.
1177
- *
1178
- * @example
1179
- * ```ts
1180
- * ui.panelGroup({
1181
- * id: "panel-group",
1182
- * direction: "horizontal",
1183
- * }, [
1184
- * ui.resizablePanel({ defaultSize: 25 }, [Sidebar()]),
1185
- * ui.resizablePanel({ defaultSize: 75, minSize: 50 }, [Content()]),
1186
- * ])
1187
- * ```
1188
- */
1189
- panelGroup(props, children = []) {
1190
- return { kind: "panelGroup", props, children };
1191
- },
1192
- /**
1193
- * Create a resizable panel within a panel group.
1194
- * Specifies size constraints for the panel.
1195
- *
1196
- * @example
1197
- * ```ts
1198
- * ui.resizablePanel({
1199
- * defaultSize: 30,
1200
- * minSize: 20,
1201
- * maxSize: 50,
1202
- * collapsible: true,
1203
- * }, [PanelContent()])
1204
- * ```
1205
- */
1206
- resizablePanel(props = {}, children = []) {
1207
- return { kind: "resizablePanel", props, children };
1208
- },
1209
- /**
1210
- * Create a code editor widget for multiline text editing.
1211
- * Supports selections, keyboard navigation, and undo/redo.
1212
- *
1213
- * @example
1214
- * ```ts
1215
- * ui.codeEditor({
1216
- * id: "editor",
1217
- * lines: state.lines,
1218
- * cursor: state.cursor,
1219
- * selection: state.selection,
1220
- * scrollTop: state.scrollTop,
1221
- * scrollLeft: state.scrollLeft,
1222
- * syntaxLanguage: "typescript",
1223
- * lineNumbers: true,
1224
- * tabSize: 2,
1225
- * onChange: (lines, cursor) => app.update({ lines, cursor }),
1226
- * onSelectionChange: (sel) => app.update({ selection: sel }),
1227
- * onScroll: (top, left) => app.update({ scrollTop: top, scrollLeft: left }),
1228
- * })
1229
- * ```
1230
- */
1231
- codeEditor(props) {
1232
- return { kind: "codeEditor", props };
1233
- },
1234
- /**
1235
- * Create a diff viewer widget for displaying file changes.
1236
- * Supports unified and side-by-side modes with hunk staging.
1237
- *
1238
- * @example
1239
- * ```ts
1240
- * ui.diffViewer({
1241
- * id: "diff",
1242
- * diff: fileDiff,
1243
- * mode: "unified",
1244
- * scrollTop: state.scrollTop,
1245
- * lineNumbers: true,
1246
- * contextLines: 3,
1247
- * onScroll: (top) => app.update({ scrollTop: top }),
1248
- * onStageHunk: (i) => stageHunk(i),
1249
- * onRevertHunk: (i) => revertHunk(i),
1250
- * })
1251
- * ```
1252
- */
1253
- diffViewer(props) {
1254
- return { kind: "diffViewer", props };
1255
- },
1256
- /**
1257
- * Create a tool approval dialog for reviewing tool execution.
1258
- * Shows tool details, risk level, and approval actions.
1259
- *
1260
- * @example
1261
- * ```ts
1262
- * ui.toolApprovalDialog({
1263
- * id: "approval",
1264
- * open: state.pendingApproval !== null,
1265
- * request: state.pendingApproval,
1266
- * onPress: (action) => action === "allow"
1267
- * ? executeTool(state.pendingApproval)
1268
- * : app.update({ pendingApproval: null }),
1269
- * onAllowForSession: () => allowForSession(state.pendingApproval),
1270
- * onClose: () => app.update({ pendingApproval: null }),
1271
- * })
1272
- * ```
1273
- */
1274
- toolApprovalDialog(props) {
1275
- return { kind: "toolApprovalDialog", props };
1276
- },
1277
- /**
1278
- * Create a logs console widget for streaming output.
1279
- * Supports filtering, auto-scroll, and expandable entries.
1280
- *
1281
- * @example
1282
- * ```ts
1283
- * ui.logsConsole({
1284
- * id: "logs",
1285
- * entries: state.logs,
1286
- * autoScroll: true,
1287
- * levelFilter: ["info", "warn", "error"],
1288
- * scrollTop: state.logsScrollTop,
1289
- * showTimestamps: true,
1290
- * onScroll: (top) => app.update({ logsScrollTop: top }),
1291
- * onPress: () => app.update({ logs: [] }),
1292
- * })
1293
- * ```
1294
- */
1295
- logsConsole(props) {
1296
- return { kind: "logsConsole", props };
1297
- },
1298
- /**
1299
- * Create a toast container for non-blocking notifications.
1300
- * Manages toast stack and auto-dismiss.
1301
- *
1302
- * @example
1303
- * ```ts
1304
- * ui.toastContainer({
1305
- * toasts: state.toasts,
1306
- * position: "bottom-right",
1307
- * maxVisible: 5,
1308
- * onClose: (id) => app.update(s => ({
1309
- * toasts: s.toasts.filter(t => t.id !== id)
1310
- * })),
1311
- * })
1312
- * ```
1313
- */
1314
- toastContainer(props) {
1315
- return { kind: "toastContainer", props };
1316
- },
64
+ dialog,
65
+ modal,
66
+ dropdown,
67
+ layer,
68
+ table,
69
+ tree,
70
+ field,
71
+ select,
72
+ slider,
73
+ checkbox,
74
+ radioGroup,
75
+ tabs,
76
+ routerBreadcrumb,
77
+ routerTabs,
78
+ accordion,
79
+ breadcrumb,
80
+ pagination,
81
+ commandPalette,
82
+ filePicker,
83
+ fileTreeExplorer,
84
+ splitPane,
85
+ panelGroup,
86
+ resizablePanel,
87
+ codeEditor,
88
+ diffViewer,
89
+ toolApprovalDialog,
90
+ logsConsole,
91
+ toastContainer,
1317
92
  };
1318
93
  //# sourceMappingURL=ui.js.map