@kerfjs/ui 5.0.0-beta.6 → 5.0.0-beta.61

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 (714) hide show
  1. package/README.md +494 -138
  2. package/ai/application-ui-diagnostic-ids-v1.json +109 -0
  3. package/ai/application-ui-profile-sync.cjs +529 -0
  4. package/ai/application-ui-profile.d.mts +1 -0
  5. package/ai/application-ui-profile.d.ts +102 -0
  6. package/ai/application-ui-profile.defaults.json +96 -0
  7. package/ai/application-ui-profile.mjs +626 -0
  8. package/ai/application-ui-profile.schema.json +130 -0
  9. package/ai/catalog-authoring.json +36 -0
  10. package/ai/catalog-authoring.schema.json +109 -0
  11. package/ai/compile-time-contracts-v1.json +149 -0
  12. package/ai/compile-time-contracts-v1.schema.json +52 -0
  13. package/ai/component-catalog-extension.schema.json +79 -0
  14. package/ai/component-catalog.json +4041 -591
  15. package/ai/component-catalog.schema.json +78 -1
  16. package/ai/component-class-owners.cjs +83 -0
  17. package/ai/component-composition-extension.d.ts +7 -0
  18. package/ai/component-composition-extension.schema.json +7 -0
  19. package/ai/component-composition-rules.json +524 -0
  20. package/ai/component-composition.d.ts +125 -0
  21. package/ai/component-composition.json +7074 -0
  22. package/ai/component-composition.schema.json +375 -0
  23. package/ai/components/README.md +171 -0
  24. package/ai/components/application-tabs.md +65 -0
  25. package/ai/components/badge.md +72 -0
  26. package/ai/components/chip.md +72 -0
  27. package/ai/components/collapsible-panel.md +102 -0
  28. package/ai/components/content-item.md +90 -0
  29. package/ai/components/disclosure-arrow.md +77 -0
  30. package/ai/components/document-baseline.md +75 -0
  31. package/ai/components/empty-state.md +80 -0
  32. package/ai/components/feedback.md +71 -0
  33. package/ai/components/floating-toolbar.md +82 -0
  34. package/ai/components/foundation.md +65 -0
  35. package/ai/components/grid.md +96 -0
  36. package/ai/components/headers.md +63 -0
  37. package/ai/components/layout.md +75 -0
  38. package/ai/components/list-action-row.md +91 -0
  39. package/ai/components/list-header.md +89 -0
  40. package/ai/components/list-inset-control.md +74 -0
  41. package/ai/components/list-inset-text.md +72 -0
  42. package/ai/components/list-item.md +94 -0
  43. package/ai/components/list.md +103 -0
  44. package/ai/components/loading-spinner.md +72 -0
  45. package/ai/components/lucide-icon.md +66 -0
  46. package/ai/components/nav-stack.md +103 -0
  47. package/ai/components/pane.md +100 -0
  48. package/ai/components/popup-menu.md +171 -0
  49. package/ai/components/recipe-app-shell.md +57 -0
  50. package/ai/components/recipe-collapsible-sidebar.md +57 -0
  51. package/ai/components/recipe-compact-toolbar.md +57 -0
  52. package/ai/components/recipe-composer-form.md +57 -0
  53. package/ai/components/recipe-list-detail-dialog.md +57 -0
  54. package/ai/components/recipe-list-workspace-states.md +57 -0
  55. package/ai/components/recipe-loading-inspector.md +57 -0
  56. package/ai/components/recipe-navigation-sidebar.md +57 -0
  57. package/ai/components/recipe-navigation-stack.md +57 -0
  58. package/ai/components/recipe-workspace-header.md +57 -0
  59. package/ai/components/resize.md +106 -0
  60. package/ai/components/row.md +96 -0
  61. package/ai/components/segmented-control.md +82 -0
  62. package/ai/components/select.md +112 -0
  63. package/ai/components/skeleton.md +84 -0
  64. package/ai/components/spacer.md +86 -0
  65. package/ai/components/split-view.md +102 -0
  66. package/ai/components/state-banner.md +94 -0
  67. package/ai/components/sunken-panel.md +79 -0
  68. package/ai/components/surface-scaffold.md +78 -0
  69. package/ai/components/tab-bar.md +112 -0
  70. package/ai/components/tab-scaffold.md +94 -0
  71. package/ai/components/tabs.md +95 -0
  72. package/ai/components/text.md +83 -0
  73. package/ai/components/token-search-field.md +103 -0
  74. package/ai/components/toolbar-control-group.md +102 -0
  75. package/ai/components/toolbar-text.md +78 -0
  76. package/ai/components/toolbar.md +97 -0
  77. package/ai/components/value-table.md +73 -0
  78. package/ai/components/wa-accordion-item.md +55 -0
  79. package/ai/components/wa-accordion.md +65 -0
  80. package/ai/components/wa-animated-image.md +55 -0
  81. package/ai/components/wa-animation.md +55 -0
  82. package/ai/components/wa-avatar.md +55 -0
  83. package/ai/components/wa-badge.md +55 -0
  84. package/ai/components/wa-breadcrumb-item.md +53 -0
  85. package/ai/components/wa-breadcrumb.md +55 -0
  86. package/ai/components/wa-button-group.md +59 -0
  87. package/ai/components/wa-button.md +55 -0
  88. package/ai/components/wa-callout.md +58 -0
  89. package/ai/components/wa-card.md +59 -0
  90. package/ai/components/wa-carousel-item.md +53 -0
  91. package/ai/components/wa-carousel.md +55 -0
  92. package/ai/components/wa-checkbox-group.md +55 -0
  93. package/ai/components/wa-checkbox.md +55 -0
  94. package/ai/components/wa-color-picker.md +55 -0
  95. package/ai/components/wa-comparison.md +55 -0
  96. package/ai/components/wa-copy-button.md +55 -0
  97. package/ai/components/wa-details.md +61 -0
  98. package/ai/components/wa-dialog.md +59 -0
  99. package/ai/components/wa-divider.md +53 -0
  100. package/ai/components/wa-drawer.md +55 -0
  101. package/ai/components/wa-dropdown-item.md +60 -0
  102. package/ai/components/wa-dropdown.md +60 -0
  103. package/ai/components/wa-format-bytes.md +53 -0
  104. package/ai/components/wa-format-date.md +53 -0
  105. package/ai/components/wa-format-number.md +53 -0
  106. package/ai/components/wa-icon.md +58 -0
  107. package/ai/components/wa-include.md +53 -0
  108. package/ai/components/wa-input.md +59 -0
  109. package/ai/components/wa-intersection-observer.md +53 -0
  110. package/ai/components/wa-known-date.md +53 -0
  111. package/ai/components/wa-markdown.md +53 -0
  112. package/ai/components/wa-mutation-observer.md +53 -0
  113. package/ai/components/wa-number-input.md +55 -0
  114. package/ai/components/wa-option.md +59 -0
  115. package/ai/components/wa-otp-input.md +53 -0
  116. package/ai/components/wa-page.md +53 -0
  117. package/ai/components/wa-pagination.md +55 -0
  118. package/ai/components/wa-popover.md +55 -0
  119. package/ai/components/wa-popup.md +53 -0
  120. package/ai/components/wa-progress-bar.md +53 -0
  121. package/ai/components/wa-progress-ring.md +53 -0
  122. package/ai/components/wa-qr-code.md +53 -0
  123. package/ai/components/wa-radio-group.md +59 -0
  124. package/ai/components/wa-radio.md +55 -0
  125. package/ai/components/wa-random-content.md +53 -0
  126. package/ai/components/wa-rating.md +55 -0
  127. package/ai/components/wa-relative-time.md +53 -0
  128. package/ai/components/wa-resize-observer.md +53 -0
  129. package/ai/components/wa-scroller.md +53 -0
  130. package/ai/components/wa-select.md +63 -0
  131. package/ai/components/wa-skeleton.md +53 -0
  132. package/ai/components/wa-slider.md +55 -0
  133. package/ai/components/wa-spinner.md +58 -0
  134. package/ai/components/wa-split-panel.md +58 -0
  135. package/ai/components/wa-switch.md +53 -0
  136. package/ai/components/wa-tab-group.md +69 -0
  137. package/ai/components/wa-tab-panel.md +60 -0
  138. package/ai/components/wa-tab.md +59 -0
  139. package/ai/components/wa-tag.md +59 -0
  140. package/ai/components/wa-textarea.md +53 -0
  141. package/ai/components/wa-time-input.md +55 -0
  142. package/ai/components/wa-toast-item.md +60 -0
  143. package/ai/components/wa-toast.md +60 -0
  144. package/ai/components/wa-tooltip.md +55 -0
  145. package/ai/components/wa-tree-item.md +55 -0
  146. package/ai/components/wa-tree.md +55 -0
  147. package/ai/components/wa-zoomable-frame.md +55 -0
  148. package/ai/components/workbench.md +114 -0
  149. package/ai/public-api-signatures-v1.md +2597 -190
  150. package/ai/skill.md +259 -65
  151. package/ai/webawesome-jsx-signatures-v1.md +9 -2
  152. package/analyzer/cli.mjs +49 -0
  153. package/analyzer/component-ownership.d.mts +56 -0
  154. package/analyzer/component-ownership.mjs +184 -0
  155. package/analyzer/index.d.mts +49 -0
  156. package/analyzer/index.mjs +1458 -0
  157. package/analyzer/loud-pairs.d.mts +49 -0
  158. package/analyzer/loud-pairs.mjs +357 -0
  159. package/analyzer/report.schema.json +66 -0
  160. package/analyzer/selectors.d.mts +21 -0
  161. package/analyzer/selectors.mjs +212 -0
  162. package/dist/app-tab.d.ts +41 -4
  163. package/dist/app-tab.js +3 -1
  164. package/dist/badge.d.ts +52 -0
  165. package/dist/badge.js +3 -0
  166. package/dist/badge.js.map +1 -0
  167. package/dist/browser/app-tab.js +1 -0
  168. package/dist/browser/badge.js +3 -0
  169. package/dist/browser/catalog.js +25 -0
  170. package/dist/browser/chip.js +3 -0
  171. package/dist/browser/collapsible-panel.js +7 -0
  172. package/dist/browser/content-item.js +3 -0
  173. package/dist/browser/floating-toolbar.js +3 -0
  174. package/dist/browser/grid.js +3 -0
  175. package/dist/browser/list-action-row.js +5 -0
  176. package/dist/browser/list-header.js +8 -0
  177. package/dist/browser/list-inset-control.js +3 -0
  178. package/dist/browser/list-inset-text.js +3 -0
  179. package/dist/browser/list-item.js +5 -0
  180. package/dist/browser/list.js +3 -0
  181. package/dist/browser/{panel-header.js → nav-stack.js} +4 -2
  182. package/dist/browser/pane.js +3 -0
  183. package/dist/browser/popup-menu.js +3 -0
  184. package/dist/browser/row.js +3 -0
  185. package/dist/browser/select.js +2 -0
  186. package/dist/browser/skeleton.js +3 -0
  187. package/dist/browser/spacer.js +3 -0
  188. package/dist/browser/split-view.js +10 -0
  189. package/dist/browser/state-banner.js +2 -0
  190. package/dist/browser/sunken-panel.js +3 -0
  191. package/dist/browser/surface-scaffold.js +3 -0
  192. package/dist/browser/tab-scaffold.js +4 -0
  193. package/dist/browser/text.js +3 -0
  194. package/dist/browser/toolbar-text.js +1 -0
  195. package/dist/browser/value-table.js +1 -0
  196. package/dist/browser/workbench.js +10 -0
  197. package/dist/catalog-resources.d.ts +46 -0
  198. package/dist/catalog-resources.js +22 -0
  199. package/dist/catalog-resources.js.map +1 -0
  200. package/dist/catalog.d.ts +90 -0
  201. package/dist/catalog.js +501 -0
  202. package/dist/catalog.js.map +1 -0
  203. package/dist/chip.d.ts +29 -0
  204. package/dist/chip.js +3 -0
  205. package/dist/chip.js.map +1 -0
  206. package/dist/chunk-2G2ZJQYK.js +152 -0
  207. package/dist/chunk-2G2ZJQYK.js.map +1 -0
  208. package/dist/chunk-3SXMEK3B.js +43 -0
  209. package/dist/chunk-3SXMEK3B.js.map +1 -0
  210. package/dist/{chunk-W2FK7ZNY.js → chunk-4R777DUZ.js} +10 -2
  211. package/dist/chunk-4R777DUZ.js.map +1 -0
  212. package/dist/chunk-4SQK27MR.js +202 -0
  213. package/dist/chunk-4SQK27MR.js.map +1 -0
  214. package/dist/chunk-5I7QGQVT.js +24 -0
  215. package/dist/chunk-5I7QGQVT.js.map +1 -0
  216. package/dist/chunk-5PESG2VP.js +115 -0
  217. package/dist/chunk-5PESG2VP.js.map +1 -0
  218. package/dist/chunk-5Q3N6EV7.js +156 -0
  219. package/dist/chunk-5Q3N6EV7.js.map +1 -0
  220. package/dist/chunk-6ZXOQEAN.js +27 -0
  221. package/dist/chunk-6ZXOQEAN.js.map +1 -0
  222. package/dist/chunk-7JUBXOIV.js +103 -0
  223. package/dist/chunk-7JUBXOIV.js.map +1 -0
  224. package/dist/chunk-A3CKOW2R.js +622 -0
  225. package/dist/chunk-A3CKOW2R.js.map +1 -0
  226. package/dist/chunk-AHEG27M7.js +66 -0
  227. package/dist/chunk-AHEG27M7.js.map +1 -0
  228. package/dist/chunk-AUKT3KMG.js +37 -0
  229. package/dist/chunk-AUKT3KMG.js.map +1 -0
  230. package/dist/chunk-AYUHMAI6.js +48 -0
  231. package/dist/chunk-AYUHMAI6.js.map +1 -0
  232. package/dist/chunk-BFPBS5Y4.js +250 -0
  233. package/dist/chunk-BFPBS5Y4.js.map +1 -0
  234. package/dist/{chunk-MQIZAD4A.js → chunk-C4OYOKWX.js} +138 -22
  235. package/dist/chunk-C4OYOKWX.js.map +1 -0
  236. package/dist/chunk-DG6G5EPF.js +35 -0
  237. package/dist/chunk-DG6G5EPF.js.map +1 -0
  238. package/dist/chunk-E36EVCKG.js +34 -0
  239. package/dist/chunk-E36EVCKG.js.map +1 -0
  240. package/dist/chunk-EAC4CDY7.js +57 -0
  241. package/dist/chunk-EAC4CDY7.js.map +1 -0
  242. package/dist/chunk-EZVNC4J6.js +104 -0
  243. package/dist/chunk-EZVNC4J6.js.map +1 -0
  244. package/dist/chunk-F4QMLOXJ.js +135 -0
  245. package/dist/chunk-F4QMLOXJ.js.map +1 -0
  246. package/dist/chunk-GLDWRCAM.js +49 -0
  247. package/dist/chunk-GLDWRCAM.js.map +1 -0
  248. package/dist/chunk-I3Q7KKYM.js +33 -0
  249. package/dist/chunk-I3Q7KKYM.js.map +1 -0
  250. package/dist/chunk-IA7TMD4Y.js +288 -0
  251. package/dist/chunk-IA7TMD4Y.js.map +1 -0
  252. package/dist/chunk-JCV4GXWB.js +249 -0
  253. package/dist/chunk-JCV4GXWB.js.map +1 -0
  254. package/dist/chunk-K47P7QZC.js +17 -0
  255. package/dist/chunk-K47P7QZC.js.map +1 -0
  256. package/dist/chunk-KLJKU6ZL.js +109 -0
  257. package/dist/chunk-KLJKU6ZL.js.map +1 -0
  258. package/dist/{chunk-56RJXPHG.js → chunk-KROD7KZK.js} +7 -4
  259. package/dist/chunk-KROD7KZK.js.map +1 -0
  260. package/dist/chunk-MA73TA6D.js +42 -0
  261. package/dist/chunk-MA73TA6D.js.map +1 -0
  262. package/dist/chunk-MERWRTBG.js +45 -0
  263. package/dist/chunk-MERWRTBG.js.map +1 -0
  264. package/dist/chunk-MEY33VWB.js +44 -0
  265. package/dist/chunk-MEY33VWB.js.map +1 -0
  266. package/dist/chunk-MP2GDBQZ.js +50 -0
  267. package/dist/chunk-MP2GDBQZ.js.map +1 -0
  268. package/dist/chunk-N3GKMPDW.js +51 -0
  269. package/dist/chunk-N3GKMPDW.js.map +1 -0
  270. package/dist/chunk-NAPE7WUS.js +75 -0
  271. package/dist/chunk-NAPE7WUS.js.map +1 -0
  272. package/dist/chunk-NN6GYOA2.js +47 -0
  273. package/dist/chunk-NN6GYOA2.js.map +1 -0
  274. package/dist/chunk-NNMLEDMD.js +399 -0
  275. package/dist/chunk-NNMLEDMD.js.map +1 -0
  276. package/dist/chunk-NYL63PSD.js +95 -0
  277. package/dist/chunk-NYL63PSD.js.map +1 -0
  278. package/dist/chunk-P7D3EMXM.js +52 -0
  279. package/dist/chunk-P7D3EMXM.js.map +1 -0
  280. package/dist/chunk-PSHUSWQH.js +18 -0
  281. package/dist/chunk-PSHUSWQH.js.map +1 -0
  282. package/dist/chunk-Q6YU3BT7.js +138 -0
  283. package/dist/chunk-Q6YU3BT7.js.map +1 -0
  284. package/dist/chunk-RRB26JRJ.js +247 -0
  285. package/dist/chunk-RRB26JRJ.js.map +1 -0
  286. package/dist/{chunk-7BR3DO2A.js → chunk-SRSJO5QE.js} +13 -4
  287. package/dist/chunk-SRSJO5QE.js.map +1 -0
  288. package/dist/chunk-SWVW56CV.js +188 -0
  289. package/dist/chunk-SWVW56CV.js.map +1 -0
  290. package/dist/chunk-TEYARRAK.js +216 -0
  291. package/dist/chunk-TEYARRAK.js.map +1 -0
  292. package/dist/chunk-UCKKT6KO.js +71 -0
  293. package/dist/chunk-UCKKT6KO.js.map +1 -0
  294. package/dist/chunk-UIDKY4UB.js +14 -0
  295. package/dist/chunk-UIDKY4UB.js.map +1 -0
  296. package/dist/chunk-VCBTX62E.js +135 -0
  297. package/dist/chunk-VCBTX62E.js.map +1 -0
  298. package/dist/chunk-VZOFZPSO.js +71 -0
  299. package/dist/chunk-VZOFZPSO.js.map +1 -0
  300. package/dist/{chunk-TRNBHPNW.js → chunk-X5QSICJ3.js} +13 -7
  301. package/dist/chunk-X5QSICJ3.js.map +1 -0
  302. package/dist/chunk-Y74NWGQW.js +418 -0
  303. package/dist/chunk-Y74NWGQW.js.map +1 -0
  304. package/dist/chunk-ZLWQZUGF.js +27 -0
  305. package/dist/chunk-ZLWQZUGF.js.map +1 -0
  306. package/dist/collapsible-panel.d.ts +122 -0
  307. package/dist/collapsible-panel.js +115 -0
  308. package/dist/collapsible-panel.js.map +1 -0
  309. package/dist/content-item.d.ts +46 -0
  310. package/dist/content-item.js +4 -0
  311. package/dist/content-item.js.map +1 -0
  312. package/dist/css-values.d.ts +107 -0
  313. package/dist/css-values.js +3 -0
  314. package/dist/css-values.js.map +1 -0
  315. package/dist/device-class.js +33 -5
  316. package/dist/device-class.js.map +1 -1
  317. package/dist/disclosure-arrow.d.ts +6 -1
  318. package/dist/disclosure-arrow.js +1 -1
  319. package/dist/empty-state.d.ts +5 -2
  320. package/dist/empty-state.js +1 -1
  321. package/dist/flex-alignment-4ms8ZbV8.d.ts +5 -0
  322. package/dist/floating-toolbar.d.ts +51 -0
  323. package/dist/floating-toolbar.js +3 -0
  324. package/dist/floating-toolbar.js.map +1 -0
  325. package/dist/grid.d.ts +42 -0
  326. package/dist/grid.js +5 -0
  327. package/dist/grid.js.map +1 -0
  328. package/dist/help-tags-register.d.ts +13 -0
  329. package/dist/help-tags-register.js +9 -0
  330. package/dist/help-tags-register.js.map +1 -0
  331. package/dist/index.d.ts +35 -14
  332. package/dist/index.js +43 -22
  333. package/dist/list-action-row.d.ts +64 -0
  334. package/dist/list-action-row.js +8 -0
  335. package/dist/list-action-row.js.map +1 -0
  336. package/dist/list-header.d.ts +99 -0
  337. package/dist/list-header.js +10 -0
  338. package/dist/list-header.js.map +1 -0
  339. package/dist/list-inset-control.d.ts +22 -0
  340. package/dist/list-inset-control.js +3 -0
  341. package/dist/list-inset-control.js.map +1 -0
  342. package/dist/list-inset-text.d.ts +30 -0
  343. package/dist/list-inset-text.js +4 -0
  344. package/dist/list-inset-text.js.map +1 -0
  345. package/dist/list-item.d.ts +62 -0
  346. package/dist/list-item.js +8 -0
  347. package/dist/list-item.js.map +1 -0
  348. package/dist/list.d.ts +59 -0
  349. package/dist/list.js +6 -0
  350. package/dist/list.js.map +1 -0
  351. package/dist/loading-spinner.d.ts +3 -1
  352. package/dist/loading-spinner.js +1 -1
  353. package/dist/lucide-icon.d.ts +3 -1
  354. package/dist/lucide-icon.js +1 -1
  355. package/dist/nav-stack.d.ts +60 -10
  356. package/dist/nav-stack.js +6 -1
  357. package/dist/pane.d.ts +102 -0
  358. package/dist/pane.js +4 -0
  359. package/dist/pane.js.map +1 -0
  360. package/dist/panel-toolbar-DqwtBxQL.d.ts +63 -0
  361. package/dist/popup-menu-register.d.ts +9 -0
  362. package/dist/popup-menu-register.js +31 -0
  363. package/dist/popup-menu-register.js.map +1 -0
  364. package/dist/popup-menu.d.ts +99 -0
  365. package/dist/popup-menu.js +3 -0
  366. package/dist/popup-menu.js.map +1 -0
  367. package/dist/resizable-region.d.ts +32 -3
  368. package/dist/resizable-region.js +1 -1
  369. package/dist/row.d.ts +48 -0
  370. package/dist/row.js +6 -0
  371. package/dist/row.js.map +1 -0
  372. package/dist/segmented-control.d.ts +13 -8
  373. package/dist/segmented-control.js +1 -1
  374. package/dist/select-register.d.ts +5 -1
  375. package/dist/select-register.js +243 -2
  376. package/dist/select-register.js.map +1 -1
  377. package/dist/select.d.ts +101 -8
  378. package/dist/select.js +4 -1
  379. package/dist/semantic-content-BbzjvSu9.d.ts +14 -0
  380. package/dist/sides-BPSWde0A.d.ts +4 -0
  381. package/dist/skeleton.d.ts +31 -0
  382. package/dist/skeleton.js +4 -0
  383. package/dist/skeleton.js.map +1 -0
  384. package/dist/spacer.d.ts +18 -0
  385. package/dist/spacer.js +4 -0
  386. package/dist/spacer.js.map +1 -0
  387. package/dist/split-view.d.ts +39 -7
  388. package/dist/split-view.js +120 -10
  389. package/dist/split-view.js.map +1 -1
  390. package/dist/state-banner.d.ts +19 -5
  391. package/dist/state-banner.js +4 -1
  392. package/dist/styles/app-tab.css +104 -0
  393. package/dist/styles/badge.css +118 -0
  394. package/dist/styles/catalog/components/catalog-example-stack.css +9 -0
  395. package/dist/styles/catalog/components/catalog-example.css +164 -0
  396. package/dist/styles/catalog/components/catalog-stage.css +55 -0
  397. package/dist/styles/catalog/components/catalog.css +12 -0
  398. package/dist/styles/catalog.css +5 -0
  399. package/dist/styles/chip.css +118 -0
  400. package/dist/styles/collapsible-panel.css +575 -0
  401. package/dist/styles/content-item.css +30 -0
  402. package/dist/styles/document.css +23 -0
  403. package/dist/styles/floating-toolbar.css +119 -0
  404. package/dist/styles/foundation.css +178 -40
  405. package/dist/styles/grid.css +28 -0
  406. package/dist/styles/layout.css +3 -41
  407. package/dist/styles/list-action-row.css +257 -0
  408. package/dist/styles/list-header.css +228 -0
  409. package/dist/styles/list-inset-control.css +30 -0
  410. package/dist/styles/list-inset-text.css +29 -0
  411. package/dist/styles/list-item.css +245 -0
  412. package/dist/styles/list.css +133 -0
  413. package/dist/styles/nav-stack.css +158 -50
  414. package/dist/styles/pane.css +229 -0
  415. package/dist/styles/popup-menu.css +271 -0
  416. package/dist/styles/resizable-region.css +429 -4
  417. package/dist/styles/row.css +111 -0
  418. package/dist/styles/segmented-control.css +33 -9
  419. package/dist/styles/select.css +262 -9
  420. package/dist/styles/skeleton.css +92 -0
  421. package/dist/styles/spacer.css +11 -0
  422. package/dist/styles/split-view.css +108 -3
  423. package/dist/styles/state-banner.css +94 -19
  424. package/dist/styles/styles.css +14 -4
  425. package/dist/styles/sunken-panel.css +22 -0
  426. package/dist/styles/surface-scaffold.css +56 -0
  427. package/dist/styles/tab-bar.css +132 -9
  428. package/dist/styles/tab-scaffold.css +113 -3
  429. package/dist/styles/text.css +65 -0
  430. package/dist/styles/token-search-field.css +49 -43
  431. package/dist/styles/toolbar-control-group.css +465 -28
  432. package/dist/styles/toolbar-text.css +88 -4
  433. package/dist/styles/toolbar.css +322 -11
  434. package/dist/styles/value-table.css +34 -4
  435. package/dist/styles/webawesome.css +348 -10
  436. package/dist/styles/workbench.css +828 -7
  437. package/dist/sunken-panel.d.ts +22 -0
  438. package/dist/sunken-panel.js +3 -0
  439. package/dist/sunken-panel.js.map +1 -0
  440. package/dist/surface-scaffold.d.ts +30 -0
  441. package/dist/surface-scaffold.js +3 -0
  442. package/dist/surface-scaffold.js.map +1 -0
  443. package/dist/tab-bar.d.ts +31 -6
  444. package/dist/tab-bar.js +1 -1
  445. package/dist/tab-scaffold.d.ts +54 -7
  446. package/dist/tab-scaffold.js +82 -9
  447. package/dist/tab-scaffold.js.map +1 -1
  448. package/dist/text.d.ts +38 -0
  449. package/dist/text.js +3 -0
  450. package/dist/text.js.map +1 -0
  451. package/dist/token-search-field-DvgFLhLL.d.ts +130 -0
  452. package/dist/token-search-field.d.ts +3 -43
  453. package/dist/token-search-field.js +1 -1
  454. package/dist/token-search-model.d.ts +3 -0
  455. package/dist/token-search-model.js +3 -0
  456. package/dist/token-search-model.js.map +1 -0
  457. package/dist/toolbar-control-group.d.ts +65 -7
  458. package/dist/toolbar-control-group.js +1 -1
  459. package/dist/toolbar-text.d.ts +37 -4
  460. package/dist/toolbar-text.js +3 -1
  461. package/dist/toolbar.d.ts +56 -7
  462. package/dist/toolbar.js +1 -1
  463. package/dist/types-BuHELdXR.d.ts +117 -0
  464. package/dist/value-table.d.ts +13 -3
  465. package/dist/value-table.js +3 -1
  466. package/dist/webawesome.d.ts +8 -1
  467. package/dist/wire-catalog.d.ts +82 -0
  468. package/dist/wire-catalog.js +327 -0
  469. package/dist/wire-catalog.js.map +1 -0
  470. package/dist/wire-nav-stack.d.ts +4 -1
  471. package/dist/wire-nav-stack.js +147 -7
  472. package/dist/wire-nav-stack.js.map +1 -1
  473. package/dist/wire-resizable-regions.d.ts +2 -1
  474. package/dist/wire-resizable-regions.js +2 -1
  475. package/dist/wire-scroll-dividers.d.ts +69 -0
  476. package/dist/wire-scroll-dividers.js +3 -0
  477. package/dist/wire-scroll-dividers.js.map +1 -0
  478. package/dist/wire-sidebar.d.ts +63 -0
  479. package/dist/wire-sidebar.js +231 -0
  480. package/dist/wire-sidebar.js.map +1 -0
  481. package/dist/wire-tab-bars.d.ts +19 -2
  482. package/dist/wire-tab-bars.js +1 -1
  483. package/dist/wire-tab-scaffold.js +9 -4
  484. package/dist/wire-tab-scaffold.js.map +1 -1
  485. package/dist/wire-token-search-fields.d.ts +65 -3
  486. package/dist/wire-token-search-fields.js +1 -1
  487. package/dist/wire-workbench.d.ts +109 -0
  488. package/dist/wire-workbench.js +6 -0
  489. package/dist/wire-workbench.js.map +1 -0
  490. package/dist/workbench.d.ts +218 -7
  491. package/dist/workbench.js +13 -15
  492. package/dist/workbench.js.map +1 -1
  493. package/docs/accessibility.md +413 -23
  494. package/docs/app-layouts.md +106 -8
  495. package/docs/catalog.md +440 -0
  496. package/docs/collapsible-panel.md +363 -0
  497. package/docs/component-contract.md +560 -52
  498. package/docs/component-integration.md +75 -0
  499. package/docs/component-selection.md +421 -89
  500. package/docs/design/templates/empty-state/filtered-dark.svg +1 -0
  501. package/docs/design/templates/empty-state/filtered.svg +1 -0
  502. package/docs/design/templates/empty-state/with-action-dark.svg +1 -0
  503. package/docs/design/templates/empty-state/with-action.svg +1 -0
  504. package/docs/design/templates/empty-state-dark.svg +1 -0
  505. package/docs/design/templates/empty-state.svg +1 -0
  506. package/docs/design/templates/list/compact-dark.svg +1 -0
  507. package/docs/design/templates/list/compact.svg +1 -0
  508. package/docs/design/templates/list/stack-dark.svg +1 -0
  509. package/docs/design/templates/list/stack.svg +1 -0
  510. package/docs/design/templates/list-action-row/default-dark.svg +1 -0
  511. package/docs/design/templates/list-action-row/default.svg +1 -0
  512. package/docs/design/templates/list-action-row/selected-dark.svg +1 -0
  513. package/docs/design/templates/list-action-row/selected.svg +1 -0
  514. package/docs/design/templates/list-action-row-dark.svg +1 -0
  515. package/docs/design/templates/list-action-row.svg +1 -0
  516. package/docs/design/templates/list-dark.svg +1 -0
  517. package/docs/design/templates/list-header/action-dark.svg +1 -0
  518. package/docs/design/templates/list-header/action.svg +1 -0
  519. package/docs/design/templates/list-header/count-dark.svg +1 -0
  520. package/docs/design/templates/list-header/count.svg +1 -0
  521. package/docs/design/templates/list-header/inline-action-dark.svg +1 -0
  522. package/docs/design/templates/list-header/inline-action.svg +1 -0
  523. package/docs/design/templates/list-header/toggle-collapsed-dark.svg +1 -0
  524. package/docs/design/templates/list-header/toggle-collapsed.svg +1 -0
  525. package/docs/design/templates/list-header/toggle-expanded-dark.svg +1 -0
  526. package/docs/design/templates/list-header/toggle-expanded.svg +1 -0
  527. package/docs/design/templates/list-header-dark.svg +1 -0
  528. package/docs/design/templates/list-header.svg +1 -0
  529. package/docs/design/templates/list-item/default-dark.svg +1 -0
  530. package/docs/design/templates/list-item/default.svg +1 -0
  531. package/docs/design/templates/list-item/multiline-dark.svg +1 -0
  532. package/docs/design/templates/list-item/multiline.svg +1 -0
  533. package/docs/design/templates/list-item/selected-dark.svg +1 -0
  534. package/docs/design/templates/list-item/selected.svg +1 -0
  535. package/docs/design/templates/list-item/trailing-dark.svg +1 -0
  536. package/docs/design/templates/list-item/trailing.svg +1 -0
  537. package/docs/design/templates/list-item-dark.svg +1 -0
  538. package/docs/design/templates/list-item.svg +1 -0
  539. package/docs/design/templates/list.svg +1 -0
  540. package/docs/design/templates/segmented-control/equal-dark.svg +1 -0
  541. package/docs/design/templates/segmented-control/equal.svg +1 -0
  542. package/docs/design/templates/segmented-control/pill-small-dark.svg +1 -0
  543. package/docs/design/templates/segmented-control/pill-small.svg +1 -0
  544. package/docs/design/templates/segmented-control-dark.svg +1 -0
  545. package/docs/design/templates/segmented-control.svg +1 -0
  546. package/docs/design/templates/skeleton/avatar-dark.svg +1 -0
  547. package/docs/design/templates/skeleton/avatar.svg +1 -0
  548. package/docs/design/templates/skeleton/block-dark.svg +1 -0
  549. package/docs/design/templates/skeleton/block.svg +1 -0
  550. package/docs/design/templates/skeleton/lines-dark.svg +1 -0
  551. package/docs/design/templates/skeleton/lines.svg +1 -0
  552. package/docs/design/templates/skeleton-dark.svg +1 -0
  553. package/docs/design/templates/skeleton.svg +1 -0
  554. package/docs/design/templates/state-banner/danger-dark.svg +1 -0
  555. package/docs/design/templates/state-banner/danger.svg +1 -0
  556. package/docs/design/templates/state-banner/info-badge-dark.svg +1 -0
  557. package/docs/design/templates/state-banner/info-badge.svg +1 -0
  558. package/docs/design/templates/state-banner/info-dark.svg +1 -0
  559. package/docs/design/templates/state-banner/info.svg +1 -0
  560. package/docs/design/templates/state-banner/success-dark.svg +1 -0
  561. package/docs/design/templates/state-banner/success.svg +1 -0
  562. package/docs/design/templates/state-banner/warning-dark.svg +1 -0
  563. package/docs/design/templates/state-banner/warning.svg +1 -0
  564. package/docs/design/templates/state-banner-dark.svg +1 -0
  565. package/docs/design/templates/state-banner.svg +1 -0
  566. package/docs/design/templates/tab-bar/workspace-tabs-dark.svg +1 -0
  567. package/docs/design/templates/tab-bar/workspace-tabs.svg +1 -0
  568. package/docs/design/templates/tab-bar-dark.svg +1 -0
  569. package/docs/design/templates/tab-bar.svg +1 -0
  570. package/docs/design/templates/token-search-field/empty-dark.svg +1 -0
  571. package/docs/design/templates/token-search-field/empty.svg +1 -0
  572. package/docs/design/templates/token-search-field/tokens-dark.svg +1 -0
  573. package/docs/design/templates/token-search-field/tokens.svg +1 -0
  574. package/docs/design/templates/token-search-field-dark.svg +1 -0
  575. package/docs/design/templates/token-search-field.svg +1 -0
  576. package/docs/design/templates/toolbar/title-and-actions-dark.svg +1 -0
  577. package/docs/design/templates/toolbar/title-and-actions.svg +1 -0
  578. package/docs/design/templates/toolbar-control-group/borderless-single-dark.svg +1 -0
  579. package/docs/design/templates/toolbar-control-group/borderless-single.svg +1 -0
  580. package/docs/design/templates/toolbar-control-group/icon-buttons-dark.svg +1 -0
  581. package/docs/design/templates/toolbar-control-group/icon-buttons.svg +1 -0
  582. package/docs/design/templates/toolbar-control-group/push-buttons-dark.svg +1 -0
  583. package/docs/design/templates/toolbar-control-group/push-buttons.svg +1 -0
  584. package/docs/design/templates/toolbar-control-group/with-text-dark.svg +1 -0
  585. package/docs/design/templates/toolbar-control-group/with-text.svg +1 -0
  586. package/docs/design/templates/toolbar-control-group-dark.svg +1 -0
  587. package/docs/design/templates/toolbar-control-group.svg +1 -0
  588. package/docs/design/templates/toolbar-dark.svg +1 -0
  589. package/docs/design/templates/toolbar-text/default-dark.svg +1 -0
  590. package/docs/design/templates/toolbar-text/default.svg +1 -0
  591. package/docs/design/templates/toolbar-text/large-dark.svg +1 -0
  592. package/docs/design/templates/toolbar-text/large.svg +1 -0
  593. package/docs/design/templates/toolbar-text/small-dark.svg +1 -0
  594. package/docs/design/templates/toolbar-text/small.svg +1 -0
  595. package/docs/design/templates/toolbar-text-dark.svg +1 -0
  596. package/docs/design/templates/toolbar-text.svg +1 -0
  597. package/docs/design/templates/toolbar.svg +1 -0
  598. package/docs/design/templates/value-table/details-dark.svg +1 -0
  599. package/docs/design/templates/value-table/details.svg +1 -0
  600. package/docs/design/templates/value-table-dark.svg +1 -0
  601. package/docs/design/templates/value-table.svg +1 -0
  602. package/docs/design/templates.md +138 -0
  603. package/docs/design-philosophy.md +48 -20
  604. package/docs/device-class.md +10 -9
  605. package/docs/document-baseline.md +38 -0
  606. package/docs/examples/application-ui-profile.json +60 -0
  607. package/docs/examples/command-palette-adapter.tsx +69 -17
  608. package/docs/examples/component-catalog-extension.json +45 -0
  609. package/docs/examples/component-composition-extension.json +80 -0
  610. package/docs/layout.md +409 -59
  611. package/docs/nav-stack.md +126 -14
  612. package/docs/recipes.md +137 -54
  613. package/docs/split-view.md +69 -6
  614. package/docs/sunken-panel.md +58 -0
  615. package/docs/surface-scaffold.md +25 -0
  616. package/docs/tab-scaffold.md +94 -10
  617. package/docs/type-contracts.md +134 -0
  618. package/docs/ui-analyzer.md +306 -0
  619. package/docs/ui-doctor.md +107 -0
  620. package/docs/ui-evaluator.md +139 -0
  621. package/docs/ux-demo.md +40 -16
  622. package/docs/webawesome-theme.md +175 -16
  623. package/docs/workbench.md +534 -12
  624. package/doctor/cli.mjs +115 -0
  625. package/doctor/config.schema.json +68 -0
  626. package/doctor/eslint-diagnostics.d.mts +24 -0
  627. package/doctor/eslint-diagnostics.mjs +24 -0
  628. package/doctor/index.d.mts +116 -0
  629. package/doctor/index.mjs +1277 -0
  630. package/doctor/report.schema.json +118 -0
  631. package/evaluator/cli.mjs +89 -0
  632. package/evaluator/index.d.mts +90 -0
  633. package/evaluator/index.mjs +1203 -0
  634. package/evaluator/report.schema.json +152 -0
  635. package/llms.txt +423 -42
  636. package/package.json +241 -37
  637. package/traversal-exclusions.mjs +27 -0
  638. package/ux-demo/recipes/app-shell.tsx +205 -17
  639. package/ux-demo/recipes/collapsible-sidebar.tsx +260 -0
  640. package/ux-demo/recipes/compact-toolbar.tsx +135 -14
  641. package/ux-demo/recipes/composer-form.tsx +133 -21
  642. package/ux-demo/recipes/list-detail-dialog.tsx +282 -0
  643. package/ux-demo/recipes/list-workspace-states.tsx +183 -11
  644. package/ux-demo/recipes/loaders.ts +15 -5
  645. package/ux-demo/recipes/loading-inspector.tsx +204 -0
  646. package/ux-demo/recipes/mount-recipe.ts +28 -10
  647. package/ux-demo/recipes/navigation-sidebar.tsx +139 -13
  648. package/ux-demo/recipes/navigation-stack.tsx +79 -24
  649. package/ux-demo/recipes/types.ts +23 -2
  650. package/ux-demo/recipes/workspace-header.tsx +86 -5
  651. package/dist/browser/menu-action-row.js +0 -3
  652. package/dist/browser/menu-header.js +0 -5
  653. package/dist/browser/menu-item.js +0 -3
  654. package/dist/chunk-24Z2XE6C.js +0 -10
  655. package/dist/chunk-24Z2XE6C.js.map +0 -1
  656. package/dist/chunk-2RJBFNB6.js +0 -172
  657. package/dist/chunk-2RJBFNB6.js.map +0 -1
  658. package/dist/chunk-55DATV3A.js +0 -10
  659. package/dist/chunk-55DATV3A.js.map +0 -1
  660. package/dist/chunk-56RJXPHG.js.map +0 -1
  661. package/dist/chunk-7BR3DO2A.js.map +0 -1
  662. package/dist/chunk-7LDCTU7D.js +0 -134
  663. package/dist/chunk-7LDCTU7D.js.map +0 -1
  664. package/dist/chunk-AQNKJRFH.js +0 -79
  665. package/dist/chunk-AQNKJRFH.js.map +0 -1
  666. package/dist/chunk-CTQKI2XL.js +0 -28
  667. package/dist/chunk-CTQKI2XL.js.map +0 -1
  668. package/dist/chunk-DAFFDO33.js +0 -14
  669. package/dist/chunk-DAFFDO33.js.map +0 -1
  670. package/dist/chunk-EGHL5S4P.js +0 -33
  671. package/dist/chunk-EGHL5S4P.js.map +0 -1
  672. package/dist/chunk-KZKSBUKC.js +0 -19
  673. package/dist/chunk-KZKSBUKC.js.map +0 -1
  674. package/dist/chunk-M5JRI6MN.js +0 -27
  675. package/dist/chunk-M5JRI6MN.js.map +0 -1
  676. package/dist/chunk-MBR3TYNL.js +0 -14
  677. package/dist/chunk-MBR3TYNL.js.map +0 -1
  678. package/dist/chunk-MFKMHK5W.js +0 -10
  679. package/dist/chunk-MFKMHK5W.js.map +0 -1
  680. package/dist/chunk-MQIZAD4A.js.map +0 -1
  681. package/dist/chunk-NPPD2A6O.js +0 -40
  682. package/dist/chunk-NPPD2A6O.js.map +0 -1
  683. package/dist/chunk-R6JHHBKQ.js +0 -19
  684. package/dist/chunk-R6JHHBKQ.js.map +0 -1
  685. package/dist/chunk-RBTVBGRD.js +0 -23
  686. package/dist/chunk-RBTVBGRD.js.map +0 -1
  687. package/dist/chunk-S3TPM2LP.js +0 -23
  688. package/dist/chunk-S3TPM2LP.js.map +0 -1
  689. package/dist/chunk-TRNBHPNW.js.map +0 -1
  690. package/dist/chunk-VHW5YNIB.js +0 -17
  691. package/dist/chunk-VHW5YNIB.js.map +0 -1
  692. package/dist/chunk-W2FK7ZNY.js.map +0 -1
  693. package/dist/chunk-WVPYVDXY.js +0 -15
  694. package/dist/chunk-WVPYVDXY.js.map +0 -1
  695. package/dist/chunk-XZXRLY5Q.js +0 -33
  696. package/dist/chunk-XZXRLY5Q.js.map +0 -1
  697. package/dist/menu-action-row.d.ts +0 -50
  698. package/dist/menu-action-row.js +0 -4
  699. package/dist/menu-action-row.js.map +0 -1
  700. package/dist/menu-header.d.ts +0 -41
  701. package/dist/menu-header.js +0 -6
  702. package/dist/menu-header.js.map +0 -1
  703. package/dist/menu-item.d.ts +0 -31
  704. package/dist/menu-item.js +0 -4
  705. package/dist/menu-item.js.map +0 -1
  706. package/dist/panel-header.d.ts +0 -26
  707. package/dist/panel-header.js +0 -6
  708. package/dist/panel-header.js.map +0 -1
  709. package/dist/styles/menu-action-row.css +0 -160
  710. package/dist/styles/menu-header.css +0 -160
  711. package/dist/styles/menu-item.css +0 -123
  712. package/dist/styles/panel-header.css +0 -59
  713. package/ux-demo/recipes/master-detail-dialog.tsx +0 -45
  714. package/ux-demo/recipes/recipes.css +0 -355
@@ -1,43 +1,164 @@
1
1
  import '@kerfjs/ui/layout.css';
2
2
  import '@kerfjs/ui/select/register';
3
- import './recipes.css';
4
3
 
4
+ import { deviceClass } from '@kerfjs/ui/device-class';
5
+ import { Grid } from '@kerfjs/ui/grid';
6
+ import { List } from '@kerfjs/ui/list';
7
+ import { ListInsetText } from '@kerfjs/ui/list-inset-text';
5
8
  import { LucideIcon } from '@kerfjs/ui/lucide-icon';
6
9
  import { SegmentedControl } from '@kerfjs/ui/segmented-control';
7
10
  import { Select } from '@kerfjs/ui/select';
11
+ import { Text } from '@kerfjs/ui/text';
8
12
  import { Toolbar } from '@kerfjs/ui/toolbar';
9
13
  import { ToolbarControlGroup } from '@kerfjs/ui/toolbar-control-group';
10
14
  import { ToolbarText } from '@kerfjs/ui/toolbar-text';
11
15
  import { signal } from 'kerfjs';
12
16
  import { Filter, MoreHorizontal, RefreshCw } from 'lucide';
13
17
 
14
- import type { RecipeFactory } from './types.js';
18
+ import type { RecipeFactory, RecipePresentation } from './types.js';
19
+
20
+ const guide = [
21
+ ['ToolbarControlGroup', 'Related commands or pressed tools.'],
22
+ ['SegmentedControl', 'A few visible exclusive choices.'],
23
+ ['Select', 'A longer controlled value list.'],
24
+ ['Ordinary button', 'One independent command.'],
25
+ ] as const;
26
+
27
+ export const presentation: RecipePresentation = {
28
+ viewport: {
29
+ width: 'full',
30
+ frame: 'solid',
31
+ surface: 'default',
32
+ overflow: 'hidden',
33
+ shadow: true,
34
+ },
35
+ note: 'The recipe owns control semantics and wrapping. The app owns values, actions, persistence, and responsive priority.',
36
+ };
15
37
 
16
38
  export const createRecipe: RecipeFactory = (announce) => {
17
39
  const view = signal('list');
18
40
  const sort = signal('updated');
19
41
  const filtered = signal(false);
20
- const render = () => <section class="kui-recipe recipe-compact-toolbar kui-recipe__surface kui-layout" data-recipe="recipe-compact-toolbar">
21
- <Toolbar
22
- label="Task workspace controls"
23
- leading={<ToolbarControlGroup appearance="borderless" single><ToolbarText text="Tasks" size="small" /></ToolbarControlGroup>}
24
- center={<ToolbarControlGroup><SegmentedControl id="recipe-view" label="View" value={view.value} action="recipe-action" appearance="toolbar" shape="pill" size="small" choices={[{ value: 'list', label: 'List' }, { value: 'board', label: 'Board' }, { value: 'timeline', label: 'Timeline' }]} /></ToolbarControlGroup>}
25
- trailing={<div class="kui-control-cluster"><Select name="recipe-sort" value={sort.value} ariaLabel="Sort tasks" fitMenu choices={[{ value: 'updated', label: 'Recently updated' }, { value: 'priority', label: 'Priority' }, { value: 'owner', label: 'Owner' }, { value: 'created', label: 'Created date' }]} /><ToolbarControlGroup label="Task actions" buttonAppearance="push"><button type="button" aria-label="Toggle filters" aria-pressed={String(filtered.value)} data-action="recipe-action" data-recipe-command="filter"><LucideIcon icon={Filter} name="filter" /></button><button type="button" aria-label="Refresh tasks" data-action="recipe-action" data-recipe-command="refresh"><LucideIcon icon={RefreshCw} name="refresh-cw" /></button></ToolbarControlGroup><button class="kui-recipe__button" type="button" aria-label="More task actions" data-action="recipe-action" data-recipe-command="more"><LucideIcon icon={MoreHorizontal} name="more-horizontal" /></button></div>}
26
- />
27
- <div class="recipe-compact-toolbar__guide kui-content-item"><div><strong>ToolbarControlGroup</strong><span class="kui-recipe__muted">Related commands or pressed tools.</span></div><div><strong>SegmentedControl</strong><span class="kui-recipe__muted">A few visible exclusive choices.</span></div><div><strong>Select</strong><span class="kui-recipe__muted">A longer controlled value list.</span></div><div><strong>Ordinary button</strong><span class="kui-recipe__muted">One independent command.</span></div></div>
28
- <p class="kui-recipe__ownership kui-content-item">The recipe owns control semantics and wrapping. The app owns values, actions, persistence, and responsive priority.</p>
29
- </section>;
42
+ const device = deviceClass();
43
+ const render = () => (
44
+ <section data-recipe="recipe-compact-toolbar" aria-label="Task workspace">
45
+ <List gap="l" controlInsets="b">
46
+ <Toolbar
47
+ label="Task workspace controls"
48
+ responsive="stack"
49
+ responsiveAt="compact"
50
+ leading={<ToolbarText text="Tasks" size="small" />}
51
+ center={
52
+ <ToolbarControlGroup>
53
+ <SegmentedControl<string>
54
+ id="recipe-view"
55
+ label="View"
56
+ value={view.value}
57
+ action="recipe-action"
58
+ appearance="toolbar"
59
+ shape="pill"
60
+ size="small"
61
+ choices={[
62
+ { value: 'list', label: 'List' },
63
+ { value: 'board', label: 'Board' },
64
+ { value: 'timeline', label: 'Timeline' },
65
+ ]}
66
+ />
67
+ </ToolbarControlGroup>
68
+ }
69
+ trailing={
70
+ <>
71
+ <ToolbarControlGroup single focusRing="outline">
72
+ <Select<string>
73
+ name="recipe-sort"
74
+ value={sort.value}
75
+ ariaLabel="Sort tasks"
76
+ fitMenu
77
+ presentation="toolbar-borderless"
78
+ size="compact"
79
+ focusRingOwner="group"
80
+ choices={[
81
+ { value: 'updated', label: 'Recently updated' },
82
+ { value: 'priority', label: 'Priority' },
83
+ { value: 'owner', label: 'Owner' },
84
+ { value: 'created', label: 'Created date' },
85
+ ]}
86
+ />
87
+ </ToolbarControlGroup>
88
+ <ToolbarControlGroup label="Task actions" buttonAppearance="push">
89
+ <button
90
+ type="button"
91
+ aria-label="Toggle filters"
92
+ aria-pressed={String(filtered.value)}
93
+ data-action="recipe-action"
94
+ data-recipe-command="filter"
95
+ >
96
+ <LucideIcon icon={Filter} name="filter" />
97
+ </button>
98
+ <button
99
+ type="button"
100
+ aria-label="Refresh tasks"
101
+ data-action="recipe-action"
102
+ data-recipe-command="refresh"
103
+ >
104
+ <LucideIcon icon={RefreshCw} name="refresh-cw" />
105
+ </button>
106
+ </ToolbarControlGroup>
107
+ <ToolbarControlGroup label="More task actions" single>
108
+ <button
109
+ type="button"
110
+ aria-label="More task actions"
111
+ data-action="recipe-action"
112
+ data-recipe-command="more"
113
+ >
114
+ <LucideIcon icon={MoreHorizontal} name="more-horizontal" />
115
+ </button>
116
+ </ToolbarControlGroup>
117
+ </>
118
+ }
119
+ />
120
+ <Grid
121
+ columns={
122
+ device.value.compact ? 1 : device.value.atLeast('desktop') ? 4 : 2
123
+ }
124
+ gap="none"
125
+ >
126
+ {guide.map(([name, use]) => (
127
+ <ListInsetText>
128
+ <List gap="2xs">
129
+ <Text variant="span">
130
+ <strong>{name}</strong>
131
+ </Text>
132
+ <Text variant="span" tone="quiet" size="compact">
133
+ {use}
134
+ </Text>
135
+ </List>
136
+ </ListInsetText>
137
+ ))}
138
+ </Grid>
139
+ </List>
140
+ </section>
141
+ );
30
142
  return {
31
143
  render,
32
144
  action(command, element) {
33
145
  const value = element.dataset.segmentValue;
34
146
  if (value) view.value = value;
35
147
  if (command === 'filter') filtered.value = !filtered.value;
36
- announce(value ? `View: ${value}` : command === 'filter' ? `Filters ${filtered.value ? 'on' : 'off'}` : `${command} requested`);
148
+ announce(
149
+ value
150
+ ? `View: ${value}`
151
+ : command === 'filter'
152
+ ? `Filters ${filtered.value ? 'on' : 'off'}`
153
+ : `${command} requested`,
154
+ );
37
155
  },
38
156
  change(element) {
39
157
  const value = (element as HTMLElement & { value?: string }).value;
40
- if (element.getAttribute('name') === 'recipe-sort' && value) { sort.value = value; announce(`Sort: ${value}`); }
158
+ if (element.getAttribute('name') === 'recipe-sort' && value) {
159
+ sort.value = value;
160
+ announce(`Sort: ${value}`);
161
+ }
41
162
  },
42
163
  };
43
164
  };
@@ -4,19 +4,40 @@ import '@kerfjs/ui/webawesome.css';
4
4
  import '@awesome.me/webawesome/dist/components/button/button.js';
5
5
  import '@awesome.me/webawesome/dist/components/input/input.js';
6
6
  import '@awesome.me/webawesome/dist/components/textarea/textarea.js';
7
- import './recipes.css';
8
7
 
9
- import { PanelHeader } from '@kerfjs/ui/panel-header';
8
+ import { Spacer } from '@kerfjs/ui';
9
+ import { List } from '@kerfjs/ui/list';
10
+ import { ListInsetText } from '@kerfjs/ui/list-inset-text';
11
+ import { Row } from '@kerfjs/ui/row';
10
12
  import { Select } from '@kerfjs/ui/select';
11
13
  import { StateBanner } from '@kerfjs/ui/state-banner';
14
+ import { Text } from '@kerfjs/ui/text';
15
+ import { Toolbar } from '@kerfjs/ui/toolbar';
16
+ import { ToolbarText } from '@kerfjs/ui/toolbar-text';
12
17
  import { signal } from 'kerfjs';
13
18
 
14
- import type { RecipeFactory } from './types.js';
19
+ import type { RecipeFactory, RecipePresentation } from './types.js';
20
+
21
+ export const presentation: RecipePresentation = {
22
+ viewport: {
23
+ width: 'medium',
24
+ frame: 'solid',
25
+ surface: 'default',
26
+ overflow: 'hidden',
27
+ shadow: true,
28
+ },
29
+ note: 'The recipe owns field, message, and action rhythm. The app owns validation rules, draft persistence, permissions, and transport.',
30
+ };
15
31
 
16
32
  type ValueField = HTMLElement & { value: string };
17
33
 
18
- const syncControlledFieldValues = (action: HTMLElement, values: Record<string, string>) => {
19
- const form = action.closest<HTMLElement>('[data-recipe="recipe-composer-form"]');
34
+ const syncControlledFieldValues = (
35
+ action: HTMLElement,
36
+ values: Record<string, string>,
37
+ ) => {
38
+ const form = action.closest<HTMLElement>(
39
+ '[data-recipe="recipe-composer-form"]',
40
+ );
20
41
  if (!form) return;
21
42
  for (const [name, value] of Object.entries(values)) {
22
43
  const field = form.querySelector<ValueField>(`[name="${name}"]`);
@@ -26,20 +47,101 @@ const syncControlledFieldValues = (action: HTMLElement, values: Record<string, s
26
47
 
27
48
  export const createRecipe: RecipeFactory = (announce) => {
28
49
  const title = signal('');
29
- const body = signal('The tablet layout now keeps navigation, content, and inspector focus order aligned.');
50
+ const body = signal(
51
+ 'The tablet layout now keeps navigation, content, and inspector focus order aligned.',
52
+ );
30
53
  const audience = signal('team');
31
54
  const status = signal<'idle' | 'error' | 'saved'>('idle');
32
- const render = () => <form class="kui-recipe recipe-form kui-recipe__surface kui-content" data-recipe="recipe-composer-form" aria-labelledby="recipe-composer-title" aria-describedby="recipe-composer-summary" noValidate>
33
- <PanelHeader title="Publish workspace update" titleId="recipe-composer-title" summary="Share a concise, actionable update with collaborators." summaryId="recipe-composer-summary" />
34
- {status.value === 'error' && <StateBanner title="Add a title before publishing" detail="The update body and audience are preserved." tone="danger" urgency="alert" />}
35
- {status.value === 'saved' && <StateBanner title="Update published" detail="The team audience can now read it." tone="success" />}
36
- <div class="recipe-form__section recipe-form__fields">
37
- <wa-input name="recipe-title" label="Update title" hint="Summarize the outcome in one line." required value={title.value}></wa-input>
38
- <wa-textarea name="recipe-body" label="Details" hint="Include decisions, owners, and the next checkpoint." rows="5" maxlength="400" with-count value={body.value}></wa-textarea>
39
- <Select name="recipe-audience" value={audience.value} label="Audience" choices={[{ value: 'team', label: 'Workspace team' }, { value: 'reviewers', label: 'Reviewers' }, { value: 'organization', label: 'Entire organization' }]} />
40
- </div>
41
- <footer class="recipe-form__section recipe-form__footer"><div class="recipe-form__actions kui-control-cluster"><wa-button appearance="outlined" data-action="recipe-action" data-recipe-command="reset">Reset</wa-button><wa-button variant="brand" appearance="accent" data-action="recipe-action" data-recipe-command="submit">Publish update</wa-button></div><p class="kui-recipe__ownership">The recipe owns field, message, and action rhythm. The app owns validation rules, draft persistence, permissions, and transport.</p></footer>
42
- </form>;
55
+ const render = () => (
56
+ <form
57
+ data-recipe="recipe-composer-form"
58
+ aria-labelledby="recipe-composer-title"
59
+ aria-describedby="recipe-composer-summary"
60
+ noValidate
61
+ >
62
+ <List gap="l" controlInsets="tb">
63
+ {/* The title and its supporting line are one heading unit. */}
64
+ <List>
65
+ <Toolbar
66
+ label="Publish workspace update"
67
+ leading={
68
+ <ToolbarText
69
+ text="Publish workspace update"
70
+ size="xlarge"
71
+ id="recipe-composer-title"
72
+ />
73
+ }
74
+ />
75
+ <ListInsetText sides="rl">
76
+ <Text variant="span" tone="quiet" id="recipe-composer-summary">
77
+ Share a concise, actionable update with collaborators.
78
+ </Text>
79
+ </ListInsetText>
80
+ </List>
81
+ {status.value === 'error' && (
82
+ <StateBanner
83
+ title="Add a title before publishing"
84
+ detail="The update body and audience are preserved."
85
+ tone="danger"
86
+ urgency="alert"
87
+ />
88
+ )}
89
+ {status.value === 'saved' && (
90
+ <StateBanner
91
+ title="Update published"
92
+ detail="The team audience can now read it."
93
+ tone="success"
94
+ />
95
+ )}
96
+ <List gap="xs" controlInsets="rl">
97
+ <wa-input
98
+ name="recipe-title"
99
+ label="Update title"
100
+ hint="Summarize the outcome in one line."
101
+ required
102
+ value={title.value}
103
+ ></wa-input>
104
+ <wa-textarea
105
+ name="recipe-body"
106
+ label="Details"
107
+ hint="Include decisions, owners, and the next checkpoint."
108
+ rows="5"
109
+ maxlength="400"
110
+ with-count
111
+ value={body.value}
112
+ ></wa-textarea>
113
+ <Select<string>
114
+ name="recipe-audience"
115
+ value={audience.value}
116
+ label="Audience"
117
+ choices={[
118
+ { value: 'team', label: 'Workspace team' },
119
+ { value: 'reviewers', label: 'Reviewers' },
120
+ { value: 'organization', label: 'Entire organization' },
121
+ ]}
122
+ />
123
+ </List>
124
+ <Row gap="xs" wrap controlInsets="rl">
125
+ <Spacer flex />
126
+ <wa-button
127
+ appearance="outlined"
128
+ data-action="recipe-action"
129
+ data-recipe-command="reset"
130
+ >
131
+ Reset
132
+ </wa-button>
133
+ <wa-button
134
+ variant="brand"
135
+ appearance="accent"
136
+ data-action="recipe-action"
137
+ data-recipe-command="submit"
138
+ >
139
+ Publish update
140
+ </wa-button>
141
+ </Row>
142
+ </List>
143
+ </form>
144
+ );
43
145
  return {
44
146
  render,
45
147
  action(command, element) {
@@ -47,17 +149,27 @@ export const createRecipe: RecipeFactory = (announce) => {
47
149
  title.value = '';
48
150
  body.value = '';
49
151
  status.value = 'idle';
50
- syncControlledFieldValues(element, { 'recipe-title': title.value, 'recipe-body': body.value });
152
+ syncControlledFieldValues(element, {
153
+ 'recipe-title': title.value,
154
+ 'recipe-body': body.value,
155
+ });
51
156
  announce('Draft reset');
52
157
  return;
53
158
  }
54
- if (command === 'submit') { status.value = title.value.trim() ? 'saved' : 'error'; announce(status.value === 'saved' ? 'Update published' : 'Title required'); }
159
+ if (command === 'submit') {
160
+ status.value = title.value.trim() ? 'saved' : 'error';
161
+ announce(
162
+ status.value === 'saved' ? 'Update published' : 'Title required',
163
+ );
164
+ }
55
165
  },
56
166
  change(element) {
57
- const value = (element as HTMLElement & { value?: string | null }).value ?? '';
167
+ const value =
168
+ (element as HTMLElement & { value?: string | null }).value ?? '';
58
169
  if (element.getAttribute('name') === 'recipe-title') title.value = value;
59
170
  if (element.getAttribute('name') === 'recipe-body') body.value = value;
60
- if (element.getAttribute('name') === 'recipe-audience') audience.value = value;
171
+ if (element.getAttribute('name') === 'recipe-audience')
172
+ audience.value = value;
61
173
  },
62
174
  };
63
175
  };
@@ -0,0 +1,282 @@
1
+ import '@kerfjs/ui/layout.css';
2
+ import '@kerfjs/ui/nav-stack.css';
3
+ import '@kerfjs/ui/split-view.css';
4
+ import '@kerfjs/ui/webawesome.css';
5
+ import '@awesome.me/webawesome/dist/components/button/button.js';
6
+ import '@awesome.me/webawesome/dist/components/dialog/dialog.js';
7
+
8
+ import { deviceClass } from '@kerfjs/ui/device-class';
9
+ import { List } from '@kerfjs/ui/list';
10
+ import { ListItem } from '@kerfjs/ui/list-item';
11
+ import { LucideIcon } from '@kerfjs/ui/lucide-icon';
12
+ import { Pane } from '@kerfjs/ui/pane';
13
+ import { Row } from '@kerfjs/ui/row';
14
+ import { Spacer } from '@kerfjs/ui/spacer';
15
+ import { SplitView } from '@kerfjs/ui/split-view';
16
+ import { DialogSurface } from '@kerfjs/ui/surface-scaffold';
17
+ import { Toolbar } from '@kerfjs/ui/toolbar';
18
+ import { ToolbarControlGroup } from '@kerfjs/ui/toolbar-control-group';
19
+ import { ToolbarText } from '@kerfjs/ui/toolbar-text';
20
+ import { ValueTable, ValueTableRow } from '@kerfjs/ui/value-table';
21
+ import { signal } from 'kerfjs';
22
+ import { ChevronRight, FileText, X } from 'lucide';
23
+
24
+ import type { RecipeFactory, RecipePresentation } from './types.js';
25
+
26
+ const records = {
27
+ alpha: {
28
+ name: 'Northstar migration',
29
+ owner: 'Mara Chen',
30
+ state: 'In review',
31
+ updated: 'Today, 09:42',
32
+ },
33
+ beta: {
34
+ name: 'Tablet navigation',
35
+ owner: 'Sam Rivera',
36
+ state: 'Ready',
37
+ updated: 'Yesterday, 16:20',
38
+ },
39
+ gamma: {
40
+ name: 'Contrast audit',
41
+ owner: 'Inez Okafor',
42
+ state: 'Blocked',
43
+ updated: 'Monday, 11:05',
44
+ },
45
+ } as const;
46
+
47
+ type RecordId = keyof typeof records;
48
+
49
+ interface RecipeDialogElement extends HTMLElement {
50
+ open: boolean;
51
+ }
52
+
53
+ export const presentation: RecipePresentation = {
54
+ viewport: { layout: 'grid', width: 'full' },
55
+ note: 'On roomy devices the dialog body is a workbench: a full-height list sidebar with its own toolbar beside a full-height detail column that carries the primary title, close control, and record actions. Compact devices get a full-screen sheet that drills from the list into the detail. Web Awesome owns modal focus and Escape; DialogSurface owns dialog geometry; SplitView owns the panes and the compact drill-down. The app owns open state, selection, and record actions.',
56
+ };
57
+
58
+ export const createRecipe: RecipeFactory = (announce) => {
59
+ const selected = signal<RecordId>('alpha');
60
+ // Compact devices drill from the list into the detail; this flag is the
61
+ // pushed detail view. Roomy devices show both panes side by side.
62
+ const detailOpen = signal(false);
63
+ const open = { value: false };
64
+ const device = deviceClass();
65
+
66
+ const projectRows = (compact: boolean) => (
67
+ <section aria-label="Projects">
68
+ {Object.entries(records).map(([id, record]) => (
69
+ <ListItem
70
+ action="recipe-action"
71
+ itemId={id}
72
+ label={record.name}
73
+ description={`${record.owner} · ${record.state}`}
74
+ icon={<LucideIcon icon={FileText} name="file-text" />}
75
+ trailing={
76
+ compact ? (
77
+ <LucideIcon icon={ChevronRight} name="chevron-right" />
78
+ ) : undefined
79
+ }
80
+ selected={!compact && selected.value === id}
81
+ multiline
82
+ />
83
+ ))}
84
+ </section>
85
+ );
86
+
87
+ const recordActions = () => (
88
+ <Row gap="xs" wrap controlInsets="trbl">
89
+ <Spacer flex />
90
+ <wa-button
91
+ appearance="outlined"
92
+ data-action="recipe-action"
93
+ data-recipe-command="archive"
94
+ >
95
+ Archive
96
+ </wa-button>
97
+ <wa-button
98
+ variant="brand"
99
+ appearance="accent"
100
+ data-action="recipe-action"
101
+ data-recipe-command="open-record"
102
+ >
103
+ Open project
104
+ </wa-button>
105
+ </Row>
106
+ );
107
+
108
+ // Roomy: a workbench. The list is a full-height sidebar with its own top
109
+ // toolbar; the detail column carries the dialog's primary title, the close
110
+ // control, and the record actions, and runs the full dialog height too.
111
+ const sidebar = () => (
112
+ <Pane
113
+ label="Recent projects"
114
+ header={
115
+ <Toolbar
116
+ label="Recent projects"
117
+ leading={<ToolbarText text="Recent projects" />}
118
+ />
119
+ }
120
+ >
121
+ <List controlInsets="tb">{projectRows(false)}</List>
122
+ </Pane>
123
+ );
124
+
125
+ const detailColumn = () => {
126
+ const record = records[selected.value];
127
+ return (
128
+ <Pane
129
+ label={record.name}
130
+ header={
131
+ <Toolbar
132
+ label="Project details"
133
+ leading={
134
+ <ToolbarText
135
+ text={record.name}
136
+ size="xlarge"
137
+ id="recipe-project-title"
138
+ headingLevel={2}
139
+ />
140
+ }
141
+ trailing={
142
+ <ToolbarControlGroup appearance="borderless" single>
143
+ <button type="button" aria-label="Close" data-dialog="close">
144
+ <LucideIcon icon={X} name="x" />
145
+ </button>
146
+ </ToolbarControlGroup>
147
+ }
148
+ />
149
+ }
150
+ footer={recordActions()}
151
+ >
152
+ <List controlInsets="tb">
153
+ <ValueTable label="Project details">
154
+ <ValueTableRow label="Owner" value={record.owner} />
155
+ <ValueTableRow label="Status" value={record.state} />
156
+ <ValueTableRow label="Updated" value={record.updated} />
157
+ </ValueTable>
158
+ </List>
159
+ </Pane>
160
+ );
161
+ };
162
+
163
+ const compactDetail = () => {
164
+ const record = records[selected.value];
165
+ return (
166
+ <List>
167
+ <ValueTable label="Project details">
168
+ <ValueTableRow label="Owner" value={record.owner} />
169
+ <ValueTableRow label="Status" value={record.state} />
170
+ <ValueTableRow label="Updated" value={record.updated} />
171
+ </ValueTable>
172
+ </List>
173
+ );
174
+ };
175
+
176
+ const render = () => {
177
+ const compact = device.value.compact;
178
+ return (
179
+ <section
180
+ data-recipe="recipe-list-detail-dialog"
181
+ aria-label="Project details dialog"
182
+ >
183
+ <Row hAlign="center">
184
+ <DialogSurface
185
+ size="large"
186
+ presentation={compact ? 'fullscreen' : 'modal'}
187
+ bodyInset="none"
188
+ footerInset="comfortable"
189
+ >
190
+ <wa-button
191
+ variant="brand"
192
+ appearance="accent"
193
+ data-action="recipe-action"
194
+ data-recipe-command="open"
195
+ >
196
+ Open project details
197
+ </wa-button>
198
+ {compact ? (
199
+ <wa-dialog label="Project details" open={open.value} with-footer>
200
+ <SplitView
201
+ id="recipe-projects"
202
+ label="Projects"
203
+ compact
204
+ detailActive={detailOpen.value}
205
+ listTitle="Recent projects"
206
+ detailTitle={records[selected.value].name}
207
+ backLabel="Back to projects"
208
+ list={<List>{projectRows(true)}</List>}
209
+ detail={compactDetail()}
210
+ />
211
+ <wa-button
212
+ slot="footer"
213
+ appearance="outlined"
214
+ data-action="recipe-action"
215
+ data-recipe-command="archive"
216
+ >
217
+ Archive
218
+ </wa-button>
219
+ <wa-button
220
+ slot="footer"
221
+ variant="brand"
222
+ appearance="accent"
223
+ data-action="recipe-action"
224
+ data-recipe-command="open-record"
225
+ >
226
+ Open project
227
+ </wa-button>
228
+ </wa-dialog>
229
+ ) : (
230
+ <wa-dialog
231
+ label="Project details"
232
+ open={open.value}
233
+ without-header
234
+ >
235
+ <SplitView
236
+ id="recipe-projects"
237
+ label="Projects"
238
+ compact={false}
239
+ listTitle="Recent projects"
240
+ detailTitle={records[selected.value].name}
241
+ list={sidebar()}
242
+ detail={detailColumn()}
243
+ />
244
+ </wa-dialog>
245
+ )}
246
+ </DialogSurface>
247
+ </Row>
248
+ </section>
249
+ );
250
+ };
251
+ return {
252
+ render,
253
+ action(command, element) {
254
+ if (command === 'nav-back') {
255
+ detailOpen.value = false;
256
+ announce('Back to projects');
257
+ return;
258
+ }
259
+ const id = element.dataset.itemId;
260
+ if (id && id in records) {
261
+ selected.value = id as RecordId;
262
+ detailOpen.value = true;
263
+ announce(`Selected ${records[selected.value].name}`);
264
+ return;
265
+ }
266
+ const dialog = element
267
+ .closest('[data-recipe]')
268
+ ?.querySelector<RecipeDialogElement>('wa-dialog');
269
+ if (command === 'open' && dialog) {
270
+ element.focus();
271
+ open.value = true;
272
+ dialog.open = true;
273
+ return;
274
+ }
275
+ announce(`${command} requested`);
276
+ },
277
+ afterHide() {
278
+ open.value = false;
279
+ detailOpen.value = false;
280
+ },
281
+ };
282
+ };