@womp/kookie-ui 0.26.2 → 0.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (340) hide show
  1. package/components.css +165 -4
  2. package/dist/cjs/components/_internal/base-button.js +1 -1
  3. package/dist/cjs/components/_internal/base-button.js.map +2 -2
  4. package/dist/cjs/components/_internal/pane-band-context.d.ts +4 -3
  5. package/dist/cjs/components/_internal/pane-band-context.d.ts.map +1 -1
  6. package/dist/cjs/components/_internal/pane-band-context.js.map +2 -2
  7. package/dist/cjs/components/_internal/pane-chrome.d.ts +7 -1
  8. package/dist/cjs/components/_internal/pane-chrome.d.ts.map +1 -1
  9. package/dist/cjs/components/_internal/pane-chrome.js +1 -1
  10. package/dist/cjs/components/_internal/pane-chrome.js.map +4 -4
  11. package/dist/cjs/components/_internal/portal-theme.d.ts +9 -0
  12. package/dist/cjs/components/_internal/portal-theme.d.ts.map +1 -0
  13. package/dist/cjs/components/_internal/portal-theme.js +3 -0
  14. package/dist/cjs/components/_internal/portal-theme.js.map +7 -0
  15. package/dist/cjs/components/_internal/shell-page-scroll.d.ts +15 -0
  16. package/dist/cjs/components/_internal/shell-page-scroll.d.ts.map +1 -0
  17. package/dist/cjs/components/_internal/shell-page-scroll.js +3 -0
  18. package/dist/cjs/components/_internal/shell-page-scroll.js.map +7 -0
  19. package/dist/cjs/components/_internal/shell-sidebar.js +1 -1
  20. package/dist/cjs/components/_internal/shell-sidebar.js.map +4 -4
  21. package/dist/cjs/components/alert-dialog.js +1 -1
  22. package/dist/cjs/components/alert-dialog.js.map +4 -4
  23. package/dist/cjs/components/button.js +1 -1
  24. package/dist/cjs/components/button.js.map +4 -4
  25. package/dist/cjs/components/chatbar.js +1 -1
  26. package/dist/cjs/components/chatbar.js.map +4 -4
  27. package/dist/cjs/components/chip.js +1 -1
  28. package/dist/cjs/components/chip.js.map +4 -4
  29. package/dist/cjs/components/combobox.d.ts.map +1 -1
  30. package/dist/cjs/components/combobox.js +1 -1
  31. package/dist/cjs/components/combobox.js.map +4 -4
  32. package/dist/cjs/components/context-menu.d.ts.map +1 -1
  33. package/dist/cjs/components/context-menu.js +1 -1
  34. package/dist/cjs/components/context-menu.js.map +4 -4
  35. package/dist/cjs/components/dialog.js +1 -1
  36. package/dist/cjs/components/dialog.js.map +4 -4
  37. package/dist/cjs/components/dropdown-menu.d.ts.map +1 -1
  38. package/dist/cjs/components/dropdown-menu.js +1 -1
  39. package/dist/cjs/components/dropdown-menu.js.map +4 -4
  40. package/dist/cjs/components/index.js +2 -2
  41. package/dist/cjs/components/index.js.map +4 -4
  42. package/dist/cjs/components/message-scroller.js +1 -1
  43. package/dist/cjs/components/message-scroller.js.map +4 -4
  44. package/dist/cjs/components/notice.js +1 -1
  45. package/dist/cjs/components/notice.js.map +4 -4
  46. package/dist/cjs/components/popover.js +1 -1
  47. package/dist/cjs/components/popover.js.map +4 -4
  48. package/dist/cjs/components/schemas/index.js +1 -1
  49. package/dist/cjs/components/schemas/index.js.map +2 -2
  50. package/dist/cjs/components/schemas/shell.schema.d.ts +1 -0
  51. package/dist/cjs/components/schemas/shell.schema.d.ts.map +1 -1
  52. package/dist/cjs/components/schemas/shell.schema.js +1 -1
  53. package/dist/cjs/components/schemas/shell.schema.js.map +2 -2
  54. package/dist/cjs/components/select.d.ts.map +1 -1
  55. package/dist/cjs/components/select.js +1 -1
  56. package/dist/cjs/components/select.js.map +4 -4
  57. package/dist/cjs/components/sheet.js +1 -1
  58. package/dist/cjs/components/sheet.js.map +4 -4
  59. package/dist/cjs/components/shell.d.ts +11 -0
  60. package/dist/cjs/components/shell.d.ts.map +1 -1
  61. package/dist/cjs/components/shell.js +1 -1
  62. package/dist/cjs/components/shell.js.map +4 -4
  63. package/dist/cjs/components/sidebar.js +1 -1
  64. package/dist/cjs/components/sidebar.js.map +4 -4
  65. package/dist/cjs/components/spinner.d.ts.map +1 -1
  66. package/dist/cjs/components/spinner.js +1 -1
  67. package/dist/cjs/components/spinner.js.map +2 -2
  68. package/dist/cjs/components/text-area.d.ts.map +1 -1
  69. package/dist/cjs/components/text-area.js +1 -1
  70. package/dist/cjs/components/text-area.js.map +2 -2
  71. package/dist/cjs/components/text-field.d.ts.map +1 -1
  72. package/dist/cjs/components/text-field.js +2 -2
  73. package/dist/cjs/components/text-field.js.map +2 -2
  74. package/dist/cjs/components/theme.d.ts.map +1 -1
  75. package/dist/cjs/components/theme.js +1 -1
  76. package/dist/cjs/components/theme.js.map +4 -4
  77. package/dist/cjs/components/toggle.js +1 -1
  78. package/dist/cjs/components/toggle.js.map +4 -4
  79. package/dist/cjs/components/toolbar.js +1 -1
  80. package/dist/cjs/components/toolbar.js.map +4 -4
  81. package/dist/cjs/components/tooltip.js +1 -1
  82. package/dist/cjs/components/tooltip.js.map +4 -4
  83. package/dist/cjs/index.js +4 -4
  84. package/dist/cjs/index.js.map +4 -4
  85. package/dist/esm/{chunk-6M6HGIGN.js → chunk-25ZRMILM.js} +2 -2
  86. package/dist/esm/chunk-2E57H3NH.js +3 -0
  87. package/dist/esm/chunk-2E57H3NH.js.map +7 -0
  88. package/dist/esm/chunk-2S7HPQVX.js +3 -0
  89. package/dist/esm/chunk-2S7HPQVX.js.map +7 -0
  90. package/dist/esm/{chunk-UG73IGRF.js → chunk-2ZKEQS76.js} +2 -2
  91. package/dist/esm/{chunk-H2TSRYQ5.js → chunk-324VC67W.js} +2 -2
  92. package/dist/esm/{chunk-UR5BUNNT.js → chunk-3MFSQ6PN.js} +2 -2
  93. package/dist/esm/{chunk-OTCVSJT7.js → chunk-4MNRLB57.js} +2 -2
  94. package/dist/esm/{chunk-TFFU435D.js → chunk-5BX2YZV6.js} +2 -2
  95. package/dist/esm/chunk-5BX2YZV6.js.map +7 -0
  96. package/dist/esm/chunk-67UEMB4K.js +3 -0
  97. package/dist/esm/chunk-67UEMB4K.js.map +7 -0
  98. package/dist/esm/chunk-6HEORZNJ.js +3 -0
  99. package/dist/esm/chunk-6HEORZNJ.js.map +7 -0
  100. package/dist/esm/{chunk-K55IQP5H.js → chunk-6YWHNLSC.js} +2 -2
  101. package/dist/esm/chunk-6YWHNLSC.js.map +7 -0
  102. package/dist/esm/{chunk-NYBE3U3V.js → chunk-7QBNXNEN.js} +2 -2
  103. package/dist/esm/{chunk-E6BDD3PN.js → chunk-7V6M3MIR.js} +2 -2
  104. package/dist/esm/{chunk-KQIZMPSW.js → chunk-ANQLWGFN.js} +1 -1
  105. package/dist/esm/{chunk-KQIZMPSW.js.map → chunk-ANQLWGFN.js.map} +2 -2
  106. package/dist/esm/chunk-AQKSO3SW.js +3 -0
  107. package/dist/esm/chunk-AQKSO3SW.js.map +7 -0
  108. package/dist/esm/{chunk-ONJYRJ66.js → chunk-B6OFKABP.js} +2 -2
  109. package/dist/esm/chunk-BUXK5VGR.js +3 -0
  110. package/dist/esm/chunk-BUXK5VGR.js.map +7 -0
  111. package/dist/esm/{chunk-7QP6JFPO.js → chunk-C67MM24U.js} +2 -2
  112. package/dist/esm/chunk-CZ24FOFS.js +3 -0
  113. package/dist/esm/chunk-CZ24FOFS.js.map +7 -0
  114. package/dist/esm/{chunk-LFAUMDU5.js → chunk-D2C2A2ZK.js} +2 -2
  115. package/dist/esm/{chunk-UBUGG2OB.js → chunk-DP7MPGR7.js} +2 -2
  116. package/dist/esm/{chunk-BVQDDN5Q.js → chunk-EB4AG3OL.js} +2 -2
  117. package/dist/esm/{chunk-5PQCTVZB.js → chunk-ENQV6SEA.js} +2 -2
  118. package/dist/esm/{chunk-VVLUY4WR.js → chunk-EPGIYTFK.js} +2 -2
  119. package/dist/esm/{chunk-2TWPPDII.js → chunk-FMVOB367.js} +2 -2
  120. package/dist/esm/chunk-FVRVBB6O.js +3 -0
  121. package/dist/esm/chunk-FVRVBB6O.js.map +7 -0
  122. package/dist/esm/{chunk-TFFMELAL.js → chunk-FYTLUDL3.js} +2 -2
  123. package/dist/esm/{chunk-W4CPV4PO.js → chunk-H2J25HXP.js} +2 -2
  124. package/dist/esm/{chunk-C2WKAIZM.js → chunk-H73AMXCH.js} +2 -2
  125. package/dist/esm/{chunk-AJANJ22M.js → chunk-HBO7W7SS.js} +2 -2
  126. package/dist/esm/{chunk-F364PDDM.js → chunk-HLIOHDEX.js} +2 -2
  127. package/dist/esm/{chunk-5FWEGTP6.js → chunk-HR2VHGJ5.js} +2 -2
  128. package/dist/esm/chunk-HR2VHGJ5.js.map +7 -0
  129. package/dist/esm/{chunk-ZKQCSGL3.js → chunk-ISCZ57VL.js} +2 -2
  130. package/dist/esm/{chunk-TFGUTYZK.js → chunk-J54GYD7A.js} +2 -2
  131. package/dist/esm/{chunk-HVMRB3AH.js → chunk-JD4KR6VZ.js} +2 -2
  132. package/dist/esm/{chunk-MS2ONKJJ.js → chunk-JKQN6QCP.js} +2 -2
  133. package/dist/esm/{chunk-NS573D6O.js → chunk-JP36JSNP.js} +2 -2
  134. package/dist/esm/chunk-K3GDM26A.js +3 -0
  135. package/dist/esm/{chunk-M7IQIKB4.js.map → chunk-K3GDM26A.js.map} +2 -2
  136. package/dist/esm/{chunk-ULCHGKI3.js → chunk-KJZSXLIX.js} +2 -2
  137. package/dist/esm/{chunk-N3B6EGXL.js → chunk-LABMK6Q7.js} +2 -2
  138. package/dist/esm/{chunk-VIVM525H.js → chunk-MGWGD6KI.js} +2 -2
  139. package/dist/esm/{chunk-RD4T2MCC.js → chunk-MJKVVGGV.js} +2 -2
  140. package/dist/esm/chunk-MJKVVGGV.js.map +7 -0
  141. package/dist/esm/{chunk-TXVZOS3E.js → chunk-MMDZBPSX.js} +2 -2
  142. package/dist/esm/{chunk-EERKYRYI.js → chunk-NWXODCTD.js} +2 -2
  143. package/dist/esm/{chunk-VCZ2GYOF.js → chunk-Q5SANVIW.js} +2 -2
  144. package/dist/esm/chunk-QEDKL23P.js +3 -0
  145. package/dist/esm/chunk-QEDKL23P.js.map +7 -0
  146. package/dist/esm/{chunk-LGZCNQBS.js → chunk-QPRUTOLI.js} +2 -2
  147. package/dist/esm/{chunk-TTW3EAQT.js → chunk-QRV32INS.js} +2 -2
  148. package/dist/esm/{chunk-3QN4C5LW.js → chunk-REORAMUH.js} +2 -2
  149. package/dist/esm/{chunk-GOXGRJO6.js → chunk-SUQJ7DD4.js} +2 -2
  150. package/dist/esm/chunk-TSWHVZ47.js +3 -0
  151. package/dist/esm/chunk-TSWHVZ47.js.map +7 -0
  152. package/dist/esm/chunk-VQDCHBZR.js +3 -0
  153. package/dist/esm/chunk-VQDCHBZR.js.map +7 -0
  154. package/dist/esm/{chunk-TF6WAIUQ.js → chunk-W4Z6ORYO.js} +2 -2
  155. package/dist/esm/{chunk-F2722F7B.js → chunk-WAXRIARV.js} +2 -2
  156. package/dist/esm/chunk-WAXRIARV.js.map +7 -0
  157. package/dist/esm/{chunk-ADL3LEOQ.js → chunk-WD66RYF6.js} +2 -2
  158. package/dist/esm/{chunk-DIY2XQKR.js → chunk-X7JHZ3HA.js} +2 -2
  159. package/dist/esm/{chunk-H33NTGVF.js → chunk-XD3C3GVF.js} +2 -2
  160. package/dist/esm/{chunk-VPUFKJQA.js → chunk-YMUERC2J.js} +2 -2
  161. package/dist/esm/chunk-ZOUIIO4C.js +6 -0
  162. package/dist/esm/chunk-ZOUIIO4C.js.map +7 -0
  163. package/dist/esm/components/_internal/base-button.js +1 -1
  164. package/dist/esm/components/_internal/base-menu.utils.js +1 -1
  165. package/dist/esm/components/_internal/menu-context.js +1 -1
  166. package/dist/esm/components/_internal/pane-band-context.d.ts +4 -3
  167. package/dist/esm/components/_internal/pane-band-context.d.ts.map +1 -1
  168. package/dist/esm/components/_internal/pane-band-context.js +1 -1
  169. package/dist/esm/components/_internal/pane-chrome.d.ts +7 -1
  170. package/dist/esm/components/_internal/pane-chrome.d.ts.map +1 -1
  171. package/dist/esm/components/_internal/pane-chrome.js +1 -1
  172. package/dist/esm/components/_internal/portal-theme.d.ts +9 -0
  173. package/dist/esm/components/_internal/portal-theme.d.ts.map +1 -0
  174. package/dist/esm/components/_internal/portal-theme.js +3 -0
  175. package/dist/esm/components/_internal/portal-theme.js.map +7 -0
  176. package/dist/esm/components/_internal/shell-bottom.js +1 -1
  177. package/dist/esm/components/_internal/shell-inspector.js +1 -1
  178. package/dist/esm/components/_internal/shell-page-scroll.d.ts +15 -0
  179. package/dist/esm/components/_internal/shell-page-scroll.d.ts.map +1 -0
  180. package/dist/esm/components/_internal/shell-page-scroll.js +3 -0
  181. package/dist/esm/components/_internal/shell-page-scroll.js.map +7 -0
  182. package/dist/esm/components/_internal/shell-sidebar.js +1 -1
  183. package/dist/esm/components/accordion.js +1 -1
  184. package/dist/esm/components/alert-dialog.js +1 -1
  185. package/dist/esm/components/avatar.js +1 -1
  186. package/dist/esm/components/blockquote.js +1 -1
  187. package/dist/esm/components/box.js +1 -1
  188. package/dist/esm/components/button.js +1 -1
  189. package/dist/esm/components/card.js +1 -1
  190. package/dist/esm/components/chatbar.js +1 -1
  191. package/dist/esm/components/checkbox-group.js +1 -1
  192. package/dist/esm/components/checkbox.js +1 -1
  193. package/dist/esm/components/chip.js +1 -1
  194. package/dist/esm/components/code.js +1 -1
  195. package/dist/esm/components/combobox.d.ts.map +1 -1
  196. package/dist/esm/components/combobox.js +1 -1
  197. package/dist/esm/components/context-menu.d.ts.map +1 -1
  198. package/dist/esm/components/context-menu.js +1 -1
  199. package/dist/esm/components/dialog.js +1 -1
  200. package/dist/esm/components/dropdown-menu.d.ts.map +1 -1
  201. package/dist/esm/components/dropdown-menu.js +1 -1
  202. package/dist/esm/components/flex.js +1 -1
  203. package/dist/esm/components/grid.js +1 -1
  204. package/dist/esm/components/heading.js +1 -1
  205. package/dist/esm/components/image.js +1 -1
  206. package/dist/esm/components/index.js +1 -1
  207. package/dist/esm/components/kbd.js +1 -1
  208. package/dist/esm/components/link.js +1 -1
  209. package/dist/esm/components/message-scroller.js +1 -1
  210. package/dist/esm/components/navbar.js +1 -1
  211. package/dist/esm/components/notice.js +1 -1
  212. package/dist/esm/components/popover.js +1 -1
  213. package/dist/esm/components/progress.js +1 -1
  214. package/dist/esm/components/radio-group.js +1 -1
  215. package/dist/esm/components/radio.js +1 -1
  216. package/dist/esm/components/schemas/index.js +1 -1
  217. package/dist/esm/components/schemas/shell.schema.d.ts +1 -0
  218. package/dist/esm/components/schemas/shell.schema.d.ts.map +1 -1
  219. package/dist/esm/components/schemas/shell.schema.js +1 -1
  220. package/dist/esm/components/scroll-area.js +1 -1
  221. package/dist/esm/components/segmented-control.js +1 -1
  222. package/dist/esm/components/select.d.ts.map +1 -1
  223. package/dist/esm/components/select.js +1 -1
  224. package/dist/esm/components/separator.js +1 -1
  225. package/dist/esm/components/sheet.js +1 -1
  226. package/dist/esm/components/shell.d.ts +11 -0
  227. package/dist/esm/components/shell.d.ts.map +1 -1
  228. package/dist/esm/components/shell.js +1 -1
  229. package/dist/esm/components/sidebar.js +1 -1
  230. package/dist/esm/components/slider.js +1 -1
  231. package/dist/esm/components/spinner.d.ts.map +1 -1
  232. package/dist/esm/components/spinner.js +1 -1
  233. package/dist/esm/components/switch.js +1 -1
  234. package/dist/esm/components/table.js +1 -1
  235. package/dist/esm/components/tabs.js +1 -1
  236. package/dist/esm/components/text-area.d.ts.map +1 -1
  237. package/dist/esm/components/text-area.js +1 -1
  238. package/dist/esm/components/text-field.d.ts.map +1 -1
  239. package/dist/esm/components/text-field.js +1 -1
  240. package/dist/esm/components/text.js +1 -1
  241. package/dist/esm/components/theme.d.ts.map +1 -1
  242. package/dist/esm/components/theme.js +1 -1
  243. package/dist/esm/components/toggle.js +1 -1
  244. package/dist/esm/components/toolbar.js +1 -1
  245. package/dist/esm/components/tooltip.js +1 -1
  246. package/dist/esm/components/virtual-menu.js +1 -1
  247. package/dist/esm/index.js +1 -1
  248. package/package.json +1 -1
  249. package/schemas/index.json +6 -1
  250. package/schemas/shell-root.json +6 -1
  251. package/src/components/_internal/pane-band-context.ts +4 -3
  252. package/src/components/_internal/pane-chrome.tsx +15 -2
  253. package/src/components/_internal/portal-theme.tsx +18 -0
  254. package/src/components/_internal/shell-page-scroll.ts +49 -0
  255. package/src/components/alert-dialog.tsx +3 -3
  256. package/src/components/combobox.tsx +4 -3
  257. package/src/components/context-menu.tsx +6 -5
  258. package/src/components/dialog.tsx +3 -3
  259. package/src/components/dropdown-menu.tsx +6 -5
  260. package/src/components/popover.tsx +3 -3
  261. package/src/components/schemas/shell.schema.ts +4 -1
  262. package/src/components/select.tsx +4 -3
  263. package/src/components/sheet.tsx +3 -3
  264. package/src/components/shell.css +201 -0
  265. package/src/components/shell.tsx +128 -22
  266. package/src/components/spinner.css +16 -1
  267. package/src/components/spinner.tsx +14 -13
  268. package/src/components/text-area.css +7 -2
  269. package/src/components/text-area.tsx +10 -8
  270. package/src/components/text-field.css +7 -2
  271. package/src/components/text-field.tsx +10 -8
  272. package/src/components/theme.tsx +24 -30
  273. package/src/components/tooltip.tsx +3 -3
  274. package/styles.css +165 -4
  275. package/dist/esm/chunk-3C4Q6PMS.js +0 -3
  276. package/dist/esm/chunk-3C4Q6PMS.js.map +0 -7
  277. package/dist/esm/chunk-3ZWHKNHI.js +0 -3
  278. package/dist/esm/chunk-3ZWHKNHI.js.map +0 -7
  279. package/dist/esm/chunk-457Z4R5W.js +0 -3
  280. package/dist/esm/chunk-457Z4R5W.js.map +0 -7
  281. package/dist/esm/chunk-5FWEGTP6.js.map +0 -7
  282. package/dist/esm/chunk-5MEWNLNH.js +0 -3
  283. package/dist/esm/chunk-5MEWNLNH.js.map +0 -7
  284. package/dist/esm/chunk-BEHAT3GI.js +0 -3
  285. package/dist/esm/chunk-BEHAT3GI.js.map +0 -7
  286. package/dist/esm/chunk-DG2KIH54.js +0 -6
  287. package/dist/esm/chunk-DG2KIH54.js.map +0 -7
  288. package/dist/esm/chunk-DQCE7DHY.js +0 -3
  289. package/dist/esm/chunk-DQCE7DHY.js.map +0 -7
  290. package/dist/esm/chunk-F2722F7B.js.map +0 -7
  291. package/dist/esm/chunk-GE7FRBZ4.js +0 -3
  292. package/dist/esm/chunk-GE7FRBZ4.js.map +0 -7
  293. package/dist/esm/chunk-K55IQP5H.js.map +0 -7
  294. package/dist/esm/chunk-M7IQIKB4.js +0 -3
  295. package/dist/esm/chunk-POP5NB33.js +0 -3
  296. package/dist/esm/chunk-POP5NB33.js.map +0 -7
  297. package/dist/esm/chunk-RD4T2MCC.js.map +0 -7
  298. package/dist/esm/chunk-SCIFT27R.js +0 -3
  299. package/dist/esm/chunk-SCIFT27R.js.map +0 -7
  300. package/dist/esm/chunk-TFFU435D.js.map +0 -7
  301. /package/dist/esm/{chunk-6M6HGIGN.js.map → chunk-25ZRMILM.js.map} +0 -0
  302. /package/dist/esm/{chunk-UG73IGRF.js.map → chunk-2ZKEQS76.js.map} +0 -0
  303. /package/dist/esm/{chunk-H2TSRYQ5.js.map → chunk-324VC67W.js.map} +0 -0
  304. /package/dist/esm/{chunk-UR5BUNNT.js.map → chunk-3MFSQ6PN.js.map} +0 -0
  305. /package/dist/esm/{chunk-OTCVSJT7.js.map → chunk-4MNRLB57.js.map} +0 -0
  306. /package/dist/esm/{chunk-NYBE3U3V.js.map → chunk-7QBNXNEN.js.map} +0 -0
  307. /package/dist/esm/{chunk-E6BDD3PN.js.map → chunk-7V6M3MIR.js.map} +0 -0
  308. /package/dist/esm/{chunk-ONJYRJ66.js.map → chunk-B6OFKABP.js.map} +0 -0
  309. /package/dist/esm/{chunk-7QP6JFPO.js.map → chunk-C67MM24U.js.map} +0 -0
  310. /package/dist/esm/{chunk-LFAUMDU5.js.map → chunk-D2C2A2ZK.js.map} +0 -0
  311. /package/dist/esm/{chunk-UBUGG2OB.js.map → chunk-DP7MPGR7.js.map} +0 -0
  312. /package/dist/esm/{chunk-BVQDDN5Q.js.map → chunk-EB4AG3OL.js.map} +0 -0
  313. /package/dist/esm/{chunk-5PQCTVZB.js.map → chunk-ENQV6SEA.js.map} +0 -0
  314. /package/dist/esm/{chunk-VVLUY4WR.js.map → chunk-EPGIYTFK.js.map} +0 -0
  315. /package/dist/esm/{chunk-2TWPPDII.js.map → chunk-FMVOB367.js.map} +0 -0
  316. /package/dist/esm/{chunk-TFFMELAL.js.map → chunk-FYTLUDL3.js.map} +0 -0
  317. /package/dist/esm/{chunk-W4CPV4PO.js.map → chunk-H2J25HXP.js.map} +0 -0
  318. /package/dist/esm/{chunk-C2WKAIZM.js.map → chunk-H73AMXCH.js.map} +0 -0
  319. /package/dist/esm/{chunk-AJANJ22M.js.map → chunk-HBO7W7SS.js.map} +0 -0
  320. /package/dist/esm/{chunk-F364PDDM.js.map → chunk-HLIOHDEX.js.map} +0 -0
  321. /package/dist/esm/{chunk-ZKQCSGL3.js.map → chunk-ISCZ57VL.js.map} +0 -0
  322. /package/dist/esm/{chunk-TFGUTYZK.js.map → chunk-J54GYD7A.js.map} +0 -0
  323. /package/dist/esm/{chunk-HVMRB3AH.js.map → chunk-JD4KR6VZ.js.map} +0 -0
  324. /package/dist/esm/{chunk-MS2ONKJJ.js.map → chunk-JKQN6QCP.js.map} +0 -0
  325. /package/dist/esm/{chunk-NS573D6O.js.map → chunk-JP36JSNP.js.map} +0 -0
  326. /package/dist/esm/{chunk-ULCHGKI3.js.map → chunk-KJZSXLIX.js.map} +0 -0
  327. /package/dist/esm/{chunk-N3B6EGXL.js.map → chunk-LABMK6Q7.js.map} +0 -0
  328. /package/dist/esm/{chunk-VIVM525H.js.map → chunk-MGWGD6KI.js.map} +0 -0
  329. /package/dist/esm/{chunk-TXVZOS3E.js.map → chunk-MMDZBPSX.js.map} +0 -0
  330. /package/dist/esm/{chunk-EERKYRYI.js.map → chunk-NWXODCTD.js.map} +0 -0
  331. /package/dist/esm/{chunk-VCZ2GYOF.js.map → chunk-Q5SANVIW.js.map} +0 -0
  332. /package/dist/esm/{chunk-LGZCNQBS.js.map → chunk-QPRUTOLI.js.map} +0 -0
  333. /package/dist/esm/{chunk-TTW3EAQT.js.map → chunk-QRV32INS.js.map} +0 -0
  334. /package/dist/esm/{chunk-3QN4C5LW.js.map → chunk-REORAMUH.js.map} +0 -0
  335. /package/dist/esm/{chunk-GOXGRJO6.js.map → chunk-SUQJ7DD4.js.map} +0 -0
  336. /package/dist/esm/{chunk-TF6WAIUQ.js.map → chunk-W4Z6ORYO.js.map} +0 -0
  337. /package/dist/esm/{chunk-ADL3LEOQ.js.map → chunk-WD66RYF6.js.map} +0 -0
  338. /package/dist/esm/{chunk-DIY2XQKR.js.map → chunk-X7JHZ3HA.js.map} +0 -0
  339. /package/dist/esm/{chunk-H33NTGVF.js.map → chunk-XD3C3GVF.js.map} +0 -0
  340. /package/dist/esm/{chunk-VPUFKJQA.js.map → chunk-YMUERC2J.js.map} +0 -0
@@ -30,6 +30,8 @@
30
30
  --shell-inset-gap: var(--space-3);
31
31
  /* Written inline by the Root while a Rail shows; stated here so a nested Shell never inherits its parent's. */
32
32
  --shell-rail-offset: 0px;
33
+ /* How far the stuck header reaches down the screen while the page scrolls. Stated here so a nested Shell never inherits its parent's. */
34
+ --kui-shell-page-top: 0px;
33
35
 
34
36
  display: grid;
35
37
  grid-template-areas:
@@ -58,6 +60,14 @@
58
60
  }
59
61
  }
60
62
 
63
+ /*
64
+ * A contained Shell fills its parent instead of the window. An explicit `height` is written
65
+ * inline and wins over this.
66
+ */
67
+ .kui-ShellRoot[data-contained] {
68
+ height: 100%;
69
+ }
70
+
61
71
  /* While an overlay is live the page holds still. Counted across Shells by the Root. */
62
72
  :root[data-kui-shell-lock] {
63
73
  overflow: hidden;
@@ -115,6 +125,8 @@
115
125
  --kui-pane-band-end: initial;
116
126
  --kui-shell-position: initial;
117
127
  --kui-shell-z: initial;
128
+ --kui-shell-pin: initial;
129
+ --kui-shell-pin-top: initial;
118
130
  --kui-shell-row: initial;
119
131
  --kui-shell-col: initial;
120
132
  --kui-shell-surface: initial;
@@ -470,6 +482,8 @@
470
482
  .kui-ShellRail[data-presentation='overlay'] ~ .kui-ShellPanel[data-presentation-follows] {
471
483
  --kui-shell-position: absolute;
472
484
  --kui-shell-z: 6;
485
+ --kui-shell-pin: fixed;
486
+ --kui-shell-pin-top: 0px;
473
487
  --kui-shell-row: 1 / -1;
474
488
  --kui-shell-col: 1 / -1;
475
489
  --kui-shell-surface: var(--color-surface);
@@ -484,6 +498,8 @@
484
498
  .kui-ShellRail[data-presentation='stacked'] ~ .kui-ShellPanel[data-presentation-follows] {
485
499
  --kui-shell-position: absolute;
486
500
  --kui-shell-z: 3;
501
+ --kui-shell-pin: fixed;
502
+ --kui-shell-pin-top: initial;
487
503
  --kui-shell-row: 2 / 3;
488
504
  --kui-shell-col: 1 / -1;
489
505
  --kui-shell-surface: var(--color-surface);
@@ -503,6 +519,8 @@
503
519
  .kui-ShellRail[data-presentation-initial='fixed'] ~ .kui-ShellPanel[data-presentation-follows] {
504
520
  --kui-shell-position: initial;
505
521
  --kui-shell-z: initial;
522
+ --kui-shell-pin: initial;
523
+ --kui-shell-pin-top: initial;
506
524
  --kui-shell-row: initial;
507
525
  --kui-shell-col: initial;
508
526
  --kui-shell-surface: initial;
@@ -517,6 +535,8 @@
517
535
  .kui-ShellRail[data-presentation-initial='overlay'] ~ .kui-ShellPanel[data-presentation-follows] {
518
536
  --kui-shell-position: absolute;
519
537
  --kui-shell-z: 6;
538
+ --kui-shell-pin: fixed;
539
+ --kui-shell-pin-top: 0px;
520
540
  --kui-shell-row: 1 / -1;
521
541
  --kui-shell-col: 1 / -1;
522
542
  --kui-shell-surface: var(--color-surface);
@@ -531,6 +551,8 @@
531
551
  .kui-ShellRail[data-presentation-initial='stacked'] ~ .kui-ShellPanel[data-presentation-follows] {
532
552
  --kui-shell-position: absolute;
533
553
  --kui-shell-z: 3;
554
+ --kui-shell-pin: fixed;
555
+ --kui-shell-pin-top: initial;
534
556
  --kui-shell-row: 2 / 3;
535
557
  --kui-shell-col: 1 / -1;
536
558
  --kui-shell-surface: var(--color-surface);
@@ -558,6 +580,8 @@
558
580
  .kui-ShellRail[data-presentation-xs='fixed'] ~ .kui-ShellPanel[data-presentation-follows] {
559
581
  --kui-shell-position: initial;
560
582
  --kui-shell-z: initial;
583
+ --kui-shell-pin: initial;
584
+ --kui-shell-pin-top: initial;
561
585
  --kui-shell-row: initial;
562
586
  --kui-shell-col: initial;
563
587
  --kui-shell-surface: initial;
@@ -572,6 +596,8 @@
572
596
  .kui-ShellRail[data-presentation-xs='overlay'] ~ .kui-ShellPanel[data-presentation-follows] {
573
597
  --kui-shell-position: absolute;
574
598
  --kui-shell-z: 6;
599
+ --kui-shell-pin: fixed;
600
+ --kui-shell-pin-top: 0px;
575
601
  --kui-shell-row: 1 / -1;
576
602
  --kui-shell-col: 1 / -1;
577
603
  --kui-shell-surface: var(--color-surface);
@@ -586,6 +612,8 @@
586
612
  .kui-ShellRail[data-presentation-xs='stacked'] ~ .kui-ShellPanel[data-presentation-follows] {
587
613
  --kui-shell-position: absolute;
588
614
  --kui-shell-z: 3;
615
+ --kui-shell-pin: fixed;
616
+ --kui-shell-pin-top: initial;
589
617
  --kui-shell-row: 2 / 3;
590
618
  --kui-shell-col: 1 / -1;
591
619
  --kui-shell-surface: var(--color-surface);
@@ -614,6 +642,8 @@
614
642
  .kui-ShellRail[data-presentation-sm='fixed'] ~ .kui-ShellPanel[data-presentation-follows] {
615
643
  --kui-shell-position: initial;
616
644
  --kui-shell-z: initial;
645
+ --kui-shell-pin: initial;
646
+ --kui-shell-pin-top: initial;
617
647
  --kui-shell-row: initial;
618
648
  --kui-shell-col: initial;
619
649
  --kui-shell-surface: initial;
@@ -628,6 +658,8 @@
628
658
  .kui-ShellRail[data-presentation-sm='overlay'] ~ .kui-ShellPanel[data-presentation-follows] {
629
659
  --kui-shell-position: absolute;
630
660
  --kui-shell-z: 6;
661
+ --kui-shell-pin: fixed;
662
+ --kui-shell-pin-top: 0px;
631
663
  --kui-shell-row: 1 / -1;
632
664
  --kui-shell-col: 1 / -1;
633
665
  --kui-shell-surface: var(--color-surface);
@@ -642,6 +674,8 @@
642
674
  .kui-ShellRail[data-presentation-sm='stacked'] ~ .kui-ShellPanel[data-presentation-follows] {
643
675
  --kui-shell-position: absolute;
644
676
  --kui-shell-z: 3;
677
+ --kui-shell-pin: fixed;
678
+ --kui-shell-pin-top: initial;
645
679
  --kui-shell-row: 2 / 3;
646
680
  --kui-shell-col: 1 / -1;
647
681
  --kui-shell-surface: var(--color-surface);
@@ -670,6 +704,8 @@
670
704
  .kui-ShellRail[data-presentation-md='fixed'] ~ .kui-ShellPanel[data-presentation-follows] {
671
705
  --kui-shell-position: initial;
672
706
  --kui-shell-z: initial;
707
+ --kui-shell-pin: initial;
708
+ --kui-shell-pin-top: initial;
673
709
  --kui-shell-row: initial;
674
710
  --kui-shell-col: initial;
675
711
  --kui-shell-surface: initial;
@@ -684,6 +720,8 @@
684
720
  .kui-ShellRail[data-presentation-md='overlay'] ~ .kui-ShellPanel[data-presentation-follows] {
685
721
  --kui-shell-position: absolute;
686
722
  --kui-shell-z: 6;
723
+ --kui-shell-pin: fixed;
724
+ --kui-shell-pin-top: 0px;
687
725
  --kui-shell-row: 1 / -1;
688
726
  --kui-shell-col: 1 / -1;
689
727
  --kui-shell-surface: var(--color-surface);
@@ -698,6 +736,8 @@
698
736
  .kui-ShellRail[data-presentation-md='stacked'] ~ .kui-ShellPanel[data-presentation-follows] {
699
737
  --kui-shell-position: absolute;
700
738
  --kui-shell-z: 3;
739
+ --kui-shell-pin: fixed;
740
+ --kui-shell-pin-top: initial;
701
741
  --kui-shell-row: 2 / 3;
702
742
  --kui-shell-col: 1 / -1;
703
743
  --kui-shell-surface: var(--color-surface);
@@ -726,6 +766,8 @@
726
766
  .kui-ShellRail[data-presentation-lg='fixed'] ~ .kui-ShellPanel[data-presentation-follows] {
727
767
  --kui-shell-position: initial;
728
768
  --kui-shell-z: initial;
769
+ --kui-shell-pin: initial;
770
+ --kui-shell-pin-top: initial;
729
771
  --kui-shell-row: initial;
730
772
  --kui-shell-col: initial;
731
773
  --kui-shell-surface: initial;
@@ -740,6 +782,8 @@
740
782
  .kui-ShellRail[data-presentation-lg='overlay'] ~ .kui-ShellPanel[data-presentation-follows] {
741
783
  --kui-shell-position: absolute;
742
784
  --kui-shell-z: 6;
785
+ --kui-shell-pin: fixed;
786
+ --kui-shell-pin-top: 0px;
743
787
  --kui-shell-row: 1 / -1;
744
788
  --kui-shell-col: 1 / -1;
745
789
  --kui-shell-surface: var(--color-surface);
@@ -754,6 +798,8 @@
754
798
  .kui-ShellRail[data-presentation-lg='stacked'] ~ .kui-ShellPanel[data-presentation-follows] {
755
799
  --kui-shell-position: absolute;
756
800
  --kui-shell-z: 3;
801
+ --kui-shell-pin: fixed;
802
+ --kui-shell-pin-top: initial;
757
803
  --kui-shell-row: 2 / 3;
758
804
  --kui-shell-col: 1 / -1;
759
805
  --kui-shell-surface: var(--color-surface);
@@ -782,6 +828,8 @@
782
828
  .kui-ShellRail[data-presentation-xl='fixed'] ~ .kui-ShellPanel[data-presentation-follows] {
783
829
  --kui-shell-position: initial;
784
830
  --kui-shell-z: initial;
831
+ --kui-shell-pin: initial;
832
+ --kui-shell-pin-top: initial;
785
833
  --kui-shell-row: initial;
786
834
  --kui-shell-col: initial;
787
835
  --kui-shell-surface: initial;
@@ -796,6 +844,8 @@
796
844
  .kui-ShellRail[data-presentation-xl='overlay'] ~ .kui-ShellPanel[data-presentation-follows] {
797
845
  --kui-shell-position: absolute;
798
846
  --kui-shell-z: 6;
847
+ --kui-shell-pin: fixed;
848
+ --kui-shell-pin-top: 0px;
799
849
  --kui-shell-row: 1 / -1;
800
850
  --kui-shell-col: 1 / -1;
801
851
  --kui-shell-surface: var(--color-surface);
@@ -810,6 +860,8 @@
810
860
  .kui-ShellRail[data-presentation-xl='stacked'] ~ .kui-ShellPanel[data-presentation-follows] {
811
861
  --kui-shell-position: absolute;
812
862
  --kui-shell-z: 3;
863
+ --kui-shell-pin: fixed;
864
+ --kui-shell-pin-top: initial;
813
865
  --kui-shell-row: 2 / 3;
814
866
  --kui-shell-col: 1 / -1;
815
867
  --kui-shell-surface: var(--color-surface);
@@ -844,6 +896,8 @@
844
896
  .kui-ShellRail ~ .kui-ShellPanel[data-presentation-follows][data-peek][data-state] {
845
897
  --kui-shell-position: absolute;
846
898
  --kui-shell-z: 4;
899
+ --kui-shell-pin: fixed;
900
+ --kui-shell-pin-top: initial;
847
901
  --kui-shell-row: 2 / 3;
848
902
  --kui-shell-col: 1 / -1;
849
903
  --kui-shell-surface: var(--color-surface);
@@ -946,6 +1000,153 @@
946
1000
  margin-block-start: 0;
947
1001
  }
948
1002
 
1003
+ /* ── On a phone, the page scrolls (0.27.0) ────────────────────────────────── */
1004
+
1005
+ /*
1006
+ * Ported from kookie-ui-v2's Shell. A mobile browser hides its toolbars only when the document
1007
+ * scrolls; no scroller inside the page reaches them. So on a narrow window with a coarse pointer
1008
+ * a window Shell (`data-window`: no `contained`, no `height`) grows with its content and the
1009
+ * document scrolls instead of the content pane. Everything that stayed put while the pane
1010
+ * scrolled stays put while the page scrolls: the header and the content's pinned rows stick, and
1011
+ * the drawers and the scrim attach to the screen.
1012
+ *
1013
+ * Narrow is below the `sm` breakpoint, where v1's panes leave the overlay posture by default.
1014
+ * `_internal/shell-page-scroll.ts` holds the same query for the few things only script can do,
1015
+ * and a test holds the two equal.
1016
+ *
1017
+ * Content that cannot wrap is clipped at the screen's edge rather than widening the page: it
1018
+ * needs its own horizontal scroller, as a code block has.
1019
+ */
1020
+ @media (max-width: 767.98px) and (pointer: coarse) {
1021
+ /* `clip`, not `hidden`: a hidden box is a scroll container, and it would catch every sticky row. */
1022
+ .kui-ShellRoot[data-window] {
1023
+ height: auto;
1024
+ min-height: 100vh;
1025
+ overflow: clip;
1026
+ }
1027
+
1028
+ @supports (height: 100dvh) {
1029
+ .kui-ShellRoot[data-window] {
1030
+ min-height: 100dvh;
1031
+ }
1032
+ }
1033
+
1034
+ /* The header's height, for the rows that stick beneath it. The Root writes `--kui-shell-header-h`
1035
+ when a Shell.Header is not the default 64px. */
1036
+ .kui-ShellRoot[data-window]:has(> .kui-ShellHeader) {
1037
+ --kui-shell-page-top: var(--kui-shell-header-h, 64px);
1038
+ }
1039
+
1040
+ .kui-ShellRoot[data-window] > .kui-ShellHeader {
1041
+ position: sticky;
1042
+ top: 0;
1043
+ }
1044
+
1045
+ /*
1046
+ * The content stops scrolling. Isolated, so nothing the app layers inside it climbs over a
1047
+ * sticky row and takes its taps. A focused control or a linked heading scrolls into view
1048
+ * beneath the stuck rows rather than under them.
1049
+ */
1050
+ .kui-ShellRoot[data-window] > .kui-ShellContent {
1051
+ overflow: clip;
1052
+ isolation: isolate;
1053
+ }
1054
+
1055
+ .kui-ShellRoot[data-window] > .kui-ShellContent :where(*) {
1056
+ scroll-margin-block: calc(var(--kui-shell-page-top) + var(--kui-content-float-start, 0px)) var(--kui-content-float-end, 0px);
1057
+ }
1058
+
1059
+ /* The floating rows' reach, as the content's Shell.Scroll works it out above. */
1060
+ .kui-ShellRoot[data-window] > .kui-ShellContent:has(> .kui-ShellPaneHeader[data-float]) {
1061
+ --kui-content-float-start: calc(max(var(--kui-pane-row-start), var(--kui-pane-band-start, 0px)) + 2 * var(--kui-pane-pad-start));
1062
+ }
1063
+
1064
+ .kui-ShellRoot[data-window] > .kui-ShellContent:has(> .kui-ShellPaneFooter[data-float]) {
1065
+ --kui-content-float-end: calc(max(var(--kui-pane-row-end), var(--kui-pane-band-end, 0px)) + 2 * var(--kui-pane-pad-end));
1066
+ }
1067
+
1068
+ /*
1069
+ * Shell.Scroll in the content stops scrolling too and grows with what it holds. The viewport's
1070
+ * overflow is written inline by Radix, hence `!important`. Its scrollbar and fade go: the
1071
+ * document's own scrollbar is the one a phone shows, and a mask with nothing to scroll could
1072
+ * only cut the page's edge.
1073
+ */
1074
+ .kui-ShellRoot[data-window] > .kui-ShellContent > .kui-ShellScroll {
1075
+ flex: none;
1076
+ height: auto;
1077
+ overflow: clip;
1078
+ }
1079
+
1080
+ .kui-ShellRoot[data-window] > .kui-ShellContent > .kui-ShellScroll > .kui-ScrollAreaViewport {
1081
+ height: auto;
1082
+ overflow: visible !important;
1083
+ mask-image: none;
1084
+ }
1085
+
1086
+ .kui-ShellRoot[data-window] > .kui-ShellContent > .kui-ShellScroll > .kui-ScrollAreaScrollbar {
1087
+ display: none;
1088
+ }
1089
+
1090
+ /*
1091
+ * The floating rows stick, and still float. Sticky is in flow, so a negative margin gives back
1092
+ * the room the row takes and the page starts where it starts in the frame. `order` because a
1093
+ * row sticks where it sits, and a footer must sit after the page.
1094
+ */
1095
+ .kui-ShellRoot[data-window] > .kui-ShellContent:has(> .kui-ShellScroll) > .kui-ShellPaneHeader[data-float] {
1096
+ position: sticky;
1097
+ top: var(--kui-shell-page-top);
1098
+ order: -1;
1099
+ margin-bottom: calc(-1 * var(--kui-content-float-start, 0px));
1100
+ }
1101
+
1102
+ .kui-ShellRoot[data-window] > .kui-ShellContent:has(> .kui-ShellScroll) > .kui-ShellPaneFooter[data-float] {
1103
+ position: sticky;
1104
+ bottom: 0;
1105
+ order: 1;
1106
+ margin-top: calc(-1 * var(--kui-content-float-end, 0px));
1107
+ }
1108
+
1109
+ /* A pinned sibling of the Scroll pins to the screen: one before it to the top, beneath the
1110
+ header, one after it to the bottom. */
1111
+ .kui-ShellRoot[data-window] > .kui-ShellContent > :not(.kui-ShellScroll, [data-float]):has(~ .kui-ShellScroll) {
1112
+ position: sticky;
1113
+ top: var(--kui-shell-page-top);
1114
+ z-index: 1;
1115
+ }
1116
+
1117
+ .kui-ShellRoot[data-window] > .kui-ShellContent > .kui-ShellScroll ~ :not([data-float]) {
1118
+ position: sticky;
1119
+ bottom: 0;
1120
+ z-index: 1;
1121
+ }
1122
+
1123
+ /*
1124
+ * The panes. A pane over the page (overlay, stacked, peek) attaches to the screen: its posture
1125
+ * writes `--kui-shell-pin: fixed`. A pane in flow sticks beneath the header, a screen tall, and
1126
+ * the bottom pane sticks to the screen's bottom. An overlay covers the header
1127
+ * (`--kui-shell-pin-top: 0px`); the rest start beneath it.
1128
+ */
1129
+ .kui-ShellRoot[data-window] > :is(.kui-ShellRail, .kui-ShellPanel, .kui-ShellSidebar, .kui-ShellInspector) {
1130
+ position: var(--kui-shell-pin, sticky);
1131
+ top: var(--kui-shell-pin-top, var(--kui-shell-page-top));
1132
+ block-size: calc(100vh - var(--kui-shell-pin-top, var(--kui-shell-page-top)));
1133
+ }
1134
+
1135
+ @supports (height: 100dvh) {
1136
+ .kui-ShellRoot[data-window] > :is(.kui-ShellRail, .kui-ShellPanel, .kui-ShellSidebar, .kui-ShellInspector) {
1137
+ block-size: calc(100dvh - var(--kui-shell-pin-top, var(--kui-shell-page-top)));
1138
+ }
1139
+ }
1140
+
1141
+ .kui-ShellRoot[data-window] > .kui-ShellBottom {
1142
+ position: var(--kui-shell-pin, sticky);
1143
+ }
1144
+
1145
+ .kui-ShellRoot[data-window] > .kui-ShellScrim {
1146
+ position: fixed;
1147
+ }
1148
+ }
1149
+
949
1150
  /* ── Resize handle ─────────────────────────────────────────────────────────── */
950
1151
 
951
1152
  /* A transparent hit area straddling the pane's edge. */
@@ -23,7 +23,7 @@
23
23
  import * as React from 'react';
24
24
  import classNames from 'classnames';
25
25
  import { Slot } from 'radix-ui';
26
- import { useComposedRefs } from 'radix-ui/internal';
26
+ import { useComposedRefs, useLayoutEffect } from 'radix-ui/internal';
27
27
  import { PaneResizeContext } from './_internal/shell-resize.js';
28
28
  import { PaneHandle, PanelHandle } from './_internal/shell-handles.js';
29
29
  import { Sidebar } from './_internal/shell-sidebar.js';
@@ -52,7 +52,8 @@ import { useShell, useSidebarMode } from './shell.context.js';
52
52
  import { useResponsivePresentation } from './shell.hooks.js';
53
53
  import { readBreakpoint } from '../hooks/use-breakpoint.js';
54
54
  import { useThemeSize } from '../hooks/theme-size.js';
55
- import { PaneChromeScope, PaneFooter, PaneHeader, Scroll, ShellContentContext, ShellSizeContext } from './_internal/pane-chrome.js';
55
+ import { PaneChromeScope, PaneFooter, PaneHeader, Scroll, ShellContentContext, ShellSizeContext, ShellWindowContext } from './_internal/pane-chrome.js';
56
+ import { onPageScrollMediaChange, pageScrollMatches } from './_internal/shell-page-scroll.js';
56
57
  import type { PaneSize, PaneHeaderProps, PaneFooterProps, ScrollProps } from './_internal/pane-chrome.js';
57
58
  import { PaneBandSizeContext } from './_internal/pane-band-context.js';
58
59
  import type { Breakpoint, CSSPropertiesWithVars, PaneBaseProps, PaneMode, PaneName, PaneTarget, ResponsivePresentation, SidebarMode } from './shell.types.js';
@@ -61,7 +62,18 @@ import type { Breakpoint, CSSPropertiesWithVars, PaneBaseProps, PaneMode, PaneNa
61
62
 
62
63
  export interface ShellRootProps extends React.ComponentPropsWithoutRef<'div'> {
63
64
  children: React.ReactNode;
65
+ /**
66
+ * The Shell's height. `full` (the default) is the window's height; on a narrow touch screen the
67
+ * page scrolls instead of the content, so the browser can hide its toolbars. `auto` grows with
68
+ * the content. Any other value is the Shell's own height, and makes it contained.
69
+ */
64
70
  height?: 'full' | 'auto' | string | number;
71
+ /**
72
+ * Makes the Shell fill its parent instead of the window, and always scroll inside itself. Its
73
+ * overlays cover only its own box and leave the page free to scroll. Use it for a Shell in a
74
+ * card, a demo or a canvas. An explicit `height` implies it.
75
+ */
76
+ contained?: boolean;
65
77
  /** The index the panes' chrome takes: `Shell.PaneHeader`, `Shell.Scroll`, `Shell.PaneFooter` and the Sidebar rows in them. Defaults to the nearest Theme's size (3 when the Theme is 4), else `2`. */
66
78
  size?: PaneSize;
67
79
  }
@@ -105,7 +117,18 @@ type LivePane = { name: PaneName; id: string; el: HTMLElement };
105
117
  /** Shell.Root's own range; a Theme size above it maps to 3. */
106
118
  const shellSizePropDef = { values: ['1', '2', '3'] as const };
107
119
 
108
- const Root = React.forwardRef<HTMLDivElement, ShellRootProps>(({ className, children, height = 'full', size: sizeProp, style, onKeyDown, onFocus, ...props }, ref) => {
120
+ /** Lets a Shell.Header tell the Root its height, for the rows that stick beneath it while the page scrolls. */
121
+ const ShellHeaderHeightContext = React.createContext<((height: number | undefined) => void) | null>(null);
122
+
123
+ /** The Shell.Header's default height, which the stylesheet assumes until a Header says otherwise. */
124
+ const DEFAULT_HEADER_HEIGHT = 64;
125
+
126
+ /** The content's scroller while the frame scrolls: the Shell.Scroll's viewport, or the content itself. */
127
+ function frameScroller(rootEl: HTMLElement): HTMLElement | null {
128
+ return rootEl.querySelector<HTMLElement>(':scope > .kui-ShellContent > .kui-ShellScroll > .kui-ScrollAreaViewport') ?? rootEl.querySelector<HTMLElement>(':scope > .kui-ShellContent');
129
+ }
130
+
131
+ const Root = React.forwardRef<HTMLDivElement, ShellRootProps>(({ className, children, height = 'full', contained: containedProp, size: sizeProp, style, onKeyDown, onFocus, ...props }, ref) => {
109
132
  // No size of its own: the nearest Theme's, mapped into 1-3.
110
133
  const size = useThemeSize(sizeProp, shellSizePropDef);
111
134
  const [store] = React.useState(createShellStore);
@@ -148,10 +171,72 @@ const Root = React.forwardRef<HTMLDivElement, ShellRootProps>(({ className, chil
148
171
  );
149
172
  const liveCount = [...store.entries.values()].filter((entry) => entry.overlayLive && entry.el).length;
150
173
 
151
- // A Shell given a height of its own sits inside a page, and its overlays
152
- // cover only its box: it holds no page lock. `full` is the page, and
153
- // `auto` grows with its content, so its overlays are placed on the window.
154
- const contained = height !== 'full' && height !== 'auto';
174
+ // A contained Shell sits inside a page, and its overlays cover only its box:
175
+ // it holds no page lock. A height of its own implies it. `full` is the
176
+ // window, and `auto` grows with its content, so its overlays are placed on
177
+ // the window. Only a `full` Shell lets the page scroll on a phone.
178
+ const contained = containedProp === true || (height !== 'full' && height !== 'auto');
179
+ const windowShell = !contained && height === 'full';
180
+
181
+ const [headerHeight, setHeaderHeight] = React.useState<number | undefined>(undefined);
182
+
183
+ /*
184
+ * The reading position crosses with the scroller. When a touch window
185
+ * crosses the narrow boundary (a phone rotating, an iPad entering Split
186
+ * View), the scroller changes between the content and the page, and the new
187
+ * one starts at the top. The offset is remembered on `scroll` from whichever
188
+ * scroller is live, because by the time the change is reported the old one
189
+ * has already been laid out again and clamped. Only the live scroller is
190
+ * heard. The clamp itself is reported as a scroll in the same frame as the
191
+ * resize and before the media change, so scrolls are not heard from a resize
192
+ * until that frame's animation callbacks.
193
+ */
194
+ React.useEffect(() => {
195
+ if (!windowShell) return;
196
+ const rootEl = rootRef.current;
197
+ const win = rootEl?.ownerDocument.defaultView;
198
+ if (!rootEl || !win || typeof win.matchMedia !== 'function') return;
199
+ let pageScrolls = pageScrollMatches();
200
+ let offset = pageScrolls ? win.scrollY : (frameScroller(rootEl)?.scrollTop ?? 0);
201
+ let frame = 0;
202
+ let resizing = 0;
203
+ const onResize = () => {
204
+ if (resizing) cancelAnimationFrame(resizing);
205
+ resizing = requestAnimationFrame(() => {
206
+ resizing = 0;
207
+ });
208
+ };
209
+ const fromPage = () => {
210
+ if (pageScrolls && !resizing) offset = win.scrollY;
211
+ };
212
+ const fromFrame = (event: Event) => {
213
+ if (!pageScrolls && !resizing && event.target instanceof HTMLElement && event.target === frameScroller(rootEl)) offset = event.target.scrollTop;
214
+ };
215
+ win.addEventListener('resize', onResize);
216
+ win.addEventListener('scroll', fromPage, { passive: true });
217
+ rootEl.addEventListener('scroll', fromFrame, { passive: true, capture: true });
218
+ const stop = onPageScrollMediaChange((matches) => {
219
+ pageScrolls = matches;
220
+ const carried = offset;
221
+ if (frame) cancelAnimationFrame(frame);
222
+ frame = requestAnimationFrame(() => {
223
+ frame = 0;
224
+ if (matches) win.scrollTo(0, carried);
225
+ else {
226
+ const el = frameScroller(rootEl);
227
+ if (el) el.scrollTop = carried;
228
+ }
229
+ });
230
+ });
231
+ return () => {
232
+ if (frame) cancelAnimationFrame(frame);
233
+ if (resizing) cancelAnimationFrame(resizing);
234
+ win.removeEventListener('resize', onResize);
235
+ win.removeEventListener('scroll', fromPage);
236
+ rootEl.removeEventListener('scroll', fromFrame, { capture: true });
237
+ stop();
238
+ };
239
+ }, [windowShell]);
155
240
 
156
241
  /*
157
242
  * Containment is the Root's, not the pane's. Only the Root can see every live
@@ -371,6 +456,8 @@ const Root = React.forwardRef<HTMLDivElement, ShellRootProps>(({ className, chil
371
456
  <ShellStoreContext.Provider value={store}>
372
457
  <ShellSizeContext.Provider value={size}>
373
458
  <ShellContentContext.Provider value={false}>
459
+ <ShellWindowContext.Provider value={windowShell}>
460
+ <ShellHeaderHeightContext.Provider value={setHeaderHeight}>
374
461
  <ShellInsetContext.Provider value={insetContext}>
375
462
  {/* A Shell inside a portalled surface's Theme starts with no band, like any other. */}
376
463
  <PaneBandSizeContext.Provider value={undefined}>
@@ -381,12 +468,19 @@ const Root = React.forwardRef<HTMLDivElement, ShellRootProps>(({ className, chil
381
468
  {...props}
382
469
  ref={composedRef}
383
470
  className={classNames('kui-ShellRoot', className)}
384
- data-height={height === 'auto' ? 'auto' : undefined}
471
+ data-height={height === 'auto' && !contained ? 'auto' : undefined}
472
+ data-contained={contained || undefined}
473
+ data-window={windowShell || undefined}
385
474
  data-has-inset={insetPanes.size > 0 || undefined}
386
475
  data-overlay-live={liveCount > 0 || undefined}
387
476
  onKeyDown={handleKeyDown}
388
477
  onFocus={handleFocus}
389
- style={{ ...heightStyle, ...(railOffset ? ({ '--shell-rail-offset': railOffset } as CSSPropertiesWithVars) : {}), ...style }}
478
+ style={{
479
+ ...heightStyle,
480
+ ...(railOffset ? ({ '--shell-rail-offset': railOffset } as CSSPropertiesWithVars) : {}),
481
+ ...(headerHeight !== undefined ? ({ '--kui-shell-header-h': `${headerHeight}px` } as CSSPropertiesWithVars) : {}),
482
+ ...style,
483
+ }}
390
484
  >
391
485
  {children}
392
486
  {/* Root-owned and always mounted. The stylesheet shows it while an
@@ -396,6 +490,8 @@ const Root = React.forwardRef<HTMLDivElement, ShellRootProps>(({ className, chil
396
490
  </div>
397
491
  </PaneBandSizeContext.Provider>
398
492
  </ShellInsetContext.Provider>
493
+ </ShellHeaderHeightContext.Provider>
494
+ </ShellWindowContext.Provider>
399
495
  </ShellContentContext.Provider>
400
496
  </ShellSizeContext.Provider>
401
497
  </ShellStoreContext.Provider>
@@ -409,19 +505,29 @@ interface ShellHeaderProps extends React.ComponentPropsWithoutRef<'header'> {
409
505
  height?: number;
410
506
  }
411
507
 
412
- const Header = React.forwardRef<HTMLElement, ShellHeaderProps>(({ className, height = 64, style, ...props }, ref) => (
413
- <header
414
- {...props}
415
- ref={ref}
416
- className={classNames('kui-ShellHeader', className)}
417
- style={
418
- {
419
- ...style,
420
- '--shell-header-height': `${height}px`,
421
- } as CSSPropertiesWithVars
422
- }
423
- />
424
- ));
508
+ const Header = React.forwardRef<HTMLElement, ShellHeaderProps>(({ className, height = DEFAULT_HEADER_HEIGHT, style, ...props }, ref) => {
509
+ // Rows that stick beneath the header while the page scrolls need its height. The stylesheet
510
+ // assumes the default, so only another height is told to the Root.
511
+ const setHeaderHeight = React.useContext(ShellHeaderHeightContext);
512
+ useLayoutEffect(() => {
513
+ if (!setHeaderHeight) return;
514
+ setHeaderHeight(height === DEFAULT_HEADER_HEIGHT ? undefined : height);
515
+ return () => setHeaderHeight(undefined);
516
+ }, [setHeaderHeight, height]);
517
+ return (
518
+ <header
519
+ {...props}
520
+ ref={ref}
521
+ className={classNames('kui-ShellHeader', className)}
522
+ style={
523
+ {
524
+ ...style,
525
+ '--shell-header-height': `${height}px`,
526
+ } as CSSPropertiesWithVars
527
+ }
528
+ />
529
+ );
530
+ });
425
531
  Header.displayName = 'Shell.Header';
426
532
 
427
533
  /* ── Left (deprecated) ─────────────────────────────────────────────────────── */
@@ -98,8 +98,23 @@
98
98
  }
99
99
  }
100
100
 
101
+ /* A Spinner with children is one tree, loading or not. At rest it steps out of layout. */
102
+ .kui-SpinnerHost:where(:not([data-loading])) {
103
+ display: contents;
104
+ }
105
+
106
+ .kui-SpinnerHost:where([data-loading]) {
107
+ position: relative;
108
+ display: flex;
109
+ align-items: center;
110
+ justify-content: center;
111
+ }
112
+
113
+ .kui-SpinnerChildren {
114
+ display: contents;
115
+ }
116
+
101
117
  /* Children of a Spinner keep their space but are not shown while it spins. A class, not an inline style. */
102
118
  .kui-SpinnerHiddenChildren {
103
- display: contents;
104
119
  visibility: hidden;
105
120
  }
@@ -19,7 +19,8 @@ const Spinner = React.forwardRef<SpinnerElement, SpinnerProps>((props, forwarded
19
19
  spinnerPropDefs
20
20
  );
21
21
 
22
- if (!loading) return children;
22
+ // Without children a Spinner is only the wheel, shown while loading.
23
+ if (children === undefined && !loading) return null;
23
24
 
24
25
  // Decorative unless named: a named spinner is a status message, an unnamed one is hidden.
25
26
  const named =
@@ -50,22 +51,22 @@ const Spinner = React.forwardRef<SpinnerElement, SpinnerProps>((props, forwarded
50
51
 
51
52
  if (children === undefined) return spinner;
52
53
 
54
+ // With children, one tree whether loading or not, so starting or stopping never remounts them
55
+ // (their state, focus and refs survive). At rest the host is `display: contents`; while loading
56
+ // it centres the wheel over the children, which keep their space but are hidden.
53
57
  return (
54
- <Flex asChild position="relative" align="center" justify="center">
55
- <span aria-busy="true">
56
- {/**
57
- * `display: contents` removes the content from the accessibility tree in some browsers,
58
- * so we force remove it with `aria-hidden`
59
- */}
60
- <span aria-hidden className="kui-SpinnerHiddenChildren">
61
- {children}
62
- </span>
63
-
58
+ <span className="kui-SpinnerHost" data-loading={loading || undefined} aria-busy={loading || undefined}>
59
+ {/* `display: contents` removes the content from the accessibility tree in some browsers, so
60
+ while loading it is removed with `aria-hidden` too. */}
61
+ <span aria-hidden={loading || undefined} className={classNames('kui-SpinnerChildren', loading && 'kui-SpinnerHiddenChildren')}>
62
+ {children}
63
+ </span>
64
+ {loading ? (
64
65
  <Flex asChild align="center" justify="center" position="absolute" inset="0">
65
66
  <span>{spinner}</span>
66
67
  </Flex>
67
- </span>
68
- </Flex>
68
+ ) : null}
69
+ </span>
69
70
  );
70
71
  });
71
72
  Spinner.displayName = 'Spinner';
@@ -464,8 +464,13 @@
464
464
  * *
465
465
  ***************************************************************************************************/
466
466
 
467
- /* With an error message, one box holds the field and the message below it. */
468
- .kui-TextAreaWrapper {
467
+ /* With an error message, one box holds the field and the message below it. Without one the
468
+ wrapper steps out of layout, and the field is the box. */
469
+ .kui-TextAreaWrapper:where(:not([data-message])) {
470
+ display: contents;
471
+ }
472
+
473
+ .kui-TextAreaWrapper:where([data-message]) {
469
474
  display: flex;
470
475
  flex-direction: column;
471
476
  min-width: 0;