@kerfjs/ui 5.0.0-beta.98 → 5.0.0-beta.99

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 (407) hide show
  1. package/README.md +42 -1
  2. package/ai/application-ui-diagnostic-ids-v1.json +1 -0
  3. package/ai/component-catalog.json +487 -66
  4. package/ai/component-catalog.schema.json +1 -1
  5. package/ai/component-composition-rules.json +22 -2
  6. package/ai/component-composition.json +360 -33
  7. package/ai/component-composition.schema.json +1 -1
  8. package/ai/components/README.md +18 -17
  9. package/ai/components/anchored-surface.md +13 -0
  10. package/ai/components/application-tabs.md +1 -1
  11. package/ai/components/chip.md +9 -5
  12. package/ai/components/choice-chips.md +15 -8
  13. package/ai/components/collapsible-panel.md +3 -2
  14. package/ai/components/composer.md +83 -0
  15. package/ai/components/content-item.md +2 -2
  16. package/ai/components/corner-status.md +1 -1
  17. package/ai/components/document-baseline.md +3 -3
  18. package/ai/components/foundation.md +2 -2
  19. package/ai/components/layout.md +1 -1
  20. package/ai/components/list-action-row.md +5 -1
  21. package/ai/components/list-item.md +5 -1
  22. package/ai/components/list.md +19 -3
  23. package/ai/components/nav-stack.md +11 -2
  24. package/ai/components/pane.md +13 -4
  25. package/ai/components/popup-menu.md +4 -4
  26. package/ai/components/recipe-app-shell.md +3 -3
  27. package/ai/components/recipe-collapsible-sidebar.md +3 -3
  28. package/ai/components/recipe-compact-toolbar.md +1 -1
  29. package/ai/components/recipe-composer-form.md +3 -3
  30. package/ai/components/recipe-list-detail-dialog.md +2 -2
  31. package/ai/components/recipe-list-workspace-states.md +3 -3
  32. package/ai/components/recipe-loading-inspector.md +1 -1
  33. package/ai/components/recipe-navigation-sidebar.md +3 -3
  34. package/ai/components/recipe-navigation-stack.md +3 -3
  35. package/ai/components/recipe-workspace-header.md +3 -3
  36. package/ai/components/resize.md +2 -2
  37. package/ai/components/split-view.md +4 -2
  38. package/ai/components/sunken-panel.md +2 -2
  39. package/ai/components/surface-scaffold.md +15 -3
  40. package/ai/components/tab-bar.md +1 -0
  41. package/ai/components/tab-navigator.md +4 -0
  42. package/ai/components/toolbar-control-group.md +2 -0
  43. package/ai/components/toolbar-text.md +1 -0
  44. package/ai/components/toolbar.md +1 -0
  45. package/ai/components/workbench.md +1 -0
  46. package/ai/public-api-signatures-v1.md +487 -77
  47. package/ai/skill.md +40 -13
  48. package/ai/webawesome-jsx-signatures-v1.md +1 -1
  49. package/analyzer/component-ownership.mjs +1 -1
  50. package/analyzer/index.mjs +41 -14
  51. package/dist/anchored-surface.d.ts +30 -2
  52. package/dist/anchored-surface.js +1 -1
  53. package/dist/app-tab.js +1 -1
  54. package/dist/browser/composer.js +4 -0
  55. package/dist/catalog-resources.d.ts +3 -2
  56. package/dist/catalog-resources.js +4 -4
  57. package/dist/catalog-resources.js.map +1 -1
  58. package/dist/catalog.d.ts +22 -5
  59. package/dist/catalog.js +50 -31
  60. package/dist/catalog.js.map +1 -1
  61. package/dist/chip.d.ts +41 -9
  62. package/dist/chip.js +1 -1
  63. package/dist/choice-chips.d.ts +40 -16
  64. package/dist/choice-chips.js +1 -1
  65. package/dist/chunk-34U4ANDJ.js +119 -0
  66. package/dist/chunk-34U4ANDJ.js.map +1 -0
  67. package/dist/{chunk-36TL6BCR.js → chunk-3GLYIIFR.js} +34 -6
  68. package/dist/chunk-3GLYIIFR.js.map +1 -0
  69. package/dist/{chunk-HWY4BSLS.js → chunk-3VXDSIBJ.js} +2 -2
  70. package/dist/{chunk-HWY4BSLS.js.map → chunk-3VXDSIBJ.js.map} +1 -1
  71. package/dist/chunk-3WYREXW4.js +120 -0
  72. package/dist/chunk-3WYREXW4.js.map +1 -0
  73. package/dist/chunk-AV7CPAPT.js +82 -0
  74. package/dist/chunk-AV7CPAPT.js.map +1 -0
  75. package/dist/{chunk-XK4E225T.js → chunk-B53PS2LE.js} +2 -2
  76. package/dist/{chunk-XK4E225T.js.map → chunk-B53PS2LE.js.map} +1 -1
  77. package/dist/{chunk-R42D2BAO.js → chunk-CA7LNX3J.js} +2 -2
  78. package/dist/{chunk-R42D2BAO.js.map → chunk-CA7LNX3J.js.map} +1 -1
  79. package/dist/{chunk-AZWE2FB5.js → chunk-CMETHPKR.js} +12 -15
  80. package/dist/chunk-CMETHPKR.js.map +1 -0
  81. package/dist/{chunk-Y43B6DS3.js → chunk-CVD5IZGB.js} +2 -2
  82. package/dist/{chunk-Y43B6DS3.js.map → chunk-CVD5IZGB.js.map} +1 -1
  83. package/dist/{chunk-6STQXRT4.js → chunk-CXZXHZTR.js} +121 -12
  84. package/dist/chunk-CXZXHZTR.js.map +1 -0
  85. package/dist/{chunk-GZE2XVKC.js → chunk-DZJ4GBSP.js} +3 -3
  86. package/dist/{chunk-GZE2XVKC.js.map → chunk-DZJ4GBSP.js.map} +1 -1
  87. package/dist/chunk-ELCMSQNJ.js +49 -0
  88. package/dist/chunk-ELCMSQNJ.js.map +1 -0
  89. package/dist/{chunk-P74VXMB6.js → chunk-EOO6PYGF.js} +7 -14
  90. package/dist/chunk-EOO6PYGF.js.map +1 -0
  91. package/dist/{chunk-PRG4CL3Q.js → chunk-FR76ZJQC.js} +21 -19
  92. package/dist/chunk-FR76ZJQC.js.map +1 -0
  93. package/dist/{chunk-QQ3TTWFH.js → chunk-G3J7JDP6.js} +1 -1
  94. package/dist/{chunk-QQ3TTWFH.js.map → chunk-G3J7JDP6.js.map} +1 -1
  95. package/dist/{chunk-IGTWXPTN.js → chunk-HGV7J4T6.js} +3 -3
  96. package/dist/{chunk-IGTWXPTN.js.map → chunk-HGV7J4T6.js.map} +1 -1
  97. package/dist/{chunk-YWQGSUF2.js → chunk-HLDRH23D.js} +3 -3
  98. package/dist/{chunk-YWQGSUF2.js.map → chunk-HLDRH23D.js.map} +1 -1
  99. package/dist/{chunk-PBT3CPPY.js → chunk-HQZYKJ56.js} +24 -4
  100. package/dist/chunk-HQZYKJ56.js.map +1 -0
  101. package/dist/{chunk-V6W56V3N.js → chunk-HZPHCSCS.js} +16 -3
  102. package/dist/chunk-HZPHCSCS.js.map +1 -0
  103. package/dist/{chunk-GJYQ27C2.js → chunk-INI4WDWC.js} +8 -1
  104. package/dist/chunk-INI4WDWC.js.map +1 -0
  105. package/dist/{chunk-U657IHFB.js → chunk-IQSRHXZR.js} +10 -4
  106. package/dist/chunk-IQSRHXZR.js.map +1 -0
  107. package/dist/{chunk-KQDU7Z7P.js → chunk-K4AT3V3J.js} +2 -1
  108. package/dist/chunk-K4AT3V3J.js.map +1 -0
  109. package/dist/{chunk-QIAPOWHH.js → chunk-KCS6NJ3O.js} +2 -2
  110. package/dist/{chunk-QIAPOWHH.js.map → chunk-KCS6NJ3O.js.map} +1 -1
  111. package/dist/{chunk-UKKRPP56.js → chunk-LOSRXZAH.js} +2 -2
  112. package/dist/{chunk-UKKRPP56.js.map → chunk-LOSRXZAH.js.map} +1 -1
  113. package/dist/{chunk-ROZLJULF.js → chunk-MF6ZUUJZ.js} +8 -3
  114. package/dist/chunk-MF6ZUUJZ.js.map +1 -0
  115. package/dist/{chunk-6IVNMC6R.js → chunk-MHMWQ7RB.js} +2 -2
  116. package/dist/{chunk-6IVNMC6R.js.map → chunk-MHMWQ7RB.js.map} +1 -1
  117. package/dist/{chunk-JYD7G4RG.js → chunk-PIVY32AE.js} +15 -5
  118. package/dist/chunk-PIVY32AE.js.map +1 -0
  119. package/dist/{chunk-527IAEWG.js → chunk-PYBBYSZ3.js} +10 -17
  120. package/dist/chunk-PYBBYSZ3.js.map +1 -0
  121. package/dist/chunk-QDSZTQXL.js +28 -0
  122. package/dist/chunk-QDSZTQXL.js.map +1 -0
  123. package/dist/{chunk-YXOMI7ES.js → chunk-QIG4IGUP.js} +2 -2
  124. package/dist/{chunk-YXOMI7ES.js.map → chunk-QIG4IGUP.js.map} +1 -1
  125. package/dist/{chunk-6BRRUPJY.js → chunk-QROYYGWU.js} +3 -3
  126. package/dist/chunk-QROYYGWU.js.map +1 -0
  127. package/dist/{chunk-FOQK4F3L.js → chunk-RHD7RKGI.js} +28 -7
  128. package/dist/chunk-RHD7RKGI.js.map +1 -0
  129. package/dist/{chunk-BBU2SPRE.js → chunk-T4WJ5VGP.js} +4 -4
  130. package/dist/{chunk-BBU2SPRE.js.map → chunk-T4WJ5VGP.js.map} +1 -1
  131. package/dist/{chunk-6NOLL5KG.js → chunk-TGLUDQP2.js} +3 -3
  132. package/dist/{chunk-6NOLL5KG.js.map → chunk-TGLUDQP2.js.map} +1 -1
  133. package/dist/{chunk-HO6FU3G7.js → chunk-TLMMFQWM.js} +4 -4
  134. package/dist/{chunk-HO6FU3G7.js.map → chunk-TLMMFQWM.js.map} +1 -1
  135. package/dist/chunk-UMKV7YVQ.js +20 -0
  136. package/dist/chunk-UMKV7YVQ.js.map +1 -0
  137. package/dist/{chunk-M2NRCFRO.js → chunk-VFYO3UGZ.js} +2 -2
  138. package/dist/{chunk-M2NRCFRO.js.map → chunk-VFYO3UGZ.js.map} +1 -1
  139. package/dist/{chunk-YOKEL75M.js → chunk-WVS6CUCT.js} +2 -2
  140. package/dist/{chunk-YOKEL75M.js.map → chunk-WVS6CUCT.js.map} +1 -1
  141. package/dist/{chunk-MN3POJFN.js → chunk-YMUIQRWK.js} +2 -2
  142. package/dist/{chunk-MN3POJFN.js.map → chunk-YMUIQRWK.js.map} +1 -1
  143. package/dist/{chunk-Y3LC7JQO.js → chunk-YOA5W5ZH.js} +2 -2
  144. package/dist/{chunk-Y3LC7JQO.js.map → chunk-YOA5W5ZH.js.map} +1 -1
  145. package/dist/{chunk-44A6LP54.js → chunk-YQ2AC4E2.js} +2 -2
  146. package/dist/{chunk-44A6LP54.js.map → chunk-YQ2AC4E2.js.map} +1 -1
  147. package/dist/chunk-ZNROKDSZ.js +54 -0
  148. package/dist/chunk-ZNROKDSZ.js.map +1 -0
  149. package/dist/collapsible-panel.d.ts +3 -2
  150. package/dist/collapsible-panel.js +4 -3
  151. package/dist/collapsible-panel.js.map +1 -1
  152. package/dist/composer.d.ts +62 -0
  153. package/dist/composer.js +5 -0
  154. package/dist/composer.js.map +1 -0
  155. package/dist/corner-status.d.ts +1 -1
  156. package/dist/corner-status.js +1 -1
  157. package/dist/css-values.d.ts +9 -1
  158. package/dist/css-values.js +1 -1
  159. package/dist/disclosure-arrow.js +1 -1
  160. package/dist/empty-state.js +1 -1
  161. package/dist/grid.js +1 -1
  162. package/dist/icon-button.js +1 -1
  163. package/dist/icon-toggle-button.js +1 -1
  164. package/dist/index.d.ts +10 -5
  165. package/dist/index.js +40 -37
  166. package/dist/list-action-row.d.ts +10 -2
  167. package/dist/list-action-row.js +1 -1
  168. package/dist/list-header.js +1 -1
  169. package/dist/list-icon-tile-B8dr97OW.d.ts +18 -0
  170. package/dist/list-item.d.ts +10 -3
  171. package/dist/list-item.js +1 -1
  172. package/dist/list.d.ts +36 -4
  173. package/dist/list.js +1 -1
  174. package/dist/loading-spinner.js +1 -1
  175. package/dist/lucide-icon.js +1 -1
  176. package/dist/{nav-stack-Cp3Y8kJ9.d.ts → nav-stack-VXTumzKa.d.ts} +48 -3
  177. package/dist/nav-stack.d.ts +3 -2
  178. package/dist/nav-stack.js +2 -1
  179. package/dist/pane.d.ts +40 -3
  180. package/dist/pane.js +1 -1
  181. package/dist/{panel-toolbar-CL9tYOkh.d.ts → panel-toolbar-vg6Ir5Dy.d.ts} +6 -1
  182. package/dist/popup-menu-register.d.ts +2 -1
  183. package/dist/popup-menu-register.js +97 -22
  184. package/dist/popup-menu-register.js.map +1 -1
  185. package/dist/popup-menu.js +1 -1
  186. package/dist/row.js +1 -1
  187. package/dist/scroll-clearance-BikHljTc.d.ts +14 -0
  188. package/dist/select.js +1 -1
  189. package/dist/skeleton.js +1 -1
  190. package/dist/spacer.js +1 -1
  191. package/dist/split-button.js +1 -1
  192. package/dist/split-view.d.ts +7 -5
  193. package/dist/split-view.js +6 -3
  194. package/dist/split-view.js.map +1 -1
  195. package/dist/state-banner.d.ts +6 -1
  196. package/dist/state-banner.js +1 -1
  197. package/dist/styles/anchored-surface.css +27 -1
  198. package/dist/styles/catalog/components/catalog-example.css +33 -0
  199. package/dist/styles/catalog/components/catalog-stage.css +7 -0
  200. package/dist/styles/chip.css +70 -0
  201. package/dist/styles/components/actions/popup-menu/popup-menu.css +14 -4
  202. package/dist/styles/components/actions/toolbar-control-group/toolbar-control-group.css +75 -1
  203. package/dist/styles/components/actions/toolbar-text/toolbar-text.css +66 -0
  204. package/dist/styles/components/collections/list/list.css +77 -7
  205. package/dist/styles/components/collections/list-action-row/list-action-row.css +177 -22
  206. package/dist/styles/components/collections/list-item/list-item.css +158 -11
  207. package/dist/styles/components/feedback/anchored-surface/anchored-surface.css +27 -1
  208. package/dist/styles/components/feedback/chip/chip.css +70 -0
  209. package/dist/styles/components/feedback/state-banner/state-banner.css +24 -13
  210. package/dist/styles/components/forms/composer/composer.css +100 -0
  211. package/dist/styles/components/forms/token-search-field/token-search-field.css +13 -2
  212. package/dist/styles/components/layout/pane/pane.css +81 -2
  213. package/dist/styles/components/navigation/nav-stack/nav-stack.css +84 -0
  214. package/dist/styles/components/navigation/tab-bar/tab-bar.css +15 -4
  215. package/dist/styles/components/navigation/tab-navigator/tab-navigator.css +79 -4
  216. package/dist/styles/components/surfaces/surface-scaffold/surface-scaffold.css +195 -0
  217. package/dist/styles/composer.css +100 -0
  218. package/dist/styles/foundation.css +40 -0
  219. package/dist/styles/list-action-row.css +177 -22
  220. package/dist/styles/list-item.css +158 -11
  221. package/dist/styles/list.css +77 -7
  222. package/dist/styles/nav-stack.css +84 -0
  223. package/dist/styles/pane.css +81 -2
  224. package/dist/styles/popup-menu.css +14 -4
  225. package/dist/styles/state-banner.css +24 -13
  226. package/dist/styles/styles.css +1 -0
  227. package/dist/styles/surface-scaffold.css +195 -0
  228. package/dist/styles/tab-bar.css +15 -4
  229. package/dist/styles/tab-navigator.css +79 -4
  230. package/dist/styles/token-search-field.css +13 -2
  231. package/dist/styles/toolbar-control-group.css +75 -1
  232. package/dist/styles/toolbar-text.css +66 -0
  233. package/dist/surface-scaffold-register.d.ts +6 -1
  234. package/dist/surface-scaffold-register.js +89 -3
  235. package/dist/surface-scaffold-register.js.map +1 -1
  236. package/dist/surface-scaffold.d.ts +66 -7
  237. package/dist/surface-scaffold.js +1 -1
  238. package/dist/tab-navigator.d.ts +23 -2
  239. package/dist/tab-navigator.js +2 -0
  240. package/dist/tab-navigator.js.map +1 -1
  241. package/dist/token-search-field.d.ts +1 -1
  242. package/dist/token-search-field.js +1 -1
  243. package/dist/{token-search-model-DTcTXWMS.d.ts → token-search-model-aYR0YAei.d.ts} +32 -2
  244. package/dist/token-search-model.d.ts +1 -1
  245. package/dist/toolbar-control-group.js +1 -1
  246. package/dist/toolbar-text.js +1 -1
  247. package/dist/toolbar.d.ts +1 -0
  248. package/dist/value-table.js +1 -1
  249. package/dist/wire-catalog.d.ts +3 -2
  250. package/dist/wire-catalog.js +2 -2
  251. package/dist/wire-composers.d.ts +16 -0
  252. package/dist/wire-composers.js +3 -0
  253. package/dist/wire-composers.js.map +1 -0
  254. package/dist/wire-list-focus-scroll.d.ts +16 -0
  255. package/dist/wire-list-focus-scroll.js +3 -0
  256. package/dist/wire-list-focus-scroll.js.map +1 -0
  257. package/dist/wire-nav-stack.js +135 -0
  258. package/dist/wire-nav-stack.js.map +1 -1
  259. package/dist/wire-scroll-dividers.d.ts +9 -0
  260. package/dist/wire-scroll-dividers.js +1 -1
  261. package/dist/wire-tab-bars.js +1 -1
  262. package/dist/wire-tab-navigator.d.ts +3 -1
  263. package/dist/wire-tab-navigator.js +133 -1
  264. package/dist/wire-tab-navigator.js.map +1 -1
  265. package/dist/wire-token-search-fields.d.ts +1 -1
  266. package/dist/wire-token-search-fields.js +1 -1
  267. package/dist/workbench.d.ts +8 -3
  268. package/dist/workbench.js +2 -1
  269. package/docs/accessibility.md +132 -3
  270. package/docs/anchored-surface.md +46 -4
  271. package/docs/app-layouts.md +23 -2
  272. package/docs/apple-hig.md +1 -0
  273. package/docs/catalog.md +54 -8
  274. package/docs/collapsible-panel.md +9 -6
  275. package/docs/component-contract.md +41 -12
  276. package/docs/component-selection.md +143 -19
  277. package/docs/composer.md +143 -0
  278. package/docs/design/templates/choice-chips/multiple-dark.svg +1 -0
  279. package/docs/design/templates/choice-chips/multiple.svg +1 -0
  280. package/docs/design/templates/choice-chips-dark.svg +1 -1
  281. package/docs/design/templates/choice-chips.svg +1 -1
  282. package/docs/design/templates/composer/chat-dark.svg +1 -0
  283. package/docs/design/templates/composer/chat.svg +1 -0
  284. package/docs/design/templates/composer/prompt-dark.svg +1 -0
  285. package/docs/design/templates/composer/prompt.svg +1 -0
  286. package/docs/design/templates/composer-dark.svg +1 -0
  287. package/docs/design/templates/composer.svg +1 -0
  288. package/docs/design/templates/empty-state/filtered-dark.svg +1 -1
  289. package/docs/design/templates/empty-state/filtered.svg +1 -1
  290. package/docs/design/templates/empty-state/with-action-dark.svg +1 -1
  291. package/docs/design/templates/empty-state/with-action.svg +1 -1
  292. package/docs/design/templates/empty-state-dark.svg +1 -1
  293. package/docs/design/templates/empty-state.svg +1 -1
  294. package/docs/design/templates/list/compact-dark.svg +1 -1
  295. package/docs/design/templates/list/compact.svg +1 -1
  296. package/docs/design/templates/list-action-row/default-dark.svg +1 -1
  297. package/docs/design/templates/list-action-row/default.svg +1 -1
  298. package/docs/design/templates/list-action-row/icon-tile-dark.svg +1 -0
  299. package/docs/design/templates/list-action-row/icon-tile.svg +1 -0
  300. package/docs/design/templates/list-action-row/selected-dark.svg +1 -1
  301. package/docs/design/templates/list-action-row/selected.svg +1 -1
  302. package/docs/design/templates/list-action-row/trailing-menu-dark.svg +1 -1
  303. package/docs/design/templates/list-action-row/trailing-menu.svg +1 -1
  304. package/docs/design/templates/list-action-row-dark.svg +1 -1
  305. package/docs/design/templates/list-action-row.svg +1 -1
  306. package/docs/design/templates/list-dark.svg +1 -1
  307. package/docs/design/templates/list-header/size-l-dark.svg +1 -1
  308. package/docs/design/templates/list-header/size-l.svg +1 -1
  309. package/docs/design/templates/list-header/size-m-dark.svg +1 -1
  310. package/docs/design/templates/list-header/size-m.svg +1 -1
  311. package/docs/design/templates/list-header/size-xl-dark.svg +1 -1
  312. package/docs/design/templates/list-header/size-xl.svg +1 -1
  313. package/docs/design/templates/list-header-dark.svg +1 -1
  314. package/docs/design/templates/list-header.svg +1 -1
  315. package/docs/design/templates/list-item/icon-tile-dark.svg +1 -0
  316. package/docs/design/templates/list-item/icon-tile.svg +1 -0
  317. package/docs/design/templates/list-item/selected-dark.svg +1 -1
  318. package/docs/design/templates/list-item/selected.svg +1 -1
  319. package/docs/design/templates/list-item-dark.svg +1 -1
  320. package/docs/design/templates/list-item.svg +1 -1
  321. package/docs/design/templates/list.svg +1 -1
  322. package/docs/design/templates/segmented-control-dark.svg +1 -1
  323. package/docs/design/templates/segmented-control.svg +1 -1
  324. package/docs/design/templates/skeleton-dark.svg +1 -1
  325. package/docs/design/templates/skeleton.svg +1 -1
  326. package/docs/design/templates/state-banner/danger-dark.svg +1 -1
  327. package/docs/design/templates/state-banner/danger.svg +1 -1
  328. package/docs/design/templates/state-banner/info-badge-dark.svg +1 -1
  329. package/docs/design/templates/state-banner/info-badge.svg +1 -1
  330. package/docs/design/templates/state-banner/info-dark.svg +1 -1
  331. package/docs/design/templates/state-banner/info.svg +1 -1
  332. package/docs/design/templates/state-banner/strip-dark.svg +1 -1
  333. package/docs/design/templates/state-banner/strip.svg +1 -1
  334. package/docs/design/templates/state-banner/success-dark.svg +1 -1
  335. package/docs/design/templates/state-banner/success.svg +1 -1
  336. package/docs/design/templates/state-banner/warning-dark.svg +1 -1
  337. package/docs/design/templates/state-banner/warning.svg +1 -1
  338. package/docs/design/templates/state-banner-dark.svg +1 -1
  339. package/docs/design/templates/state-banner.svg +1 -1
  340. package/docs/design/templates/tab-bar-dark.svg +1 -1
  341. package/docs/design/templates/tab-bar.svg +1 -1
  342. package/docs/design/templates/token-search-field-dark.svg +1 -1
  343. package/docs/design/templates/token-search-field.svg +1 -1
  344. package/docs/design/templates/toolbar-control-group-dark.svg +1 -1
  345. package/docs/design/templates/toolbar-control-group.svg +1 -1
  346. package/docs/design/templates/toolbar-dark.svg +1 -1
  347. package/docs/design/templates/toolbar-text/default-dark.svg +1 -1
  348. package/docs/design/templates/toolbar-text/default.svg +1 -1
  349. package/docs/design/templates/toolbar-text/large-dark.svg +1 -1
  350. package/docs/design/templates/toolbar-text/large.svg +1 -1
  351. package/docs/design/templates/toolbar-text-dark.svg +1 -1
  352. package/docs/design/templates/toolbar-text.svg +1 -1
  353. package/docs/design/templates/toolbar.svg +1 -1
  354. package/docs/design/templates/value-table/details-dark.svg +1 -1
  355. package/docs/design/templates/value-table/details.svg +1 -1
  356. package/docs/design/templates/value-table-dark.svg +1 -1
  357. package/docs/design/templates/value-table.svg +1 -1
  358. package/docs/design-philosophy.md +9 -1
  359. package/docs/examples/command-palette-adapter.tsx +3 -3
  360. package/docs/layout.md +147 -14
  361. package/docs/nav-stack.md +112 -2
  362. package/docs/recipes.md +9 -9
  363. package/docs/split-view.md +3 -3
  364. package/docs/sunken-panel.md +2 -2
  365. package/docs/surface-scaffold.md +138 -7
  366. package/docs/tab-navigator.md +38 -1
  367. package/docs/type-contracts.md +16 -16
  368. package/docs/ui-analyzer.md +3 -1
  369. package/docs/ui-doctor.md +71 -0
  370. package/docs/ux-demo.md +6 -6
  371. package/docs/workbench.md +10 -6
  372. package/docs/writing.md +152 -0
  373. package/doctor/copy-capitalization-checks.mjs +591 -0
  374. package/doctor/index.mjs +17 -8
  375. package/llms.txt +105 -11
  376. package/package.json +15 -1
  377. package/ux-demo/recipes/app-shell.tsx +11 -11
  378. package/ux-demo/recipes/collapsible-sidebar.tsx +12 -11
  379. package/ux-demo/recipes/compact-toolbar.tsx +10 -10
  380. package/ux-demo/recipes/composer-form.tsx +8 -8
  381. package/ux-demo/recipes/list-detail-dialog.tsx +13 -13
  382. package/ux-demo/recipes/list-workspace-states.tsx +13 -13
  383. package/ux-demo/recipes/loading-inspector.tsx +10 -10
  384. package/ux-demo/recipes/navigation-sidebar.tsx +7 -7
  385. package/ux-demo/recipes/navigation-stack.tsx +5 -5
  386. package/ux-demo/recipes/workspace-header.tsx +5 -5
  387. package/dist/chunk-36TL6BCR.js.map +0 -1
  388. package/dist/chunk-4LOK4634.js +0 -21
  389. package/dist/chunk-4LOK4634.js.map +0 -1
  390. package/dist/chunk-527IAEWG.js.map +0 -1
  391. package/dist/chunk-6BRRUPJY.js.map +0 -1
  392. package/dist/chunk-6STQXRT4.js.map +0 -1
  393. package/dist/chunk-76PWEN5Y.js +0 -64
  394. package/dist/chunk-76PWEN5Y.js.map +0 -1
  395. package/dist/chunk-AZWE2FB5.js.map +0 -1
  396. package/dist/chunk-DQDTZE4W.js +0 -70
  397. package/dist/chunk-DQDTZE4W.js.map +0 -1
  398. package/dist/chunk-FOQK4F3L.js.map +0 -1
  399. package/dist/chunk-GJYQ27C2.js.map +0 -1
  400. package/dist/chunk-JYD7G4RG.js.map +0 -1
  401. package/dist/chunk-KQDU7Z7P.js.map +0 -1
  402. package/dist/chunk-P74VXMB6.js.map +0 -1
  403. package/dist/chunk-PBT3CPPY.js.map +0 -1
  404. package/dist/chunk-PRG4CL3Q.js.map +0 -1
  405. package/dist/chunk-ROZLJULF.js.map +0 -1
  406. package/dist/chunk-U657IHFB.js.map +0 -1
  407. package/dist/chunk-V6W56V3N.js.map +0 -1
@@ -2,6 +2,27 @@ import { delegate } from 'kerfjs';
2
2
 
3
3
  // src/components/navigation/nav-stack/wiring/wire-nav-stack.ts
4
4
  var DEFAULT_DURATION = 200;
5
+ var CHROME_OVERLAY = "data-chrome-overlay";
6
+ var BOTTOM_TOOLBAR_OVERLAY = "data-bottom-toolbar-overlay";
7
+ var OVERLAY_EDGES = [
8
+ {
9
+ presentation: "data-chrome-presentation",
10
+ element: ":scope > [data-nav-stack-chrome]:not([data-nav-chrome-copy])",
11
+ blockSize: "--_kui-nav-stack-chrome-block-size",
12
+ scrollbarInlineSize: "--_kui-nav-stack-scrollbar-inline-size",
13
+ // A Pane header lies beneath the chrome and starts its content below it.
14
+ paneChrome: ":scope > :is(.kui-pane__header, .kui-pane__toolbar)"
15
+ },
16
+ {
17
+ presentation: "data-bottom-toolbar-presentation",
18
+ element: ":scope > [data-nav-stack-bottom]:not([data-nav-chrome-copy])",
19
+ blockSize: "--_kui-nav-stack-bottom-block-size",
20
+ scrollbarInlineSize: "--_kui-nav-stack-bottom-scrollbar-inline-size",
21
+ // A Pane footer lies beneath the toolbar and ends its content above it.
22
+ paneChrome: ":scope > .kui-pane__footer"
23
+ }
24
+ ];
25
+ var NESTED_LAYOUT = ["nav-stack", "split-view", "workbench", "tab-scaffold"].map((name) => `[data-component="${name}"]`).join(", ");
5
26
  var FOCUSABLE_SELECTOR = [
6
27
  "a[href]",
7
28
  "button:not([disabled])",
@@ -144,6 +165,109 @@ function wireNavStack(root, options = {}) {
144
165
  }
145
166
  targetView.focus({ preventScroll: true });
146
167
  };
168
+ const edges = OVERLAY_EDGES.map((edge) => [
169
+ edge,
170
+ { covers: false }
171
+ ]);
172
+ const measuredEdge = (state) => state.element !== void 0 && state.size !== void 0;
173
+ let measuredScroller;
174
+ let scrollbarSize = 0;
175
+ const writeProperty = (name, value) => {
176
+ if (section.style.getPropertyValue(name) === value) return;
177
+ if (value) section.style.setProperty(name, value);
178
+ else section.style.removeProperty(name);
179
+ };
180
+ const publishOverlay = () => {
181
+ for (const [edge, state] of edges) {
182
+ const measured = measuredEdge(state);
183
+ writeProperty(edge.blockSize, measured ? `${state.size}px` : "");
184
+ writeProperty(
185
+ edge.scrollbarInlineSize,
186
+ measured && state.covers && scrollbarSize > 0 ? `${scrollbarSize}px` : ""
187
+ );
188
+ }
189
+ if (section.getAttribute("style") === "") section.removeAttribute("style");
190
+ const [top, bottom] = edges.map(([, state]) => measuredEdge(state));
191
+ if (top && section.getAttribute(CHROME_OVERLAY) !== "measured")
192
+ section.setAttribute(CHROME_OVERLAY, "measured");
193
+ else if (!top && section.hasAttribute(CHROME_OVERLAY))
194
+ section.removeAttribute(CHROME_OVERLAY);
195
+ if (bottom && section.getAttribute(BOTTOM_TOOLBAR_OVERLAY) !== "measured")
196
+ section.setAttribute(BOTTOM_TOOLBAR_OVERLAY, "measured");
197
+ else if (!bottom && section.hasAttribute(BOTTOM_TOOLBAR_OVERLAY))
198
+ section.removeAttribute(BOTTOM_TOOLBAR_OVERLAY);
199
+ };
200
+ const activeScroller = () => {
201
+ const top = topView(viewport);
202
+ const only = top?.children.length === 1 ? top.children[0] : void 0;
203
+ if (!only) return { scroller: top };
204
+ if (only.matches(".kui-pane"))
205
+ return {
206
+ scroller: only.querySelector(":scope > .kui-pane__content") ?? void 0,
207
+ pane: only
208
+ };
209
+ return { scroller: only.matches(NESTED_LAYOUT) ? void 0 : top };
210
+ };
211
+ const measureScrollbar = () => {
212
+ const scroller = measuredScroller;
213
+ if (!scroller) {
214
+ scrollbarSize = 0;
215
+ return;
216
+ }
217
+ const style = view.getComputedStyle(scroller);
218
+ scrollbarSize = Math.max(
219
+ 0,
220
+ scroller.offsetWidth - scroller.clientWidth - (Number.parseFloat(style.borderLeftWidth) || 0) - (Number.parseFloat(style.borderRightWidth) || 0)
221
+ );
222
+ };
223
+ const chromeObserver = view.ResizeObserver ? new view.ResizeObserver((entries) => {
224
+ for (const entry of entries) {
225
+ const state = edges.find(
226
+ ([, edgeState]) => edgeState.element === entry.target
227
+ )?.[1];
228
+ if (state)
229
+ state.size = entry.borderBoxSize?.[0]?.blockSize ?? entry.target.getBoundingClientRect().height;
230
+ else if (entry.target === measuredScroller) measureScrollbar();
231
+ }
232
+ publishOverlay();
233
+ }) : void 0;
234
+ const syncOverlay = () => {
235
+ for (const [edge, state] of edges) {
236
+ const element = section.getAttribute(edge.presentation) === "overlay" ? section.querySelector(edge.element) ?? void 0 : void 0;
237
+ if (element === state.element) continue;
238
+ if (state.element) chromeObserver?.unobserve(state.element);
239
+ state.element = element;
240
+ if (!element) state.size = void 0;
241
+ else {
242
+ if (state.size === void 0 || !chromeObserver)
243
+ state.size = element.getBoundingClientRect().height;
244
+ chromeObserver?.observe(element, { box: "border-box" });
245
+ }
246
+ }
247
+ const { scroller, pane } = activeScroller();
248
+ for (const [edge, state] of edges)
249
+ state.covers = state.element !== void 0 && scroller !== void 0 && !pane?.querySelector(edge.paneChrome);
250
+ const covered = edges.some(([, state]) => state.covers) ? scroller : void 0;
251
+ if (covered !== measuredScroller) {
252
+ if (measuredScroller) chromeObserver?.unobserve(measuredScroller);
253
+ measuredScroller = covered;
254
+ measureScrollbar();
255
+ if (measuredScroller) chromeObserver?.observe(measuredScroller);
256
+ }
257
+ publishOverlay();
258
+ };
259
+ const overlayObserver = new MutationObserver(syncOverlay);
260
+ overlayObserver.observe(section, {
261
+ childList: true,
262
+ attributes: true,
263
+ attributeFilter: [
264
+ ...OVERLAY_EDGES.map((edge) => edge.presentation),
265
+ CHROME_OVERLAY,
266
+ BOTTOM_TOOLBAR_OVERLAY,
267
+ "style"
268
+ ]
269
+ });
270
+ syncOverlay();
147
271
  const onFocusIn = (event) => rememberFocusedView(event.target);
148
272
  section.addEventListener("focusin", onFocusIn);
149
273
  rememberFocusedView(section.ownerDocument.activeElement);
@@ -231,6 +355,7 @@ function wireNavStack(root, options = {}) {
231
355
  focusInto(top);
232
356
  }
233
357
  activeKey = currentKey;
358
+ syncOverlay();
234
359
  });
235
360
  observer.observe(viewport, {
236
361
  childList: true,
@@ -242,6 +367,16 @@ function wireNavStack(root, options = {}) {
242
367
  disposeBack();
243
368
  section.removeEventListener("focusin", onFocusIn);
244
369
  observer.disconnect();
370
+ overlayObserver.disconnect();
371
+ chromeObserver?.disconnect();
372
+ for (const [, state] of edges) {
373
+ state.element = void 0;
374
+ state.size = void 0;
375
+ state.covers = false;
376
+ }
377
+ measuredScroller = void 0;
378
+ scrollbarSize = 0;
379
+ publishOverlay();
245
380
  finishTransition();
246
381
  for (const [element, previousTabIndex] of generatedFallbacks) {
247
382
  if (!element.isConnected || element.tabIndex !== -1) continue;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/navigation/nav-stack/wiring/wire-nav-stack.ts"],"names":[],"mappings":"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","file":"wire-nav-stack.js","sourcesContent":["import { delegate } from 'kerfjs';\n\nexport interface WireNavStackOptions {\n /** Invoked when the back control is activated. The app pops its own stack. */\n onBack?: () => void;\n /** Transition duration in ms (default 200). Set 0 to disable animation. */\n duration?: number;\n}\n\nconst DEFAULT_DURATION = 200;\nconst FOCUSABLE_SELECTOR = [\n 'a[href]',\n 'button:not([disabled])',\n 'input:not([disabled])',\n 'select:not([disabled])',\n 'textarea:not([disabled])',\n '[tabindex]:not([tabindex=\"-1\"])',\n].join(',');\n\nfunction viewsOf(viewport: Element): HTMLElement[] {\n return Array.from(\n viewport.querySelectorAll<HTMLElement>(':scope > .kui-nav-stack__view'),\n );\n}\n\nfunction topView(viewport: Element): HTMLElement | undefined {\n const live = viewsOf(viewport).filter(\n (view) => view.dataset.navExiting !== 'true',\n );\n return live[live.length - 1];\n}\n\nfunction reducedMotion(view: Window): boolean {\n return (\n typeof view.matchMedia === 'function' &&\n view.matchMedia('(prefers-reduced-motion: reduce)').matches\n );\n}\n\nfunction chromeOf(section: HTMLElement): HTMLElement[] {\n return Array.from(\n section.querySelectorAll<HTMLElement>(\n ':scope > [data-nav-stack-chrome]:not([data-nav-chrome-copy]), :scope > [data-nav-stack-bottom]:not([data-nav-chrome-copy])',\n ),\n );\n}\n\nfunction availableFocusTarget(\n element: Element | null | undefined,\n): element is HTMLElement {\n return (\n element instanceof HTMLElement &&\n element.isConnected &&\n !element.matches('[disabled], [aria-disabled=\"true\"]') &&\n !element.closest('[inert], [hidden], [aria-hidden=\"true\"]')\n );\n}\n\n/**\n * Animate a `NavStack`'s push/pop transitions and wire its back control. The app\n * owns the stack (a signal of `NavStackView[]`) and re-renders `NavStack` when it\n * changes; this helper slides the content and settles the chrome across each\n * change, moves focus into every new top view, restores that view's last focused\n * descendant on pop, and calls `onBack` when the back control is used. Mark a\n * preferred initial target with `data-nav-focus`; otherwise the first focusable\n * descendant (or the view itself) receives focus. Returns a disposer.\n */\nexport function wireNavStack(\n root: Element,\n options: WireNavStackOptions = {},\n): () => void {\n const section = root.matches('[data-component=\"nav-stack\"]')\n ? root\n : root.querySelector('[data-component=\"nav-stack\"]');\n const viewport = section?.querySelector('[data-nav-stack-viewport]');\n if (!(section instanceof HTMLElement) || !viewport) return () => {};\n\n const view = section.ownerDocument.defaultView ?? window;\n const duration = options.duration ?? DEFAULT_DURATION;\n const previousDuration = section.style.getPropertyValue(\n '--kui-nav-stack-transition-duration',\n );\n section.style.setProperty(\n '--kui-nav-stack-transition-duration',\n `${Math.max(0, duration)}ms`,\n );\n const disposeBack = delegate(section, 'click', '[data-nav-back]', () =>\n options.onBack?.(),\n );\n\n let activeKey = topView(viewport)?.dataset.navKey;\n const timers = new Set<number>();\n const frames = new Set<number>();\n const frame = (fn: () => void): void => {\n const id = view.requestAnimationFrame(() => {\n frames.delete(id);\n fn();\n });\n frames.add(id);\n };\n const finishTransition = (): void => {\n for (const id of frames) view.cancelAnimationFrame(id);\n frames.clear();\n for (const id of timers) view.clearTimeout(id);\n timers.clear();\n section\n .querySelectorAll<HTMLElement>(':scope > [data-nav-chrome-copy]')\n .forEach((element) => element.remove());\n chromeOf(section).forEach((element) =>\n element.classList.remove('kui-nav-stack__chrome--entering'),\n );\n viewsOf(viewport).forEach((element) => {\n if (element.dataset.navExiting === 'true') element.remove();\n else {\n element.classList.remove('kui-nav-stack__view--entering');\n delete element.dataset.navRevealed;\n }\n });\n delete section.dataset.navChromeTransition;\n };\n const rememberedFocus = new Map<string, HTMLElement>();\n const generatedFallbacks = new Map<HTMLElement, string | null>();\n let chromeSnapshots = chromeOf(section).map((element) =>\n element.cloneNode(true),\n ) as HTMLElement[];\n\n const settle = (fn: () => void): void => {\n if (duration <= 0 || reducedMotion(view)) {\n fn();\n return;\n }\n const timer = view.setTimeout(() => {\n timers.delete(timer);\n fn();\n }, duration);\n timers.add(timer);\n };\n\n const play = (el: HTMLElement, kind: 'entering' | 'exiting'): void => {\n const animated = duration > 0 && !reducedMotion(view);\n if (kind === 'entering') {\n // Push: start the incoming view off the trailing edge, then release it so\n // it slides to rest (translateX(100%) → 0).\n el.classList.add('kui-nav-stack__view--entering');\n if (animated) {\n // Force a reflow so the starting transform applies before we clear it.\n void el.offsetWidth;\n frame(() => el.classList.remove('kui-nav-stack__view--entering'));\n } else {\n el.classList.remove('kui-nav-stack__view--entering');\n }\n } else if (animated) {\n // Pop: the outgoing view is at rest; add the off-edge class on the next\n // frame so it slides OUT (translateX(0) → 100%), not in.\n frame(() => el.classList.add('kui-nav-stack__view--exiting'));\n } else {\n el.classList.add('kui-nav-stack__view--exiting');\n }\n };\n\n const rememberFocusedView = (target: Element | null): void => {\n if (!(target instanceof HTMLElement)) return;\n const owner = target.closest<HTMLElement>('.kui-nav-stack__view');\n const key = owner?.dataset.navKey;\n if (key && owner !== target && viewport.contains(owner))\n rememberedFocus.set(key, target);\n };\n\n const focusInto = (targetView: HTMLElement): void => {\n const key = targetView.dataset.navKey;\n const remembered = key ? rememberedFocus.get(key) : undefined;\n const preferred = Array.from(\n targetView.querySelectorAll<HTMLElement>('[data-nav-focus]'),\n ).find(availableFocusTarget);\n const first = Array.from(\n targetView.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTOR),\n ).find(availableFocusTarget);\n const target =\n (availableFocusTarget(remembered) && targetView.contains(remembered)\n ? remembered\n : undefined) ??\n preferred ??\n first;\n if (target) {\n target.focus({ preventScroll: true });\n return;\n }\n\n if (!generatedFallbacks.has(targetView)) {\n generatedFallbacks.set(\n targetView,\n targetView.hasAttribute('tabindex')\n ? targetView.getAttribute('tabindex')\n : null,\n );\n targetView.tabIndex = -1;\n }\n targetView.focus({ preventScroll: true });\n };\n\n const onFocusIn = (event: Event): void =>\n rememberFocusedView(event.target as Element | null);\n section.addEventListener('focusin', onFocusIn);\n rememberFocusedView(section.ownerDocument.activeElement);\n\n const crossFadeChrome = (): void => {\n const current = chromeOf(section);\n const animated = duration > 0 && !reducedMotion(view);\n if (!animated) {\n chromeSnapshots = current.map((element) =>\n element.cloneNode(true),\n ) as HTMLElement[];\n return;\n }\n\n section.dataset.navChromeTransition = 'true';\n const copies = chromeSnapshots.map((snapshot) => {\n const copy = snapshot.cloneNode(true) as HTMLElement;\n copy.classList.add('kui-nav-stack__chrome-copy');\n copy.dataset.navChromeCopy = '';\n copy.setAttribute('aria-hidden', 'true');\n copy.setAttribute('inert', '');\n if (copy.hasAttribute('data-nav-stack-bottom'))\n copy.classList.add('kui-nav-stack__chrome-copy--bottom');\n section.append(copy);\n return copy;\n });\n\n current.forEach((element) =>\n element.classList.add('kui-nav-stack__chrome--entering'),\n );\n void section.offsetWidth;\n frame(() => {\n current.forEach((element) =>\n element.classList.remove('kui-nav-stack__chrome--entering'),\n );\n copies.forEach((copy) =>\n copy.classList.add('kui-nav-stack__chrome-copy--exiting'),\n );\n });\n settle(() => {\n copies.forEach((copy) => copy.remove());\n delete section.dataset.navChromeTransition;\n });\n chromeSnapshots = current.map((element) => {\n const snapshot = element.cloneNode(true) as HTMLElement;\n snapshot.classList.remove('kui-nav-stack__chrome--entering');\n return snapshot;\n });\n };\n\n const observer = new MutationObserver((records) => {\n const removed: HTMLElement[] = [];\n for (const record of records) {\n if (record.target !== viewport) continue;\n record.removedNodes.forEach((node) => {\n if (\n node instanceof HTMLElement &&\n node.classList.contains('kui-nav-stack__view') &&\n node.dataset.navExiting !== 'true'\n )\n removed.push(node);\n });\n }\n\n const top = topView(viewport);\n const currentKey = top?.dataset.navKey;\n const poppedTop = removed.find((node) => node.dataset.navKey === activeKey);\n\n if (poppedTop && currentKey !== activeKey) {\n finishTransition();\n // Pop: bring the removed node back briefly to slide it out over the revealed view.\n poppedTop.classList.remove(\n 'kui-nav-stack__view--entering',\n 'kui-nav-stack__view--exiting',\n );\n poppedTop.dataset.navExiting = 'true';\n poppedTop.setAttribute('aria-hidden', 'true');\n viewport.append(poppedTop);\n void poppedTop.offsetWidth;\n play(poppedTop, 'exiting');\n crossFadeChrome();\n if (top) focusInto(top);\n settle(() => poppedTop.remove());\n } else if (currentKey !== activeKey && top) {\n finishTransition();\n const previous = viewsOf(viewport).find(\n (element) => element.dataset.navKey === activeKey,\n );\n if (previous) {\n previous.dataset.navRevealed = 'true';\n settle(() => delete previous.dataset.navRevealed);\n }\n // Push: slide the new top in.\n rememberFocusedView(section.ownerDocument.activeElement);\n play(top, 'entering');\n crossFadeChrome();\n focusInto(top);\n }\n\n activeKey = currentKey;\n });\n observer.observe(viewport, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: ['data-nav-key', 'data-nav-active'],\n });\n\n return () => {\n disposeBack();\n section.removeEventListener('focusin', onFocusIn);\n observer.disconnect();\n finishTransition();\n for (const [element, previousTabIndex] of generatedFallbacks) {\n if (!element.isConnected || element.tabIndex !== -1) continue;\n if (previousTabIndex === null) element.removeAttribute('tabindex');\n else element.setAttribute('tabindex', previousTabIndex);\n }\n generatedFallbacks.clear();\n rememberedFocus.clear();\n if (previousDuration)\n section.style.setProperty(\n '--kui-nav-stack-transition-duration',\n previousDuration,\n );\n else section.style.removeProperty('--kui-nav-stack-transition-duration');\n };\n}\n"]}
1
+ {"version":3,"sources":["../src/components/navigation/nav-stack/wiring/wire-nav-stack.ts"],"names":[],"mappings":"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","file":"wire-nav-stack.js","sourcesContent":["import { delegate } from 'kerfjs';\n\nexport interface WireNavStackOptions {\n /** Invoked when the back control is activated. The app pops its own stack. */\n onBack?: () => void;\n /** Transition duration in ms (default 200). Set 0 to disable animation. */\n duration?: number;\n}\n\nconst DEFAULT_DURATION = 200;\n/** On an overlay-chrome NavStack: the wiring has measured its live chrome. */\nconst CHROME_OVERLAY = 'data-chrome-overlay';\n/** On an overlay-bottom-toolbar NavStack: the wiring has measured it. */\nconst BOTTOM_TOOLBAR_OVERLAY = 'data-bottom-toolbar-overlay';\n/**\n * One overlay-capable chrome edge of a NavStack: the top chrome\n * (`chromePresentation`) or the bottom toolbar (`bottomToolbarPresentation`).\n * Each names the root attribute that opts it in, its live element (never a\n * cross-fading copy), the border-box block size the wiring publishes on the\n * root once it has measured that element (beside its gate), the root\n * property for the classic scrollbar inline size it leaves uncovered, and\n * the sole-Pane slot that, when present, keeps the Pane's scroller clear of\n * it.\n */\ninterface OverlayEdge {\n readonly presentation: string;\n readonly element: string;\n readonly blockSize: string;\n readonly scrollbarInlineSize: string;\n readonly paneChrome: string;\n}\n\nconst OVERLAY_EDGES: readonly OverlayEdge[] = [\n {\n presentation: 'data-chrome-presentation',\n element: ':scope > [data-nav-stack-chrome]:not([data-nav-chrome-copy])',\n blockSize: '--_kui-nav-stack-chrome-block-size',\n scrollbarInlineSize: '--_kui-nav-stack-scrollbar-inline-size',\n // A Pane header lies beneath the chrome and starts its content below it.\n paneChrome: ':scope > :is(.kui-pane__header, .kui-pane__toolbar)',\n },\n {\n presentation: 'data-bottom-toolbar-presentation',\n element: ':scope > [data-nav-stack-bottom]:not([data-nav-chrome-copy])',\n blockSize: '--_kui-nav-stack-bottom-block-size',\n scrollbarInlineSize: '--_kui-nav-stack-bottom-scrollbar-inline-size',\n // A Pane footer lies beneath the toolbar and ends its content above it.\n paneChrome: ':scope > .kui-pane__footer',\n },\n];\n/** A layout that, as a view's only child, owns its own chrome and scroller. */\nconst NESTED_LAYOUT = ['nav-stack', 'split-view', 'workbench', 'tab-scaffold']\n .map((name) => `[data-component=\"${name}\"]`)\n .join(', ');\nconst FOCUSABLE_SELECTOR = [\n 'a[href]',\n 'button:not([disabled])',\n 'input:not([disabled])',\n 'select:not([disabled])',\n 'textarea:not([disabled])',\n '[tabindex]:not([tabindex=\"-1\"])',\n].join(',');\n\nfunction viewsOf(viewport: Element): HTMLElement[] {\n return Array.from(\n viewport.querySelectorAll<HTMLElement>(':scope > .kui-nav-stack__view'),\n );\n}\n\nfunction topView(viewport: Element): HTMLElement | undefined {\n const live = viewsOf(viewport).filter(\n (view) => view.dataset.navExiting !== 'true',\n );\n return live[live.length - 1];\n}\n\nfunction reducedMotion(view: Window): boolean {\n return (\n typeof view.matchMedia === 'function' &&\n view.matchMedia('(prefers-reduced-motion: reduce)').matches\n );\n}\n\nfunction chromeOf(section: HTMLElement): HTMLElement[] {\n return Array.from(\n section.querySelectorAll<HTMLElement>(\n ':scope > [data-nav-stack-chrome]:not([data-nav-chrome-copy]), :scope > [data-nav-stack-bottom]:not([data-nav-chrome-copy])',\n ),\n );\n}\n\nfunction availableFocusTarget(\n element: Element | null | undefined,\n): element is HTMLElement {\n return (\n element instanceof HTMLElement &&\n element.isConnected &&\n !element.matches('[disabled], [aria-disabled=\"true\"]') &&\n !element.closest('[inert], [hidden], [aria-hidden=\"true\"]')\n );\n}\n\n/**\n * Animate a `NavStack`'s push/pop transitions and wire its back control. The app\n * owns the stack (a signal of `NavStackView[]`) and re-renders `NavStack` when it\n * changes; this helper slides the content and settles the chrome across each\n * change, moves focus into every new top view, restores that view's last focused\n * descendant on pop, and calls `onBack` when the back control is used. Mark a\n * preferred initial target with `data-nav-focus`; otherwise the first focusable\n * descendant (or the view itself) receives focus. Returns a disposer.\n */\nexport function wireNavStack(\n root: Element,\n options: WireNavStackOptions = {},\n): () => void {\n const section = root.matches('[data-component=\"nav-stack\"]')\n ? root\n : root.querySelector('[data-component=\"nav-stack\"]');\n const viewport = section?.querySelector('[data-nav-stack-viewport]');\n if (!(section instanceof HTMLElement) || !viewport) return () => {};\n\n const view = section.ownerDocument.defaultView ?? window;\n const duration = options.duration ?? DEFAULT_DURATION;\n const previousDuration = section.style.getPropertyValue(\n '--kui-nav-stack-transition-duration',\n );\n section.style.setProperty(\n '--kui-nav-stack-transition-duration',\n `${Math.max(0, duration)}ms`,\n );\n const disposeBack = delegate(section, 'click', '[data-nav-back]', () =>\n options.onBack?.(),\n );\n\n let activeKey = topView(viewport)?.dataset.navKey;\n const timers = new Set<number>();\n const frames = new Set<number>();\n const frame = (fn: () => void): void => {\n const id = view.requestAnimationFrame(() => {\n frames.delete(id);\n fn();\n });\n frames.add(id);\n };\n const finishTransition = (): void => {\n for (const id of frames) view.cancelAnimationFrame(id);\n frames.clear();\n for (const id of timers) view.clearTimeout(id);\n timers.clear();\n section\n .querySelectorAll<HTMLElement>(':scope > [data-nav-chrome-copy]')\n .forEach((element) => element.remove());\n chromeOf(section).forEach((element) =>\n element.classList.remove('kui-nav-stack__chrome--entering'),\n );\n viewsOf(viewport).forEach((element) => {\n if (element.dataset.navExiting === 'true') element.remove();\n else {\n element.classList.remove('kui-nav-stack__view--entering');\n delete element.dataset.navRevealed;\n }\n });\n delete section.dataset.navChromeTransition;\n };\n const rememberedFocus = new Map<string, HTMLElement>();\n const generatedFallbacks = new Map<HTMLElement, string | null>();\n let chromeSnapshots = chromeOf(section).map((element) =>\n element.cloneNode(true),\n ) as HTMLElement[];\n\n const settle = (fn: () => void): void => {\n if (duration <= 0 || reducedMotion(view)) {\n fn();\n return;\n }\n const timer = view.setTimeout(() => {\n timers.delete(timer);\n fn();\n }, duration);\n timers.add(timer);\n };\n\n const play = (el: HTMLElement, kind: 'entering' | 'exiting'): void => {\n const animated = duration > 0 && !reducedMotion(view);\n if (kind === 'entering') {\n // Push: start the incoming view off the trailing edge, then release it so\n // it slides to rest (translateX(100%) → 0).\n el.classList.add('kui-nav-stack__view--entering');\n if (animated) {\n // Force a reflow so the starting transform applies before we clear it.\n void el.offsetWidth;\n frame(() => el.classList.remove('kui-nav-stack__view--entering'));\n } else {\n el.classList.remove('kui-nav-stack__view--entering');\n }\n } else if (animated) {\n // Pop: the outgoing view is at rest; add the off-edge class on the next\n // frame so it slides OUT (translateX(0) → 100%), not in.\n frame(() => el.classList.add('kui-nav-stack__view--exiting'));\n } else {\n el.classList.add('kui-nav-stack__view--exiting');\n }\n };\n\n const rememberFocusedView = (target: Element | null): void => {\n if (!(target instanceof HTMLElement)) return;\n const owner = target.closest<HTMLElement>('.kui-nav-stack__view');\n const key = owner?.dataset.navKey;\n if (key && owner !== target && viewport.contains(owner))\n rememberedFocus.set(key, target);\n };\n\n const focusInto = (targetView: HTMLElement): void => {\n const key = targetView.dataset.navKey;\n const remembered = key ? rememberedFocus.get(key) : undefined;\n const preferred = Array.from(\n targetView.querySelectorAll<HTMLElement>('[data-nav-focus]'),\n ).find(availableFocusTarget);\n const first = Array.from(\n targetView.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTOR),\n ).find(availableFocusTarget);\n const target =\n (availableFocusTarget(remembered) && targetView.contains(remembered)\n ? remembered\n : undefined) ??\n preferred ??\n first;\n if (target) {\n target.focus({ preventScroll: true });\n return;\n }\n\n if (!generatedFallbacks.has(targetView)) {\n generatedFallbacks.set(\n targetView,\n targetView.hasAttribute('tabindex')\n ? targetView.getAttribute('tabindex')\n : null,\n );\n targetView.tabIndex = -1;\n }\n targetView.focus({ preventScroll: true });\n };\n\n // Overlay chrome (`chromePresentation=\"overlay\"` for the top chrome,\n // `bottomToolbarPresentation=\"overlay\"` for the bottom toolbar): measure\n // each live edge element, never a cross-fading copy, and publish its\n // border-box block size with the gate that lays it over the viewport. The\n // size follows the element as it wraps, zooms, or changes with the active\n // view, and a re-render that strips the published state gets it back\n // before paint. The active view's classic (space-taking) vertical\n // scrollbar is measured too, so each overlaid edge ends where its track\n // begins.\n interface EdgeState {\n element?: HTMLElement;\n size?: number;\n /** The active scroller's track lies beneath this edge. */\n covers: boolean;\n }\n const edges = OVERLAY_EDGES.map((edge): [OverlayEdge, EdgeState] => [\n edge,\n { covers: false },\n ]);\n const measuredEdge = (state: EdgeState): boolean =>\n state.element !== undefined && state.size !== undefined;\n let measuredScroller: HTMLElement | undefined;\n let scrollbarSize = 0;\n const writeProperty = (name: string, value: string): void => {\n if (section.style.getPropertyValue(name) === value) return;\n if (value) section.style.setProperty(name, value);\n else section.style.removeProperty(name);\n };\n const publishOverlay = (): void => {\n for (const [edge, state] of edges) {\n const measured = measuredEdge(state);\n writeProperty(edge.blockSize, measured ? `${state.size}px` : '');\n writeProperty(\n edge.scrollbarInlineSize,\n measured && state.covers && scrollbarSize > 0\n ? `${scrollbarSize}px`\n : '',\n );\n }\n if (section.getAttribute('style') === '') section.removeAttribute('style');\n // Each gate changes only when it must, so the root observer settles.\n const [top, bottom] = edges.map(([, state]) => measuredEdge(state));\n if (top && section.getAttribute(CHROME_OVERLAY) !== 'measured')\n section.setAttribute(CHROME_OVERLAY, 'measured');\n else if (!top && section.hasAttribute(CHROME_OVERLAY))\n section.removeAttribute(CHROME_OVERLAY);\n if (bottom && section.getAttribute(BOTTOM_TOOLBAR_OVERLAY) !== 'measured')\n section.setAttribute(BOTTOM_TOOLBAR_OVERLAY, 'measured');\n else if (!bottom && section.hasAttribute(BOTTOM_TOOLBAR_OVERLAY))\n section.removeAttribute(BOTTOM_TOOLBAR_OVERLAY);\n };\n /**\n * The element that scrolls beneath the overlaid edges in the active view\n * (the view itself, or a sole Pane's content), and that sole Pane, whose\n * own header or footer keeps its scroller clear of the matching edge.\n */\n const activeScroller = (): { scroller?: HTMLElement; pane?: Element } => {\n const top = topView(viewport);\n const only = top?.children.length === 1 ? top.children[0] : undefined;\n if (!only) return { scroller: top };\n if (only.matches('.kui-pane'))\n return {\n scroller:\n only.querySelector<HTMLElement>(':scope > .kui-pane__content') ??\n undefined,\n pane: only,\n };\n return { scroller: only.matches(NESTED_LAYOUT) ? undefined : top };\n };\n const measureScrollbar = (): void => {\n const scroller = measuredScroller;\n if (!scroller) {\n scrollbarSize = 0;\n return;\n }\n const style = view.getComputedStyle(scroller);\n scrollbarSize = Math.max(\n 0,\n scroller.offsetWidth -\n scroller.clientWidth -\n (Number.parseFloat(style.borderLeftWidth) || 0) -\n (Number.parseFloat(style.borderRightWidth) || 0),\n );\n };\n const chromeObserver = view.ResizeObserver\n ? new view.ResizeObserver((entries) => {\n for (const entry of entries) {\n const state = edges.find(\n ([, edgeState]) => edgeState.element === entry.target,\n )?.[1];\n if (state)\n state.size =\n entry.borderBoxSize?.[0]?.blockSize ??\n entry.target.getBoundingClientRect().height;\n else if (entry.target === measuredScroller) measureScrollbar();\n }\n publishOverlay();\n })\n : undefined;\n const syncOverlay = (): void => {\n for (const [edge, state] of edges) {\n const element =\n section.getAttribute(edge.presentation) === 'overlay'\n ? (section.querySelector<HTMLElement>(edge.element) ?? undefined)\n : undefined;\n if (element === state.element) continue;\n if (state.element) chromeObserver?.unobserve(state.element);\n state.element = element;\n if (!element) state.size = undefined;\n else {\n // A replacement keeps the last size until the observer reports it\n // after layout; a first one (or one with no observer to report it)\n // is measured at once.\n if (state.size === undefined || !chromeObserver)\n state.size = element.getBoundingClientRect().height;\n // The border box: a forced-colors edge changes no content box.\n chromeObserver?.observe(element, { box: 'border-box' });\n }\n }\n // A scrollbar appearing or leaving resizes the scroller's content box.\n const { scroller, pane } = activeScroller();\n for (const [edge, state] of edges)\n state.covers =\n state.element !== undefined &&\n scroller !== undefined &&\n !pane?.querySelector(edge.paneChrome);\n const covered = edges.some(([, state]) => state.covers)\n ? scroller\n : undefined;\n if (covered !== measuredScroller) {\n if (measuredScroller) chromeObserver?.unobserve(measuredScroller);\n measuredScroller = covered;\n measureScrollbar();\n if (measuredScroller) chromeObserver?.observe(measuredScroller);\n }\n publishOverlay();\n };\n const overlayObserver = new MutationObserver(syncOverlay);\n overlayObserver.observe(section, {\n childList: true,\n attributes: true,\n attributeFilter: [\n ...OVERLAY_EDGES.map((edge) => edge.presentation),\n CHROME_OVERLAY,\n BOTTOM_TOOLBAR_OVERLAY,\n 'style',\n ],\n });\n syncOverlay();\n\n const onFocusIn = (event: Event): void =>\n rememberFocusedView(event.target as Element | null);\n section.addEventListener('focusin', onFocusIn);\n rememberFocusedView(section.ownerDocument.activeElement);\n\n const crossFadeChrome = (): void => {\n const current = chromeOf(section);\n const animated = duration > 0 && !reducedMotion(view);\n if (!animated) {\n chromeSnapshots = current.map((element) =>\n element.cloneNode(true),\n ) as HTMLElement[];\n return;\n }\n\n section.dataset.navChromeTransition = 'true';\n const copies = chromeSnapshots.map((snapshot) => {\n const copy = snapshot.cloneNode(true) as HTMLElement;\n copy.classList.add('kui-nav-stack__chrome-copy');\n copy.dataset.navChromeCopy = '';\n copy.setAttribute('aria-hidden', 'true');\n copy.setAttribute('inert', '');\n if (copy.hasAttribute('data-nav-stack-bottom'))\n copy.classList.add('kui-nav-stack__chrome-copy--bottom');\n section.append(copy);\n return copy;\n });\n\n current.forEach((element) =>\n element.classList.add('kui-nav-stack__chrome--entering'),\n );\n void section.offsetWidth;\n frame(() => {\n current.forEach((element) =>\n element.classList.remove('kui-nav-stack__chrome--entering'),\n );\n copies.forEach((copy) =>\n copy.classList.add('kui-nav-stack__chrome-copy--exiting'),\n );\n });\n settle(() => {\n copies.forEach((copy) => copy.remove());\n delete section.dataset.navChromeTransition;\n });\n chromeSnapshots = current.map((element) => {\n const snapshot = element.cloneNode(true) as HTMLElement;\n snapshot.classList.remove('kui-nav-stack__chrome--entering');\n return snapshot;\n });\n };\n\n const observer = new MutationObserver((records) => {\n const removed: HTMLElement[] = [];\n for (const record of records) {\n if (record.target !== viewport) continue;\n record.removedNodes.forEach((node) => {\n if (\n node instanceof HTMLElement &&\n node.classList.contains('kui-nav-stack__view') &&\n node.dataset.navExiting !== 'true'\n )\n removed.push(node);\n });\n }\n\n const top = topView(viewport);\n const currentKey = top?.dataset.navKey;\n const poppedTop = removed.find((node) => node.dataset.navKey === activeKey);\n\n if (poppedTop && currentKey !== activeKey) {\n finishTransition();\n // Pop: bring the removed node back briefly to slide it out over the revealed view.\n poppedTop.classList.remove(\n 'kui-nav-stack__view--entering',\n 'kui-nav-stack__view--exiting',\n );\n poppedTop.dataset.navExiting = 'true';\n poppedTop.setAttribute('aria-hidden', 'true');\n viewport.append(poppedTop);\n void poppedTop.offsetWidth;\n play(poppedTop, 'exiting');\n crossFadeChrome();\n if (top) focusInto(top);\n settle(() => poppedTop.remove());\n } else if (currentKey !== activeKey && top) {\n finishTransition();\n const previous = viewsOf(viewport).find(\n (element) => element.dataset.navKey === activeKey,\n );\n if (previous) {\n previous.dataset.navRevealed = 'true';\n settle(() => delete previous.dataset.navRevealed);\n }\n // Push: slide the new top in.\n rememberFocusedView(section.ownerDocument.activeElement);\n play(top, 'entering');\n crossFadeChrome();\n focusInto(top);\n }\n\n activeKey = currentKey;\n // The active view, and so the scroller beneath the chrome, may change.\n syncOverlay();\n });\n observer.observe(viewport, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: ['data-nav-key', 'data-nav-active'],\n });\n\n return () => {\n disposeBack();\n section.removeEventListener('focusin', onFocusIn);\n observer.disconnect();\n overlayObserver.disconnect();\n chromeObserver?.disconnect();\n for (const [, state] of edges) {\n state.element = undefined;\n state.size = undefined;\n state.covers = false;\n }\n measuredScroller = undefined;\n scrollbarSize = 0;\n publishOverlay();\n finishTransition();\n for (const [element, previousTabIndex] of generatedFallbacks) {\n if (!element.isConnected || element.tabIndex !== -1) continue;\n if (previousTabIndex === null) element.removeAttribute('tabindex');\n else element.setAttribute('tabindex', previousTabIndex);\n }\n generatedFallbacks.clear();\n rememberedFocus.clear();\n if (previousDuration)\n section.style.setProperty(\n '--kui-nav-stack-transition-duration',\n previousDuration,\n );\n else section.style.removeProperty('--kui-nav-stack-transition-duration');\n };\n}\n"]}
@@ -59,6 +59,15 @@ type Root = HTMLElement | Document;
59
59
  * - each app-owned `targets` pairing: a `Toolbar` or `List` named as chrome
60
60
  * draws the divider on its facing side.
61
61
  *
62
+ * It also measures every `Pane` header laid over its content
63
+ * (`headerPresentation="overlay"`, with fixed chrome placement): it publishes
64
+ * the header's border-box block size on the Pane root as the inherited
65
+ * `--kui-scroll-clearance-block-start` context, and marks the root
66
+ * `data-header-overlay="measured"`, which moves the header over the content
67
+ * and has the content clear it. The measurement follows the header as it
68
+ * wraps, zooms, or changes content, and both are restored before paint if a
69
+ * re-render drops them.
70
+ *
62
71
  * Structure is re-read after every DOM change below root that can change a
63
72
  * pairing — a structural element or target id added, removed, or re-classed;
64
73
  * mutations inside scrolled content (a row's class, a list's rows) do not
@@ -1,3 +1,3 @@
1
- export { wireScrollDividers } from './chunk-6STQXRT4.js';
1
+ export { wireScrollDividers } from './chunk-CXZXHZTR.js';
2
2
 
3
3
  //# sourceMappingURL=wire-scroll-dividers.js.map
@@ -1,3 +1,3 @@
1
- export { reorderTabs, wireTabBars } from './chunk-KQDU7Z7P.js';
1
+ export { reorderTabs, wireTabBars } from './chunk-K4AT3V3J.js';
2
2
 
3
3
  //# sourceMappingURL=wire-tab-bars.js.map
@@ -4,7 +4,9 @@ interface WireTabNavigatorOptions {
4
4
  }
5
5
  /**
6
6
  * Wire a `TabNavigator`'s bottom tab bar: clicking a tab calls `onSelect` with its
7
- * id (the app then updates its controlled `active`). Returns a disposer.
7
+ * id (the app then updates its controlled `active`). With
8
+ * `barPresentation="overlay"` it also measures the live bar and lays it over
9
+ * the scenes (see `TabNavigatorProps.barPresentation`). Returns a disposer.
8
10
  */
9
11
  declare function wireTabNavigator(root: Element, options: WireTabNavigatorOptions): () => void;
10
12
 
@@ -1,11 +1,138 @@
1
1
  import { delegate } from 'kerfjs';
2
2
 
3
3
  // src/components/navigation/tab-navigator/wiring/wire-tab-navigator.ts
4
+ var BAR_OVERLAY = "data-bar-overlay";
5
+ var BAR_BLOCK_SIZE = "--_kui-tab-scaffold-bar-block-size";
6
+ var BAR_SCROLLBAR_INLINE_SIZE = "--_kui-tab-scaffold-bar-scrollbar-inline-size";
7
+ var NESTED_LAYOUT = ["nav-stack", "split-view", "workbench", "tab-scaffold"].map((name) => `[data-component="${name}"]`).join(", ");
8
+ function paneScroller(pane) {
9
+ if (pane.querySelector(":scope > .kui-pane__footer")) return void 0;
10
+ return pane.querySelector(":scope > .kui-pane__content") ?? void 0;
11
+ }
12
+ function activeScroller(section) {
13
+ const scene = section.querySelector(
14
+ ':scope > .kui-tab-scaffold__scenes > .kui-tab-scaffold__scene[data-active="true"]'
15
+ );
16
+ if (!scene) return void 0;
17
+ const only = scene.children.length === 1 ? scene.children[0] : void 0;
18
+ if (!only?.matches(`[data-component="pane"], ${NESTED_LAYOUT}`)) return scene;
19
+ if (only.matches('[data-component="pane"]')) return paneScroller(only);
20
+ if (!only.matches('[data-component="nav-stack"]')) return void 0;
21
+ if (only.querySelector(":scope > [data-nav-stack-bottom]") && only.getAttribute("data-bottom-toolbar-presentation") !== "overlay")
22
+ return void 0;
23
+ const views = [
24
+ ...only.querySelectorAll(
25
+ ':scope > [data-nav-stack-viewport] > [data-nav-active="true"]:not([data-nav-exiting="true"])'
26
+ )
27
+ ];
28
+ const view = views.at(-1);
29
+ if (!view) return void 0;
30
+ const child = view.children.length === 1 ? view.children[0] : void 0;
31
+ if (child?.matches('[data-component="pane"]')) return paneScroller(child);
32
+ return child?.matches(NESTED_LAYOUT) ? void 0 : view;
33
+ }
34
+ function wireBarOverlay(section) {
35
+ const view = section.ownerDocument.defaultView ?? window;
36
+ let bar;
37
+ let size;
38
+ let scroller;
39
+ let scrollbarSize = 0;
40
+ const writeProperty = (name, value) => {
41
+ if (section.style.getPropertyValue(name) === value) return;
42
+ if (value) section.style.setProperty(name, value);
43
+ else section.style.removeProperty(name);
44
+ };
45
+ const publish = () => {
46
+ const measured = bar !== void 0 && size !== void 0;
47
+ writeProperty(BAR_BLOCK_SIZE, measured ? `${size}px` : "");
48
+ writeProperty(
49
+ BAR_SCROLLBAR_INLINE_SIZE,
50
+ measured && scrollbarSize > 0 ? `${scrollbarSize}px` : ""
51
+ );
52
+ if (section.getAttribute("style") === "") section.removeAttribute("style");
53
+ if (measured && section.getAttribute(BAR_OVERLAY) !== "measured")
54
+ section.setAttribute(BAR_OVERLAY, "measured");
55
+ else if (!measured && section.hasAttribute(BAR_OVERLAY))
56
+ section.removeAttribute(BAR_OVERLAY);
57
+ };
58
+ const measureScrollbar = () => {
59
+ if (!scroller) {
60
+ scrollbarSize = 0;
61
+ return;
62
+ }
63
+ const style = view.getComputedStyle(scroller);
64
+ scrollbarSize = Math.max(
65
+ 0,
66
+ scroller.offsetWidth - scroller.clientWidth - (Number.parseFloat(style.borderLeftWidth) || 0) - (Number.parseFloat(style.borderRightWidth) || 0)
67
+ );
68
+ };
69
+ const resizeObserver = view.ResizeObserver ? new view.ResizeObserver((entries) => {
70
+ for (const entry of entries)
71
+ if (entry.target === bar)
72
+ size = entry.borderBoxSize?.[0]?.blockSize ?? entry.target.getBoundingClientRect().height;
73
+ else if (entry.target === scroller) measureScrollbar();
74
+ publish();
75
+ }) : void 0;
76
+ const sync = () => {
77
+ const next = section.getAttribute("data-bar-presentation") === "overlay" ? section.querySelector(
78
+ ":scope > .kui-tab-scaffold__bar"
79
+ ) ?? void 0 : void 0;
80
+ if (next !== bar) {
81
+ if (bar) resizeObserver?.unobserve(bar);
82
+ bar = next;
83
+ if (!bar) size = void 0;
84
+ else {
85
+ if (size === void 0 || !resizeObserver)
86
+ size = bar.getBoundingClientRect().height;
87
+ resizeObserver?.observe(bar, { box: "border-box" });
88
+ }
89
+ }
90
+ const covered = bar ? activeScroller(section) : void 0;
91
+ if (covered !== scroller) {
92
+ if (scroller) resizeObserver?.unobserve(scroller);
93
+ scroller = covered;
94
+ measureScrollbar();
95
+ if (scroller) resizeObserver?.observe(scroller);
96
+ }
97
+ publish();
98
+ };
99
+ const mutationObserver = new MutationObserver(sync);
100
+ mutationObserver.observe(section, {
101
+ childList: true,
102
+ attributes: true,
103
+ attributeFilter: ["data-bar-presentation", BAR_OVERLAY, "style"]
104
+ });
105
+ const sceneObserver = new MutationObserver(sync);
106
+ const scenes = section.querySelector(":scope > .kui-tab-scaffold__scenes");
107
+ if (scenes)
108
+ sceneObserver.observe(scenes, {
109
+ childList: true,
110
+ subtree: true,
111
+ attributes: true,
112
+ attributeFilter: [
113
+ "data-active",
114
+ "data-nav-active",
115
+ "data-nav-exiting",
116
+ "data-bottom-toolbar-presentation"
117
+ ]
118
+ });
119
+ sync();
120
+ return () => {
121
+ mutationObserver.disconnect();
122
+ sceneObserver.disconnect();
123
+ resizeObserver?.disconnect();
124
+ bar = void 0;
125
+ size = void 0;
126
+ scroller = void 0;
127
+ scrollbarSize = 0;
128
+ publish();
129
+ };
130
+ }
4
131
  function wireTabNavigator(root, options) {
5
132
  const section = root.matches('[data-component="tab-scaffold"]') ? root : root.querySelector('[data-component="tab-scaffold"]');
6
133
  if (!(section instanceof HTMLElement)) return () => {
7
134
  };
8
- return delegate(
135
+ const stopClicks = delegate(
9
136
  section,
10
137
  "click",
11
138
  "[data-tab-scaffold-tab]",
@@ -14,6 +141,11 @@ function wireTabNavigator(root, options) {
14
141
  if (tabId) options.onSelect(tabId);
15
142
  }
16
143
  );
144
+ const stopOverlay = wireBarOverlay(section);
145
+ return () => {
146
+ stopClicks();
147
+ stopOverlay();
148
+ };
17
149
  }
18
150
 
19
151
  export { wireTabNavigator };
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/navigation/tab-navigator/wiring/wire-tab-navigator.ts"],"names":[],"mappings":";;;AAWO,SAAS,gBAAA,CACd,MACA,OAAA,EACY;AACZ,EAAA,MAAM,OAAA,GAAU,KAAK,OAAA,CAAQ,iCAAiC,IAC1D,IAAA,GACA,IAAA,CAAK,cAAc,iCAAiC,CAAA;AACxD,EAAA,IAAI,EAAE,OAAA,YAAmB,WAAA,CAAA,EAAc,OAAO,MAAM;AAAA,EAAC,CAAA;AACrD,EAAA,OAAO,QAAA;AAAA,IACL,OAAA;AAAA,IACA,OAAA;AAAA,IACA,yBAAA;AAAA,IACA,CAAC,QAAQ,MAAA,KAAW;AAClB,MAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,YAAA,CAAa,uBAAuB,CAAA;AACzD,MAAA,IAAI,KAAA,EAAO,OAAA,CAAQ,QAAA,CAAS,KAAK,CAAA;AAAA,IACnC;AAAA,GACF;AACF","file":"wire-tab-navigator.js","sourcesContent":["import { delegate } from 'kerfjs';\n\nexport interface WireTabNavigatorOptions {\n /** Invoked with the selected tab id when a bottom-bar tab is activated. */\n onSelect: (tabId: string) => void;\n}\n\n/**\n * Wire a `TabNavigator`'s bottom tab bar: clicking a tab calls `onSelect` with its\n * id (the app then updates its controlled `active`). Returns a disposer.\n */\nexport function wireTabNavigator(\n root: Element,\n options: WireTabNavigatorOptions,\n): () => void {\n const section = root.matches('[data-component=\"tab-scaffold\"]')\n ? root\n : root.querySelector('[data-component=\"tab-scaffold\"]');\n if (!(section instanceof HTMLElement)) return () => {};\n return delegate(\n section,\n 'click',\n '[data-tab-scaffold-tab]',\n (_event, target) => {\n const tabId = target.getAttribute('data-tab-scaffold-tab');\n if (tabId) options.onSelect(tabId);\n },\n );\n}\n"]}
1
+ {"version":3,"sources":["../src/components/navigation/tab-navigator/wiring/wire-tab-navigator.ts"],"names":[],"mappings":"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","file":"wire-tab-navigator.js","sourcesContent":["import { delegate } from 'kerfjs';\n\n/** On an overlay-bar TabNavigator: the wiring has measured its live bar. */\nconst BAR_OVERLAY = 'data-bar-overlay';\n/** The measured bar's border-box block size, published on the root. */\nconst BAR_BLOCK_SIZE = '--_kui-tab-scaffold-bar-block-size';\n/**\n * The inline size of the active scene's classic (space-taking) vertical\n * scrollbar running beneath the bar, which the bar leaves uncovered. Unset for\n * an overlay scrollbar, which takes no space.\n */\nconst BAR_SCROLLBAR_INLINE_SIZE =\n '--_kui-tab-scaffold-bar-scrollbar-inline-size';\n/** A layout that, as a scene's (or view's) only child, owns its scroller. */\nconst NESTED_LAYOUT = ['nav-stack', 'split-view', 'workbench', 'tab-scaffold']\n .map((name) => `[data-component=\"${name}\"]`)\n .join(', ');\n\n/**\n * A sole Pane's scroller when it reaches the bottom edge: its content, unless\n * a footer sits between the content and the bar.\n */\nfunction paneScroller(pane: Element): HTMLElement | undefined {\n if (pane.querySelector(':scope > .kui-pane__footer')) return undefined;\n return (\n pane.querySelector<HTMLElement>(':scope > .kui-pane__content') ?? undefined\n );\n}\n\n/**\n * The element whose vertical scrollbar runs beneath the bar in the active\n * scene: the scene itself; a sole Pane's content; or, in a sole NavStack\n * without a docked bottom toolbar, its active view (or that view's sole Pane's\n * content). Undefined when chrome (a Pane footer, a docked stack toolbar) or a\n * nested layout's own scroller ends above the bar.\n */\nfunction activeScroller(section: Element): HTMLElement | undefined {\n const scene = section.querySelector<HTMLElement>(\n ':scope > .kui-tab-scaffold__scenes > .kui-tab-scaffold__scene[data-active=\"true\"]',\n );\n if (!scene) return undefined;\n const only = scene.children.length === 1 ? scene.children[0]! : undefined;\n if (!only?.matches(`[data-component=\"pane\"], ${NESTED_LAYOUT}`)) return scene;\n if (only.matches('[data-component=\"pane\"]')) return paneScroller(only);\n if (!only.matches('[data-component=\"nav-stack\"]')) return undefined;\n if (\n only.querySelector(':scope > [data-nav-stack-bottom]') &&\n only.getAttribute('data-bottom-toolbar-presentation') !== 'overlay'\n )\n return undefined;\n const views = [\n ...only.querySelectorAll<HTMLElement>(\n ':scope > [data-nav-stack-viewport] > [data-nav-active=\"true\"]:not([data-nav-exiting=\"true\"])',\n ),\n ];\n const view = views.at(-1);\n if (!view) return undefined;\n const child = view.children.length === 1 ? view.children[0]! : undefined;\n if (child?.matches('[data-component=\"pane\"]')) return paneScroller(child);\n return child?.matches(NESTED_LAYOUT) ? undefined : view;\n}\n\n/**\n * `barPresentation=\"overlay\"`: measure the live tab bar's border box (bottom\n * safe area and its 1px top edge included) and publish it on the root with\n * the gate that lays the bar over the scenes. The size follows the bar as\n * labels wrap, text zooms, or the safe area changes, and a re-render that\n * replaces the bar or strips the published state gets it back before paint.\n */\nfunction wireBarOverlay(section: HTMLElement): () => void {\n const view = section.ownerDocument.defaultView ?? window;\n let bar: HTMLElement | undefined;\n let size: number | undefined;\n let scroller: HTMLElement | undefined;\n let scrollbarSize = 0;\n const writeProperty = (name: string, value: string): void => {\n if (section.style.getPropertyValue(name) === value) return;\n if (value) section.style.setProperty(name, value);\n else section.style.removeProperty(name);\n };\n const publish = (): void => {\n const measured = bar !== undefined && size !== undefined;\n writeProperty(BAR_BLOCK_SIZE, measured ? `${size}px` : '');\n writeProperty(\n BAR_SCROLLBAR_INLINE_SIZE,\n measured && scrollbarSize > 0 ? `${scrollbarSize}px` : '',\n );\n if (section.getAttribute('style') === '') section.removeAttribute('style');\n // The gate changes only when it must, so the observer below settles.\n if (measured && section.getAttribute(BAR_OVERLAY) !== 'measured')\n section.setAttribute(BAR_OVERLAY, 'measured');\n else if (!measured && section.hasAttribute(BAR_OVERLAY))\n section.removeAttribute(BAR_OVERLAY);\n };\n const measureScrollbar = (): void => {\n if (!scroller) {\n scrollbarSize = 0;\n return;\n }\n const style = view.getComputedStyle(scroller);\n scrollbarSize = Math.max(\n 0,\n scroller.offsetWidth -\n scroller.clientWidth -\n (Number.parseFloat(style.borderLeftWidth) || 0) -\n (Number.parseFloat(style.borderRightWidth) || 0),\n );\n };\n const resizeObserver = view.ResizeObserver\n ? new view.ResizeObserver((entries) => {\n for (const entry of entries)\n if (entry.target === bar)\n size =\n entry.borderBoxSize?.[0]?.blockSize ??\n entry.target.getBoundingClientRect().height;\n // A scrollbar appearing or leaving resizes the content box.\n else if (entry.target === scroller) measureScrollbar();\n publish();\n })\n : undefined;\n const sync = (): void => {\n const next =\n section.getAttribute('data-bar-presentation') === 'overlay'\n ? (section.querySelector<HTMLElement>(\n ':scope > .kui-tab-scaffold__bar',\n ) ?? undefined)\n : undefined;\n if (next !== bar) {\n if (bar) resizeObserver?.unobserve(bar);\n bar = next;\n if (!bar) size = undefined;\n else {\n // A replacement keeps the last size until the observer reports it\n // after layout; a first bar (or one with no observer) is measured now.\n if (size === undefined || !resizeObserver)\n size = bar.getBoundingClientRect().height;\n // The border box: a forced-colors edge changes no content box.\n resizeObserver?.observe(bar, { box: 'border-box' });\n }\n }\n // The active scroller changes with the active tab, a stack's push or pop,\n // or a re-render of the scene.\n const covered = bar ? activeScroller(section) : undefined;\n if (covered !== scroller) {\n if (scroller) resizeObserver?.unobserve(scroller);\n scroller = covered;\n measureScrollbar();\n if (scroller) resizeObserver?.observe(scroller);\n }\n publish();\n };\n const mutationObserver = new MutationObserver(sync);\n mutationObserver.observe(section, {\n childList: true,\n attributes: true,\n attributeFilter: ['data-bar-presentation', BAR_OVERLAY, 'style'],\n });\n // Scene switches and nested stack transitions below the root.\n const sceneObserver = new MutationObserver(sync);\n const scenes = section.querySelector(':scope > .kui-tab-scaffold__scenes');\n if (scenes)\n sceneObserver.observe(scenes, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: [\n 'data-active',\n 'data-nav-active',\n 'data-nav-exiting',\n 'data-bottom-toolbar-presentation',\n ],\n });\n sync();\n return () => {\n mutationObserver.disconnect();\n sceneObserver.disconnect();\n resizeObserver?.disconnect();\n bar = undefined;\n size = undefined;\n scroller = undefined;\n scrollbarSize = 0;\n publish();\n };\n}\n\nexport interface WireTabNavigatorOptions {\n /** Invoked with the selected tab id when a bottom-bar tab is activated. */\n onSelect: (tabId: string) => void;\n}\n\n/**\n * Wire a `TabNavigator`'s bottom tab bar: clicking a tab calls `onSelect` with its\n * id (the app then updates its controlled `active`). With\n * `barPresentation=\"overlay\"` it also measures the live bar and lays it over\n * the scenes (see `TabNavigatorProps.barPresentation`). Returns a disposer.\n */\nexport function wireTabNavigator(\n root: Element,\n options: WireTabNavigatorOptions,\n): () => void {\n const section = root.matches('[data-component=\"tab-scaffold\"]')\n ? root\n : root.querySelector('[data-component=\"tab-scaffold\"]');\n if (!(section instanceof HTMLElement)) return () => {};\n const stopClicks = delegate(\n section,\n 'click',\n '[data-tab-scaffold-tab]',\n (_event, target) => {\n const tabId = target.getAttribute('data-tab-scaffold-tab');\n if (tabId) options.onSelect(tabId);\n },\n );\n const stopOverlay = wireBarOverlay(section);\n return () => {\n stopClicks();\n stopOverlay();\n };\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  import { Signal } from 'kerfjs';
2
- import { d as TokenSearchModel } from './token-search-model-DTcTXWMS.js';
2
+ import { d as TokenSearchModel } from './token-search-model-aYR0YAei.js';
3
3
  import './semantic-content-BbzjvSu9.js';
4
4
 
5
5
  interface TokenSearchSubmit {
@@ -1,4 +1,4 @@
1
- export { wireTokenSearchFields } from './chunk-Y3LC7JQO.js';
1
+ export { wireTokenSearchFields } from './chunk-YOA5W5ZH.js';
2
2
 
3
3
 
4
4
 
@@ -1,15 +1,16 @@
1
1
  import { SafeHtml } from 'kerfjs';
2
2
  import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
3
- import { b as NavPane, N as NavStackProps } from './nav-stack-Cp3Y8kJ9.js';
3
+ import { b as NavPane, N as NavStackProps } from './nav-stack-VXTumzKa.js';
4
4
  import { ListConfig } from './list.js';
5
5
  import { PaneConfig } from './pane.js';
6
6
  import { ResizableRegionSeparator, ResizableRegionCollapseMotion, ResizableRegionContentOverflow, ResizableRegionPresentation, ResizableRegionRestorePosition } from './resizable-region.js';
7
- import { a as PanelToolbar, c as PanelBottomToolbar, b as PanelChromePlacement, d as PanelToggle } from './panel-toolbar-CL9tYOkh.js';
7
+ import { a as PanelToolbar, c as PanelBottomToolbar, b as PanelChromePlacement, d as PanelToggle } from './panel-toolbar-vg6Ir5Dy.js';
8
8
  import { ToolbarConfig } from './toolbar.js';
9
9
  import './toolbar-text.js';
10
10
  import './css-values.js';
11
11
  import './extension-attributes-mu8MFUl0.js';
12
12
  import './flex-alignment-4ms8ZbV8.js';
13
+ import './scroll-clearance-BikHljTc.js';
13
14
  import './sides-BPSWde0A.js';
14
15
  import './lucide-icon.js';
15
16
  import 'lucide';
@@ -100,7 +101,11 @@ interface WorkbenchPanelBase {
100
101
  * with `wireWorkbench` from `@kerfjs/ui/wire-workbench`.
101
102
  */
102
103
  resizable?: boolean | WorkbenchPanelResizable;
103
- /** Accessible name for the panel region. */
104
+ /**
105
+ * Accessible name for the panel region, in title style. A resizable
106
+ * panel's handle is named "Resize {label}", or "Resize Left Rail" /
107
+ * "Resize Right Rail" / "Resize Bottom Drawer" without one.
108
+ */
104
109
  label?: string;
105
110
  /** Opt into keyboard (`0`) or programmatic (`-1`) focus on the panel region. */
106
111
  tabIndex?: 0 | -1;
package/dist/workbench.js CHANGED
@@ -1,4 +1,5 @@
1
- export { Workbench } from './chunk-527IAEWG.js';
1
+ export { Workbench } from './chunk-PYBBYSZ3.js';
2
+
2
3
 
3
4
 
4
5