@womp/kookie-ui 0.6.2 → 0.8.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 (1047) hide show
  1. package/components.css +741 -1078
  2. package/dist/cjs/components/_internal/base-button.js +1 -1
  3. package/dist/cjs/components/_internal/base-button.js.map +4 -4
  4. package/dist/cjs/components/_internal/base-button.props.d.ts +2 -7
  5. package/dist/cjs/components/_internal/base-button.props.d.ts.map +1 -1
  6. package/dist/cjs/components/_internal/base-button.props.js +1 -1
  7. package/dist/cjs/components/_internal/base-button.props.js.map +4 -4
  8. package/dist/cjs/components/_internal/base-checkbox.props.d.ts +0 -5
  9. package/dist/cjs/components/_internal/base-checkbox.props.d.ts.map +1 -1
  10. package/dist/cjs/components/_internal/base-checkbox.props.js +1 -1
  11. package/dist/cjs/components/_internal/base-checkbox.props.js.map +4 -4
  12. package/dist/cjs/components/_internal/base-menu.props.d.ts +0 -10
  13. package/dist/cjs/components/_internal/base-menu.props.d.ts.map +1 -1
  14. package/dist/cjs/components/_internal/base-menu.props.js +1 -1
  15. package/dist/cjs/components/_internal/base-menu.props.js.map +4 -4
  16. package/dist/cjs/components/_internal/base-menu.utils.js +1 -1
  17. package/dist/cjs/components/_internal/base-menu.utils.js.map +3 -3
  18. package/dist/cjs/components/_internal/base-radio.props.d.ts +0 -5
  19. package/dist/cjs/components/_internal/base-radio.props.d.ts.map +1 -1
  20. package/dist/cjs/components/_internal/base-radio.props.js +1 -1
  21. package/dist/cjs/components/_internal/base-radio.props.js.map +4 -4
  22. package/dist/cjs/components/_internal/base-tab-list.props.d.ts +0 -5
  23. package/dist/cjs/components/_internal/base-tab-list.props.d.ts.map +1 -1
  24. package/dist/cjs/components/_internal/base-tab-list.props.js +1 -1
  25. package/dist/cjs/components/_internal/base-tab-list.props.js.map +4 -4
  26. package/dist/cjs/components/_internal/menu-context.js +1 -1
  27. package/dist/cjs/components/_internal/menu-context.js.map +3 -3
  28. package/dist/cjs/components/_internal/shell-bottom.d.ts +6 -7
  29. package/dist/cjs/components/_internal/shell-bottom.d.ts.map +1 -1
  30. package/dist/cjs/components/_internal/shell-bottom.js +1 -1
  31. package/dist/cjs/components/_internal/shell-bottom.js.map +4 -4
  32. package/dist/cjs/components/_internal/shell-handles.d.ts +9 -0
  33. package/dist/cjs/components/_internal/shell-handles.d.ts.map +1 -1
  34. package/dist/cjs/components/_internal/shell-handles.js +1 -1
  35. package/dist/cjs/components/_internal/shell-handles.js.map +3 -3
  36. package/dist/cjs/components/_internal/shell-inspector.d.ts +4 -6
  37. package/dist/cjs/components/_internal/shell-inspector.d.ts.map +1 -1
  38. package/dist/cjs/components/_internal/shell-inspector.js +1 -1
  39. package/dist/cjs/components/_internal/shell-inspector.js.map +4 -4
  40. package/dist/cjs/components/_internal/shell-pane.d.ts +70 -0
  41. package/dist/cjs/components/_internal/shell-pane.d.ts.map +1 -0
  42. package/dist/cjs/components/_internal/shell-pane.js +2 -0
  43. package/dist/cjs/components/_internal/shell-pane.js.map +7 -0
  44. package/dist/cjs/components/_internal/shell-resizable.d.ts +48 -0
  45. package/dist/cjs/components/_internal/shell-resizable.d.ts.map +1 -0
  46. package/dist/cjs/components/_internal/shell-resizable.js +2 -0
  47. package/dist/cjs/components/_internal/shell-resizable.js.map +7 -0
  48. package/dist/cjs/components/_internal/shell-resize.d.ts +11 -3
  49. package/dist/cjs/components/_internal/shell-resize.d.ts.map +1 -1
  50. package/dist/cjs/components/_internal/shell-resize.js +1 -1
  51. package/dist/cjs/components/_internal/shell-resize.js.map +2 -2
  52. package/dist/cjs/components/_internal/shell-rest.d.ts +27 -0
  53. package/dist/cjs/components/_internal/shell-rest.d.ts.map +1 -0
  54. package/dist/cjs/components/_internal/shell-rest.js +2 -0
  55. package/dist/cjs/components/_internal/shell-rest.js.map +7 -0
  56. package/dist/cjs/components/_internal/shell-sidebar.d.ts +7 -12
  57. package/dist/cjs/components/_internal/shell-sidebar.d.ts.map +1 -1
  58. package/dist/cjs/components/_internal/shell-sidebar.js +1 -1
  59. package/dist/cjs/components/_internal/shell-sidebar.js.map +4 -4
  60. package/dist/cjs/components/_internal/shell-store.d.ts +99 -0
  61. package/dist/cjs/components/_internal/shell-store.d.ts.map +1 -0
  62. package/dist/cjs/components/_internal/shell-store.js +2 -0
  63. package/dist/cjs/components/_internal/shell-store.js.map +7 -0
  64. package/dist/cjs/components/accordion.js +1 -1
  65. package/dist/cjs/components/accordion.js.map +4 -4
  66. package/dist/cjs/components/accordion.props.d.ts +0 -6
  67. package/dist/cjs/components/accordion.props.d.ts.map +1 -1
  68. package/dist/cjs/components/accordion.props.js +1 -1
  69. package/dist/cjs/components/accordion.props.js.map +4 -4
  70. package/dist/cjs/components/alert-dialog.js +1 -1
  71. package/dist/cjs/components/alert-dialog.js.map +4 -4
  72. package/dist/cjs/components/avatar.js +1 -1
  73. package/dist/cjs/components/avatar.js.map +4 -4
  74. package/dist/cjs/components/avatar.props.d.ts +0 -5
  75. package/dist/cjs/components/avatar.props.d.ts.map +1 -1
  76. package/dist/cjs/components/avatar.props.js +1 -1
  77. package/dist/cjs/components/avatar.props.js.map +4 -4
  78. package/dist/cjs/components/badge.js +1 -1
  79. package/dist/cjs/components/badge.js.map +4 -4
  80. package/dist/cjs/components/badge.props.d.ts +0 -5
  81. package/dist/cjs/components/badge.props.d.ts.map +1 -1
  82. package/dist/cjs/components/badge.props.js +1 -1
  83. package/dist/cjs/components/badge.props.js.map +4 -4
  84. package/dist/cjs/components/blockquote.js +1 -1
  85. package/dist/cjs/components/blockquote.js.map +4 -4
  86. package/dist/cjs/components/blockquote.props.d.ts +3 -2
  87. package/dist/cjs/components/blockquote.props.d.ts.map +1 -1
  88. package/dist/cjs/components/blockquote.props.js +1 -1
  89. package/dist/cjs/components/blockquote.props.js.map +4 -4
  90. package/dist/cjs/components/button.js +1 -1
  91. package/dist/cjs/components/button.js.map +4 -4
  92. package/dist/cjs/components/button.props.js +1 -1
  93. package/dist/cjs/components/button.props.js.map +4 -4
  94. package/dist/cjs/components/callout.js +1 -1
  95. package/dist/cjs/components/callout.js.map +4 -4
  96. package/dist/cjs/components/callout.props.d.ts +0 -5
  97. package/dist/cjs/components/callout.props.d.ts.map +1 -1
  98. package/dist/cjs/components/callout.props.js +1 -1
  99. package/dist/cjs/components/callout.props.js.map +4 -4
  100. package/dist/cjs/components/chatbar.d.ts.map +1 -1
  101. package/dist/cjs/components/chatbar.js +2 -2
  102. package/dist/cjs/components/chatbar.js.map +4 -4
  103. package/dist/cjs/components/checkbox-cards.d.ts.map +1 -1
  104. package/dist/cjs/components/checkbox-cards.js +1 -1
  105. package/dist/cjs/components/checkbox-cards.js.map +4 -4
  106. package/dist/cjs/components/checkbox-cards.props.d.ts +0 -5
  107. package/dist/cjs/components/checkbox-cards.props.d.ts.map +1 -1
  108. package/dist/cjs/components/checkbox-cards.props.js +1 -1
  109. package/dist/cjs/components/checkbox-cards.props.js.map +4 -4
  110. package/dist/cjs/components/checkbox-group.d.ts.map +1 -1
  111. package/dist/cjs/components/checkbox-group.js +1 -1
  112. package/dist/cjs/components/checkbox-group.js.map +4 -4
  113. package/dist/cjs/components/checkbox-group.props.d.ts +0 -5
  114. package/dist/cjs/components/checkbox-group.props.d.ts.map +1 -1
  115. package/dist/cjs/components/checkbox-group.props.js +1 -1
  116. package/dist/cjs/components/checkbox-group.props.js.map +4 -4
  117. package/dist/cjs/components/checkbox.js +1 -1
  118. package/dist/cjs/components/checkbox.js.map +4 -4
  119. package/dist/cjs/components/checkbox.props.js +1 -1
  120. package/dist/cjs/components/checkbox.props.js.map +4 -4
  121. package/dist/cjs/components/code.js +1 -1
  122. package/dist/cjs/components/code.js.map +4 -4
  123. package/dist/cjs/components/code.props.d.ts +3 -2
  124. package/dist/cjs/components/code.props.d.ts.map +1 -1
  125. package/dist/cjs/components/code.props.js +1 -1
  126. package/dist/cjs/components/code.props.js.map +4 -4
  127. package/dist/cjs/components/combobox.d.ts.map +1 -1
  128. package/dist/cjs/components/combobox.js +1 -1
  129. package/dist/cjs/components/combobox.js.map +4 -4
  130. package/dist/cjs/components/combobox.props.d.ts +1 -11
  131. package/dist/cjs/components/combobox.props.d.ts.map +1 -1
  132. package/dist/cjs/components/combobox.props.js +1 -1
  133. package/dist/cjs/components/combobox.props.js.map +4 -4
  134. package/dist/cjs/components/context-menu.d.ts.map +1 -1
  135. package/dist/cjs/components/context-menu.js +1 -1
  136. package/dist/cjs/components/context-menu.js.map +4 -4
  137. package/dist/cjs/components/context-menu.props.js +1 -1
  138. package/dist/cjs/components/context-menu.props.js.map +4 -4
  139. package/dist/cjs/components/data-list.js +1 -1
  140. package/dist/cjs/components/data-list.js.map +4 -4
  141. package/dist/cjs/components/data-list.props.d.ts +4 -3
  142. package/dist/cjs/components/data-list.props.d.ts.map +1 -1
  143. package/dist/cjs/components/data-list.props.js +1 -1
  144. package/dist/cjs/components/data-list.props.js.map +4 -4
  145. package/dist/cjs/components/dialog.js +1 -1
  146. package/dist/cjs/components/dialog.js.map +4 -4
  147. package/dist/cjs/components/dropdown-menu.d.ts.map +1 -1
  148. package/dist/cjs/components/dropdown-menu.js +1 -1
  149. package/dist/cjs/components/dropdown-menu.js.map +4 -4
  150. package/dist/cjs/components/dropdown-menu.props.js +1 -1
  151. package/dist/cjs/components/dropdown-menu.props.js.map +4 -4
  152. package/dist/cjs/components/heading.js +1 -1
  153. package/dist/cjs/components/heading.js.map +4 -4
  154. package/dist/cjs/components/heading.props.d.ts +3 -2
  155. package/dist/cjs/components/heading.props.d.ts.map +1 -1
  156. package/dist/cjs/components/heading.props.js +1 -1
  157. package/dist/cjs/components/heading.props.js.map +4 -4
  158. package/dist/cjs/components/hover-card.js.map +1 -1
  159. package/dist/cjs/components/icon-button.js +2 -2
  160. package/dist/cjs/components/icon-button.js.map +4 -4
  161. package/dist/cjs/components/icon-button.props.js +1 -1
  162. package/dist/cjs/components/icon-button.props.js.map +4 -4
  163. package/dist/cjs/components/index.js +5 -5
  164. package/dist/cjs/components/index.js.map +4 -4
  165. package/dist/cjs/components/link.js +1 -1
  166. package/dist/cjs/components/link.js.map +4 -4
  167. package/dist/cjs/components/link.props.d.ts +0 -5
  168. package/dist/cjs/components/link.props.d.ts.map +1 -1
  169. package/dist/cjs/components/link.props.js +1 -1
  170. package/dist/cjs/components/link.props.js.map +4 -4
  171. package/dist/cjs/components/popover.js.map +1 -1
  172. package/dist/cjs/components/progress.js +1 -1
  173. package/dist/cjs/components/progress.js.map +4 -4
  174. package/dist/cjs/components/progress.props.d.ts +0 -5
  175. package/dist/cjs/components/progress.props.d.ts.map +1 -1
  176. package/dist/cjs/components/progress.props.js +1 -1
  177. package/dist/cjs/components/progress.props.js.map +4 -4
  178. package/dist/cjs/components/radio-cards.js +1 -1
  179. package/dist/cjs/components/radio-cards.js.map +4 -4
  180. package/dist/cjs/components/radio-cards.props.d.ts +0 -5
  181. package/dist/cjs/components/radio-cards.props.d.ts.map +1 -1
  182. package/dist/cjs/components/radio-cards.props.js +1 -1
  183. package/dist/cjs/components/radio-cards.props.js.map +4 -4
  184. package/dist/cjs/components/radio-group.d.ts.map +1 -1
  185. package/dist/cjs/components/radio-group.js +1 -1
  186. package/dist/cjs/components/radio-group.js.map +4 -4
  187. package/dist/cjs/components/radio-group.props.d.ts +0 -5
  188. package/dist/cjs/components/radio-group.props.d.ts.map +1 -1
  189. package/dist/cjs/components/radio-group.props.js +1 -1
  190. package/dist/cjs/components/radio-group.props.js.map +4 -4
  191. package/dist/cjs/components/radio.js +1 -1
  192. package/dist/cjs/components/radio.js.map +4 -4
  193. package/dist/cjs/components/radio.props.js +1 -1
  194. package/dist/cjs/components/radio.props.js.map +4 -4
  195. package/dist/cjs/components/schemas/base-button.schema.d.ts +0 -1
  196. package/dist/cjs/components/schemas/base-button.schema.d.ts.map +1 -1
  197. package/dist/cjs/components/schemas/base-button.schema.js +1 -1
  198. package/dist/cjs/components/schemas/base-button.schema.js.map +2 -2
  199. package/dist/cjs/components/schemas/button.schema.d.ts +0 -1
  200. package/dist/cjs/components/schemas/button.schema.d.ts.map +1 -1
  201. package/dist/cjs/components/schemas/button.schema.js +1 -1
  202. package/dist/cjs/components/schemas/button.schema.js.map +2 -2
  203. package/dist/cjs/components/schemas/icon-button.schema.d.ts +0 -1
  204. package/dist/cjs/components/schemas/icon-button.schema.d.ts.map +1 -1
  205. package/dist/cjs/components/schemas/icon-button.schema.js +1 -1
  206. package/dist/cjs/components/schemas/icon-button.schema.js.map +2 -2
  207. package/dist/cjs/components/schemas/index.js +1 -1
  208. package/dist/cjs/components/schemas/index.js.map +3 -3
  209. package/dist/cjs/components/schemas/shell.schema.d.ts +277 -229
  210. package/dist/cjs/components/schemas/shell.schema.d.ts.map +1 -1
  211. package/dist/cjs/components/schemas/shell.schema.js +1 -1
  212. package/dist/cjs/components/schemas/shell.schema.js.map +3 -3
  213. package/dist/cjs/components/schemas/toggle-button.schema.d.ts +0 -1
  214. package/dist/cjs/components/schemas/toggle-button.schema.d.ts.map +1 -1
  215. package/dist/cjs/components/schemas/toggle-button.schema.js +1 -1
  216. package/dist/cjs/components/schemas/toggle-button.schema.js.map +2 -2
  217. package/dist/cjs/components/schemas/toggle-icon-button.schema.d.ts +0 -1
  218. package/dist/cjs/components/schemas/toggle-icon-button.schema.d.ts.map +1 -1
  219. package/dist/cjs/components/schemas/toggle-icon-button.schema.js +1 -1
  220. package/dist/cjs/components/schemas/toggle-icon-button.schema.js.map +2 -2
  221. package/dist/cjs/components/select.js +1 -1
  222. package/dist/cjs/components/select.js.map +4 -4
  223. package/dist/cjs/components/select.props.d.ts +0 -5
  224. package/dist/cjs/components/select.props.d.ts.map +1 -1
  225. package/dist/cjs/components/select.props.js +1 -1
  226. package/dist/cjs/components/select.props.js.map +4 -4
  227. package/dist/cjs/components/separator.js.map +1 -1
  228. package/dist/cjs/components/separator.props.js.map +1 -1
  229. package/dist/cjs/components/sheet.js +1 -1
  230. package/dist/cjs/components/sheet.js.map +4 -4
  231. package/dist/cjs/components/shell.context.d.ts +25 -114
  232. package/dist/cjs/components/shell.context.d.ts.map +1 -1
  233. package/dist/cjs/components/shell.context.js +1 -1
  234. package/dist/cjs/components/shell.context.js.map +4 -4
  235. package/dist/cjs/components/shell.d.ts +42 -21
  236. package/dist/cjs/components/shell.d.ts.map +1 -1
  237. package/dist/cjs/components/shell.hooks.d.ts +7 -23
  238. package/dist/cjs/components/shell.hooks.d.ts.map +1 -1
  239. package/dist/cjs/components/shell.hooks.js +1 -1
  240. package/dist/cjs/components/shell.hooks.js.map +4 -4
  241. package/dist/cjs/components/shell.js +1 -1
  242. package/dist/cjs/components/shell.js.map +4 -4
  243. package/dist/cjs/components/shell.types.d.ts +19 -2
  244. package/dist/cjs/components/shell.types.d.ts.map +1 -1
  245. package/dist/cjs/components/shell.types.js +1 -1
  246. package/dist/cjs/components/shell.types.js.map +3 -3
  247. package/dist/cjs/components/sidebar.d.ts +0 -1
  248. package/dist/cjs/components/sidebar.d.ts.map +1 -1
  249. package/dist/cjs/components/sidebar.js +1 -1
  250. package/dist/cjs/components/sidebar.js.map +4 -4
  251. package/dist/cjs/components/sidebar.props.d.ts +0 -5
  252. package/dist/cjs/components/sidebar.props.d.ts.map +1 -1
  253. package/dist/cjs/components/sidebar.props.js +1 -1
  254. package/dist/cjs/components/sidebar.props.js.map +4 -4
  255. package/dist/cjs/components/slider.js +1 -1
  256. package/dist/cjs/components/slider.js.map +4 -4
  257. package/dist/cjs/components/slider.props.d.ts +0 -5
  258. package/dist/cjs/components/slider.props.d.ts.map +1 -1
  259. package/dist/cjs/components/slider.props.js +1 -1
  260. package/dist/cjs/components/slider.props.js.map +4 -4
  261. package/dist/cjs/components/switch.d.ts.map +1 -1
  262. package/dist/cjs/components/switch.js +1 -1
  263. package/dist/cjs/components/switch.js.map +4 -4
  264. package/dist/cjs/components/switch.props.d.ts +0 -5
  265. package/dist/cjs/components/switch.props.d.ts.map +1 -1
  266. package/dist/cjs/components/switch.props.js +1 -1
  267. package/dist/cjs/components/switch.props.js.map +4 -4
  268. package/dist/cjs/components/tab-nav.js +1 -1
  269. package/dist/cjs/components/tab-nav.js.map +4 -4
  270. package/dist/cjs/components/tab-nav.props.js +1 -1
  271. package/dist/cjs/components/tab-nav.props.js.map +4 -4
  272. package/dist/cjs/components/tabs.js +1 -1
  273. package/dist/cjs/components/tabs.js.map +4 -4
  274. package/dist/cjs/components/tabs.props.js +1 -1
  275. package/dist/cjs/components/tabs.props.js.map +4 -4
  276. package/dist/cjs/components/text-area.js.map +1 -1
  277. package/dist/cjs/components/text-area.props.js.map +1 -1
  278. package/dist/cjs/components/text-field.js.map +1 -1
  279. package/dist/cjs/components/text-field.props.js.map +1 -1
  280. package/dist/cjs/components/text.js +1 -1
  281. package/dist/cjs/components/text.js.map +4 -4
  282. package/dist/cjs/components/text.props.d.ts +3 -2
  283. package/dist/cjs/components/text.props.d.ts.map +1 -1
  284. package/dist/cjs/components/text.props.js +1 -1
  285. package/dist/cjs/components/text.props.js.map +4 -4
  286. package/dist/cjs/components/theme-panel.js +3 -3
  287. package/dist/cjs/components/theme-panel.js.map +4 -4
  288. package/dist/cjs/components/theme.js.map +1 -1
  289. package/dist/cjs/components/theme.props.js.map +1 -1
  290. package/dist/cjs/components/toggle-button.js +2 -2
  291. package/dist/cjs/components/toggle-button.js.map +4 -4
  292. package/dist/cjs/components/toggle-icon-button.js +3 -3
  293. package/dist/cjs/components/toggle-icon-button.js.map +4 -4
  294. package/dist/cjs/components/toolbar.js +1 -1
  295. package/dist/cjs/components/toolbar.js.map +4 -4
  296. package/dist/cjs/components/tooltip.js +1 -1
  297. package/dist/cjs/components/tooltip.js.map +4 -4
  298. package/dist/cjs/components/user-card.d.ts.map +1 -1
  299. package/dist/cjs/components/user-card.js +1 -1
  300. package/dist/cjs/components/user-card.js.map +4 -4
  301. package/dist/cjs/components/user-card.props.d.ts +0 -5
  302. package/dist/cjs/components/user-card.props.d.ts.map +1 -1
  303. package/dist/cjs/components/user-card.props.js +1 -1
  304. package/dist/cjs/components/user-card.props.js.map +4 -4
  305. package/dist/cjs/components/virtual-menu.js.map +1 -1
  306. package/dist/cjs/hooks/use-breakpoint.d.ts +5 -0
  307. package/dist/cjs/hooks/use-breakpoint.d.ts.map +1 -1
  308. package/dist/cjs/hooks/use-breakpoint.js +1 -1
  309. package/dist/cjs/hooks/use-breakpoint.js.map +3 -3
  310. package/dist/cjs/index.js +5 -5
  311. package/dist/cjs/index.js.map +4 -4
  312. package/dist/cjs/props/color.prop.js.map +1 -1
  313. package/dist/cjs/props/emphasis.prop.d.ts +11 -0
  314. package/dist/cjs/props/emphasis.prop.d.ts.map +1 -0
  315. package/dist/cjs/props/emphasis.prop.js +2 -0
  316. package/dist/cjs/props/emphasis.prop.js.map +7 -0
  317. package/dist/cjs/props/index.d.ts +1 -1
  318. package/dist/cjs/props/index.d.ts.map +1 -1
  319. package/dist/cjs/props/index.js +1 -1
  320. package/dist/cjs/props/index.js.map +4 -4
  321. package/dist/esm/{chunk-MBCBP73P.js → chunk-25X75TI7.js} +2 -2
  322. package/dist/esm/chunk-26I257HE.js +2 -0
  323. package/dist/esm/chunk-26I257HE.js.map +7 -0
  324. package/dist/esm/chunk-2CMM7MEL.js +2 -0
  325. package/dist/esm/chunk-2CMM7MEL.js.map +7 -0
  326. package/dist/esm/chunk-2EQWBT2S.js +2 -0
  327. package/dist/esm/chunk-2EQWBT2S.js.map +7 -0
  328. package/dist/esm/{chunk-GLERJXVS.js → chunk-2Q7BJ7YG.js} +2 -2
  329. package/dist/esm/chunk-3AOFY2B4.js +2 -0
  330. package/dist/esm/chunk-3AOFY2B4.js.map +7 -0
  331. package/dist/esm/chunk-3J6AUDID.js +2 -0
  332. package/dist/esm/chunk-3J6AUDID.js.map +7 -0
  333. package/dist/esm/chunk-3KSGRY6I.js +2 -0
  334. package/dist/esm/chunk-3KSGRY6I.js.map +7 -0
  335. package/dist/esm/chunk-3PTSRBVY.js +2 -0
  336. package/dist/esm/{chunk-SZTZ2XLI.js.map → chunk-3PTSRBVY.js.map} +2 -2
  337. package/dist/esm/chunk-3XSB7YIM.js +2 -0
  338. package/dist/esm/{chunk-FMBECDL4.js.map → chunk-3XSB7YIM.js.map} +3 -3
  339. package/dist/esm/{chunk-FIB3XATL.js → chunk-44JZYS7A.js} +3 -3
  340. package/dist/esm/{chunk-FIB3XATL.js.map → chunk-44JZYS7A.js.map} +2 -2
  341. package/dist/esm/{chunk-CTA5ODAO.js → chunk-4WU2WKUJ.js} +2 -2
  342. package/dist/esm/chunk-4WVNMGI5.js +2 -0
  343. package/dist/esm/chunk-4WVNMGI5.js.map +7 -0
  344. package/dist/esm/chunk-5M7STAH3.js +2 -0
  345. package/dist/esm/chunk-5M7STAH3.js.map +7 -0
  346. package/dist/esm/chunk-5SNHUVDA.js +2 -0
  347. package/dist/esm/{chunk-H7ST535H.js → chunk-5TAHT6VC.js} +2 -2
  348. package/dist/esm/chunk-5XV4QEP5.js +2 -0
  349. package/dist/esm/chunk-5XV4QEP5.js.map +7 -0
  350. package/dist/esm/chunk-667BKCUG.js +2 -0
  351. package/dist/esm/chunk-667BKCUG.js.map +7 -0
  352. package/dist/esm/{chunk-MHPPVJDB.js → chunk-67MKPTZJ.js} +2 -2
  353. package/dist/esm/{chunk-UFI53QUC.js → chunk-6J6YX2VX.js} +2 -2
  354. package/dist/esm/chunk-7FKKGUHK.js +2 -0
  355. package/dist/esm/chunk-7FKKGUHK.js.map +7 -0
  356. package/dist/esm/{chunk-UUUZXUIP.js → chunk-7NYODT3Z.js} +2 -2
  357. package/dist/esm/{chunk-NVDXXGVW.js → chunk-7PMMYHZV.js} +2 -2
  358. package/dist/esm/chunk-A2XVR7GL.js +2 -0
  359. package/dist/esm/chunk-A2XVR7GL.js.map +7 -0
  360. package/dist/esm/chunk-ADXZNG4F.js +2 -0
  361. package/dist/esm/chunk-ADXZNG4F.js.map +7 -0
  362. package/dist/esm/chunk-AF6XKU3W.js +2 -0
  363. package/dist/esm/chunk-AF6XKU3W.js.map +7 -0
  364. package/dist/esm/chunk-AGNIFHOE.js +2 -0
  365. package/dist/esm/chunk-AGNIFHOE.js.map +7 -0
  366. package/dist/esm/chunk-AIHQ3MVK.js +2 -0
  367. package/dist/esm/{chunk-SO67YEVQ.js.map → chunk-AIHQ3MVK.js.map} +2 -2
  368. package/dist/esm/{chunk-UBOOUDS4.js → chunk-AO32NT75.js} +2 -2
  369. package/dist/esm/chunk-BZZXXZ3O.js +2 -0
  370. package/dist/esm/chunk-BZZXXZ3O.js.map +7 -0
  371. package/dist/esm/{chunk-JDGJSNWT.js → chunk-C5RVO3C3.js} +2 -2
  372. package/dist/esm/{chunk-IHK3H2OM.js → chunk-CBNTPHYK.js} +2 -2
  373. package/dist/esm/chunk-CFNESRYI.js +2 -0
  374. package/dist/esm/chunk-CFNESRYI.js.map +7 -0
  375. package/dist/esm/{chunk-SESAEJ6W.js → chunk-CLMOWP5T.js} +2 -2
  376. package/dist/esm/{chunk-BBJUB52V.js → chunk-CRBOJ7N7.js} +2 -2
  377. package/dist/esm/{chunk-DUHJVT64.js → chunk-CRSHBENJ.js} +2 -2
  378. package/dist/esm/{chunk-56TS6OKQ.js → chunk-DCIQHXAR.js} +2 -2
  379. package/dist/esm/chunk-EBQZ3Z22.js +2 -0
  380. package/dist/esm/chunk-EBQZ3Z22.js.map +7 -0
  381. package/dist/esm/chunk-EDKQURDU.js +2 -0
  382. package/dist/esm/chunk-EDKQURDU.js.map +7 -0
  383. package/dist/esm/{chunk-43A5GUSI.js → chunk-EHBAK3LQ.js} +2 -2
  384. package/dist/esm/{chunk-2TIADHPD.js → chunk-F3AXE27Q.js} +2 -2
  385. package/dist/esm/chunk-F6V7GBNQ.js +2 -0
  386. package/dist/esm/chunk-F6V7GBNQ.js.map +7 -0
  387. package/dist/esm/{chunk-VA4CTVQL.js → chunk-FB3PD4Z3.js} +2 -2
  388. package/dist/esm/{chunk-OYF6YXH7.js → chunk-FEAOFF77.js} +2 -2
  389. package/dist/esm/chunk-G4YKBAZT.js +2 -0
  390. package/dist/esm/{chunk-666GX7O5.js.map → chunk-G4YKBAZT.js.map} +2 -2
  391. package/dist/esm/{chunk-ADBLURLJ.js → chunk-GDAKJS64.js} +2 -2
  392. package/dist/esm/{chunk-IEWCQU2S.js → chunk-GGSJXOKR.js} +2 -2
  393. package/dist/esm/chunk-GM7KMQDI.js +2 -0
  394. package/dist/esm/chunk-GMHA5CFH.js +2 -0
  395. package/dist/esm/chunk-GMHA5CFH.js.map +7 -0
  396. package/dist/esm/{chunk-HBR42MIX.js → chunk-H4GR4262.js} +2 -2
  397. package/dist/esm/chunk-HBIF43PT.js +2 -0
  398. package/dist/esm/chunk-HBIF43PT.js.map +7 -0
  399. package/dist/esm/chunk-HCNO7PX6.js +2 -0
  400. package/dist/esm/chunk-HCNO7PX6.js.map +7 -0
  401. package/dist/esm/chunk-HMSSFU6I.js +2 -0
  402. package/dist/esm/{chunk-UIRSGVJG.js.map → chunk-HMSSFU6I.js.map} +2 -2
  403. package/dist/esm/chunk-HWQ3NTJP.js +2 -0
  404. package/dist/esm/chunk-HWQ3NTJP.js.map +7 -0
  405. package/dist/esm/{chunk-S5C5YRBS.js → chunk-IDUVJJYG.js} +2 -2
  406. package/dist/esm/{chunk-P7IAHW4V.js → chunk-IK3MQHA5.js} +2 -2
  407. package/dist/esm/{chunk-SPIU5JYC.js → chunk-JDEBKA56.js} +2 -2
  408. package/dist/esm/{chunk-E67CIG6A.js → chunk-JDWCQ2XP.js} +2 -2
  409. package/dist/esm/chunk-JFWMAYEH.js +2 -0
  410. package/dist/esm/chunk-JFWMAYEH.js.map +7 -0
  411. package/dist/esm/chunk-JQSZF3E2.js +2 -0
  412. package/dist/esm/chunk-JQSZF3E2.js.map +7 -0
  413. package/dist/esm/{chunk-JBO5YOUM.js → chunk-JQW4XYBS.js} +2 -2
  414. package/dist/esm/{chunk-P5OSU4NX.js → chunk-JRFZ535T.js} +2 -2
  415. package/dist/esm/{chunk-GYBLXQ4R.js → chunk-KEEPKI2X.js} +2 -2
  416. package/dist/esm/{chunk-WXP6MMUB.js → chunk-KOFEFBB3.js} +2 -2
  417. package/dist/esm/{chunk-YMUGKYGW.js → chunk-KV4SZP3F.js} +2 -2
  418. package/dist/esm/chunk-KZYFTDGO.js +2 -0
  419. package/dist/esm/chunk-KZYFTDGO.js.map +7 -0
  420. package/dist/esm/{chunk-FG7XM7KJ.js → chunk-LJCUPAOI.js} +2 -2
  421. package/dist/esm/{chunk-MBE2YSBU.js → chunk-MBCQA7UZ.js} +2 -2
  422. package/dist/esm/chunk-MM5IHQFM.js +2 -0
  423. package/dist/esm/{chunk-YVBCDTTD.js → chunk-MN3XALXD.js} +2 -2
  424. package/dist/esm/chunk-NIIEIZKQ.js +2 -0
  425. package/dist/esm/chunk-NIIEIZKQ.js.map +7 -0
  426. package/dist/esm/{chunk-3R7XMRV5.js → chunk-NQXRWBQM.js} +2 -2
  427. package/dist/esm/{chunk-CSKZZOI2.js → chunk-NTNMJX5M.js} +2 -2
  428. package/dist/esm/chunk-NV3P2CKH.js +2 -0
  429. package/dist/esm/chunk-NV3P2CKH.js.map +7 -0
  430. package/dist/esm/{chunk-4ME6O27S.js → chunk-O4CSXNST.js} +2 -2
  431. package/dist/esm/chunk-ODCVOXEV.js +2 -0
  432. package/dist/esm/{chunk-DMJJM5IS.js → chunk-OEEF6KJG.js} +2 -2
  433. package/dist/esm/chunk-OGVKSYLL.js +2 -0
  434. package/dist/esm/chunk-OGVKSYLL.js.map +7 -0
  435. package/dist/esm/{chunk-ABSKRHVM.js → chunk-OJSOX3AX.js} +2 -2
  436. package/dist/esm/chunk-OJU5GCDZ.js +2 -0
  437. package/dist/esm/chunk-OJU5GCDZ.js.map +7 -0
  438. package/dist/esm/{chunk-JGLAE5G7.js → chunk-OQU2SKLN.js} +2 -2
  439. package/dist/esm/chunk-OTKQN2KY.js +2 -0
  440. package/dist/esm/chunk-OTKQN2KY.js.map +7 -0
  441. package/dist/esm/{chunk-UWT6TE5D.js → chunk-OTXCKEWT.js} +2 -2
  442. package/dist/esm/chunk-OWMA6GTG.js +2 -0
  443. package/dist/esm/chunk-OWMA6GTG.js.map +7 -0
  444. package/dist/esm/{chunk-LAOMR7SE.js → chunk-P27KV2LS.js} +2 -2
  445. package/dist/esm/{chunk-LAOMR7SE.js.map → chunk-P27KV2LS.js.map} +3 -3
  446. package/dist/esm/{chunk-JUY7CBSL.js → chunk-PBFSBHBS.js} +2 -2
  447. package/dist/esm/{chunk-L6PVH3RM.js → chunk-PDUHBDFC.js} +2 -2
  448. package/dist/esm/{chunk-HW324FK3.js → chunk-POG3YABW.js} +2 -2
  449. package/dist/esm/chunk-PYHEBG5I.js +2 -0
  450. package/dist/esm/chunk-PYHEBG5I.js.map +7 -0
  451. package/dist/esm/{chunk-TOOSHJOA.js → chunk-PYXMGEO7.js} +2 -2
  452. package/dist/esm/{chunk-T4UHUQFJ.js → chunk-QEGEUD4D.js} +2 -2
  453. package/dist/esm/chunk-QEL55MLF.js +2 -0
  454. package/dist/esm/chunk-QFPHEY77.js +2 -0
  455. package/dist/esm/chunk-QFPHEY77.js.map +7 -0
  456. package/dist/esm/{chunk-F7IYL2VW.js → chunk-QJVAS7AK.js} +2 -2
  457. package/dist/esm/chunk-QQ62LO3X.js +2 -0
  458. package/dist/esm/chunk-QQ62LO3X.js.map +7 -0
  459. package/dist/esm/chunk-RDAMYQFF.js +2 -0
  460. package/dist/esm/chunk-RDAMYQFF.js.map +7 -0
  461. package/dist/esm/chunk-ROSWI2CL.js +2 -0
  462. package/dist/esm/chunk-ROSWI2CL.js.map +7 -0
  463. package/dist/esm/chunk-RY67WG3O.js +2 -0
  464. package/dist/esm/chunk-RY67WG3O.js.map +7 -0
  465. package/dist/esm/{chunk-DXL6V2A5.js → chunk-SEY4NA45.js} +2 -2
  466. package/dist/esm/{chunk-TS623UPD.js → chunk-TLGXIWAS.js} +2 -2
  467. package/dist/esm/{chunk-6FLLFCBU.js → chunk-UBSLEGQZ.js} +2 -2
  468. package/dist/esm/{chunk-37OGSEQR.js → chunk-UNWPH3SO.js} +2 -2
  469. package/dist/esm/chunk-V5ZSDDVZ.js +2 -0
  470. package/dist/esm/chunk-V5ZSDDVZ.js.map +7 -0
  471. package/dist/esm/chunk-VLTXI4A7.js +2 -0
  472. package/dist/esm/chunk-VLTXI4A7.js.map +7 -0
  473. package/dist/esm/{chunk-HIKVMKYQ.js → chunk-VTIL55SR.js} +2 -2
  474. package/dist/esm/{chunk-CQNPBTM5.js → chunk-W2LD2YE6.js} +2 -2
  475. package/dist/esm/chunk-WGWUEU4K.js +2 -0
  476. package/dist/esm/chunk-WGWUEU4K.js.map +7 -0
  477. package/dist/esm/{chunk-NMKPFUNP.js → chunk-WIDJYVZF.js} +2 -2
  478. package/dist/esm/{chunk-3OBXZUFJ.js → chunk-WJBOOAIO.js} +2 -2
  479. package/dist/esm/chunk-WMGIFPI2.js +2 -0
  480. package/dist/esm/chunk-WMGIFPI2.js.map +7 -0
  481. package/dist/esm/{chunk-7FC7HF76.js → chunk-WQCB7KSH.js} +2 -2
  482. package/dist/esm/{chunk-OWAUCLRT.js → chunk-WZFVTC7P.js} +2 -2
  483. package/dist/esm/chunk-XDDKT4NF.js +2 -0
  484. package/dist/esm/{chunk-DX5JJYMZ.js → chunk-XYVLQDGR.js} +2 -2
  485. package/dist/esm/{chunk-KFA53SVQ.js → chunk-YA5DF67M.js} +2 -2
  486. package/dist/esm/chunk-YA5DF67M.js.map +7 -0
  487. package/dist/esm/chunk-YAQBIO2B.js +2 -0
  488. package/dist/esm/chunk-YAQBIO2B.js.map +7 -0
  489. package/dist/esm/{chunk-VNPNEJI6.js → chunk-YG66IRW4.js} +2 -2
  490. package/dist/esm/chunk-YVSM2LGS.js +2 -0
  491. package/dist/esm/chunk-YVSM2LGS.js.map +7 -0
  492. package/dist/esm/chunk-Z7AZNMNX.js +2 -0
  493. package/dist/esm/chunk-Z7AZNMNX.js.map +7 -0
  494. package/dist/esm/chunk-ZJ33QP5N.js +2 -0
  495. package/dist/esm/{chunk-66ZLZAAJ.js → chunk-ZNK6AH2G.js} +1 -1
  496. package/dist/esm/{chunk-66ZLZAAJ.js.map → chunk-ZNK6AH2G.js.map} +1 -1
  497. package/dist/esm/{chunk-KPBG7CIL.js → chunk-ZO7TTWJI.js} +2 -2
  498. package/dist/esm/{chunk-OGXZHAQL.js → chunk-ZW26J2SA.js} +2 -2
  499. package/dist/esm/chunk-ZWZGUBL4.js +2 -0
  500. package/dist/esm/chunk-ZWZGUBL4.js.map +7 -0
  501. package/dist/esm/components/_internal/base-button.js +1 -1
  502. package/dist/esm/components/_internal/base-button.props.d.ts +2 -7
  503. package/dist/esm/components/_internal/base-button.props.d.ts.map +1 -1
  504. package/dist/esm/components/_internal/base-button.props.js +1 -1
  505. package/dist/esm/components/_internal/base-checkbox.props.d.ts +0 -5
  506. package/dist/esm/components/_internal/base-checkbox.props.d.ts.map +1 -1
  507. package/dist/esm/components/_internal/base-checkbox.props.js +1 -1
  508. package/dist/esm/components/_internal/base-menu.props.d.ts +0 -10
  509. package/dist/esm/components/_internal/base-menu.props.d.ts.map +1 -1
  510. package/dist/esm/components/_internal/base-menu.props.js +1 -1
  511. package/dist/esm/components/_internal/base-menu.utils.js +1 -1
  512. package/dist/esm/components/_internal/base-radio.props.d.ts +0 -5
  513. package/dist/esm/components/_internal/base-radio.props.d.ts.map +1 -1
  514. package/dist/esm/components/_internal/base-radio.props.js +1 -1
  515. package/dist/esm/components/_internal/base-tab-list.props.d.ts +0 -5
  516. package/dist/esm/components/_internal/base-tab-list.props.d.ts.map +1 -1
  517. package/dist/esm/components/_internal/base-tab-list.props.js +1 -1
  518. package/dist/esm/components/_internal/menu-context.js +1 -1
  519. package/dist/esm/components/_internal/shell-bottom.d.ts +6 -7
  520. package/dist/esm/components/_internal/shell-bottom.d.ts.map +1 -1
  521. package/dist/esm/components/_internal/shell-bottom.js +1 -1
  522. package/dist/esm/components/_internal/shell-handles.d.ts +9 -0
  523. package/dist/esm/components/_internal/shell-handles.d.ts.map +1 -1
  524. package/dist/esm/components/_internal/shell-handles.js +1 -1
  525. package/dist/esm/components/_internal/shell-inspector.d.ts +4 -6
  526. package/dist/esm/components/_internal/shell-inspector.d.ts.map +1 -1
  527. package/dist/esm/components/_internal/shell-inspector.js +1 -1
  528. package/dist/esm/components/_internal/shell-pane.d.ts +70 -0
  529. package/dist/esm/components/_internal/shell-pane.d.ts.map +1 -0
  530. package/dist/esm/components/_internal/shell-pane.js +2 -0
  531. package/dist/esm/components/_internal/shell-resizable.d.ts +48 -0
  532. package/dist/esm/components/_internal/shell-resizable.d.ts.map +1 -0
  533. package/dist/esm/components/_internal/shell-resizable.js +2 -0
  534. package/dist/esm/components/_internal/shell-resize.d.ts +11 -3
  535. package/dist/esm/components/_internal/shell-resize.d.ts.map +1 -1
  536. package/dist/esm/components/_internal/shell-resize.js +1 -1
  537. package/dist/esm/components/_internal/shell-rest.d.ts +27 -0
  538. package/dist/esm/components/_internal/shell-rest.d.ts.map +1 -0
  539. package/dist/esm/components/_internal/shell-rest.js +2 -0
  540. package/dist/esm/components/_internal/shell-rest.js.map +7 -0
  541. package/dist/esm/components/_internal/shell-sidebar.d.ts +7 -12
  542. package/dist/esm/components/_internal/shell-sidebar.d.ts.map +1 -1
  543. package/dist/esm/components/_internal/shell-sidebar.js +1 -1
  544. package/dist/esm/components/_internal/shell-store.d.ts +99 -0
  545. package/dist/esm/components/_internal/shell-store.d.ts.map +1 -0
  546. package/dist/esm/components/_internal/shell-store.js +2 -0
  547. package/dist/esm/components/_internal/shell-store.js.map +7 -0
  548. package/dist/esm/components/accordion.js +1 -1
  549. package/dist/esm/components/accordion.props.d.ts +0 -6
  550. package/dist/esm/components/accordion.props.d.ts.map +1 -1
  551. package/dist/esm/components/accordion.props.js +1 -1
  552. package/dist/esm/components/alert-dialog.js +1 -1
  553. package/dist/esm/components/avatar.js +1 -1
  554. package/dist/esm/components/avatar.props.d.ts +0 -5
  555. package/dist/esm/components/avatar.props.d.ts.map +1 -1
  556. package/dist/esm/components/avatar.props.js +1 -1
  557. package/dist/esm/components/badge.js +1 -1
  558. package/dist/esm/components/badge.props.d.ts +0 -5
  559. package/dist/esm/components/badge.props.d.ts.map +1 -1
  560. package/dist/esm/components/badge.props.js +1 -1
  561. package/dist/esm/components/blockquote.js +1 -1
  562. package/dist/esm/components/blockquote.props.d.ts +3 -2
  563. package/dist/esm/components/blockquote.props.d.ts.map +1 -1
  564. package/dist/esm/components/blockquote.props.js +1 -1
  565. package/dist/esm/components/box.js +1 -1
  566. package/dist/esm/components/button.js +1 -1
  567. package/dist/esm/components/button.props.js +1 -1
  568. package/dist/esm/components/callout.js +1 -1
  569. package/dist/esm/components/callout.props.d.ts +0 -5
  570. package/dist/esm/components/callout.props.d.ts.map +1 -1
  571. package/dist/esm/components/callout.props.js +1 -1
  572. package/dist/esm/components/card.js +1 -1
  573. package/dist/esm/components/chatbar.d.ts.map +1 -1
  574. package/dist/esm/components/chatbar.js +1 -1
  575. package/dist/esm/components/checkbox-cards.d.ts.map +1 -1
  576. package/dist/esm/components/checkbox-cards.js +1 -1
  577. package/dist/esm/components/checkbox-cards.props.d.ts +0 -5
  578. package/dist/esm/components/checkbox-cards.props.d.ts.map +1 -1
  579. package/dist/esm/components/checkbox-cards.props.js +1 -1
  580. package/dist/esm/components/checkbox-group.d.ts.map +1 -1
  581. package/dist/esm/components/checkbox-group.js +1 -1
  582. package/dist/esm/components/checkbox-group.props.d.ts +0 -5
  583. package/dist/esm/components/checkbox-group.props.d.ts.map +1 -1
  584. package/dist/esm/components/checkbox-group.props.js +1 -1
  585. package/dist/esm/components/checkbox.js +1 -1
  586. package/dist/esm/components/checkbox.props.js +1 -1
  587. package/dist/esm/components/code.js +1 -1
  588. package/dist/esm/components/code.props.d.ts +3 -2
  589. package/dist/esm/components/code.props.d.ts.map +1 -1
  590. package/dist/esm/components/code.props.js +1 -1
  591. package/dist/esm/components/combobox.d.ts.map +1 -1
  592. package/dist/esm/components/combobox.js +1 -1
  593. package/dist/esm/components/combobox.props.d.ts +1 -11
  594. package/dist/esm/components/combobox.props.d.ts.map +1 -1
  595. package/dist/esm/components/combobox.props.js +1 -1
  596. package/dist/esm/components/container.js +1 -1
  597. package/dist/esm/components/context-menu.d.ts.map +1 -1
  598. package/dist/esm/components/context-menu.js +1 -1
  599. package/dist/esm/components/context-menu.props.js +1 -1
  600. package/dist/esm/components/data-list.js +1 -1
  601. package/dist/esm/components/data-list.props.d.ts +4 -3
  602. package/dist/esm/components/data-list.props.d.ts.map +1 -1
  603. package/dist/esm/components/data-list.props.js +1 -1
  604. package/dist/esm/components/dialog.js +1 -1
  605. package/dist/esm/components/dropdown-menu.d.ts.map +1 -1
  606. package/dist/esm/components/dropdown-menu.js +1 -1
  607. package/dist/esm/components/dropdown-menu.props.js +1 -1
  608. package/dist/esm/components/em.js +1 -1
  609. package/dist/esm/components/em.props.js +1 -1
  610. package/dist/esm/components/flex.js +1 -1
  611. package/dist/esm/components/grid.js +1 -1
  612. package/dist/esm/components/heading.js +1 -1
  613. package/dist/esm/components/heading.props.d.ts +3 -2
  614. package/dist/esm/components/heading.props.d.ts.map +1 -1
  615. package/dist/esm/components/heading.props.js +1 -1
  616. package/dist/esm/components/hover-card.js +1 -1
  617. package/dist/esm/components/icon-button.js +1 -1
  618. package/dist/esm/components/icon-button.props.js +1 -1
  619. package/dist/esm/components/image.js +1 -1
  620. package/dist/esm/components/index.js +1 -1
  621. package/dist/esm/components/inset.js +1 -1
  622. package/dist/esm/components/kbd.js +1 -1
  623. package/dist/esm/components/link.js +1 -1
  624. package/dist/esm/components/link.props.d.ts +0 -5
  625. package/dist/esm/components/link.props.d.ts.map +1 -1
  626. package/dist/esm/components/link.props.js +1 -1
  627. package/dist/esm/components/navbar.js +1 -1
  628. package/dist/esm/components/popover.js +1 -1
  629. package/dist/esm/components/progress.js +1 -1
  630. package/dist/esm/components/progress.props.d.ts +0 -5
  631. package/dist/esm/components/progress.props.d.ts.map +1 -1
  632. package/dist/esm/components/progress.props.js +1 -1
  633. package/dist/esm/components/quote.js +1 -1
  634. package/dist/esm/components/quote.props.js +1 -1
  635. package/dist/esm/components/radio-cards.js +1 -1
  636. package/dist/esm/components/radio-cards.props.d.ts +0 -5
  637. package/dist/esm/components/radio-cards.props.d.ts.map +1 -1
  638. package/dist/esm/components/radio-cards.props.js +1 -1
  639. package/dist/esm/components/radio-group.d.ts.map +1 -1
  640. package/dist/esm/components/radio-group.js +1 -1
  641. package/dist/esm/components/radio-group.props.d.ts +0 -5
  642. package/dist/esm/components/radio-group.props.d.ts.map +1 -1
  643. package/dist/esm/components/radio-group.props.js +1 -1
  644. package/dist/esm/components/radio.js +1 -1
  645. package/dist/esm/components/radio.props.js +1 -1
  646. package/dist/esm/components/schemas/base-button.schema.d.ts +0 -1
  647. package/dist/esm/components/schemas/base-button.schema.d.ts.map +1 -1
  648. package/dist/esm/components/schemas/base-button.schema.js +1 -1
  649. package/dist/esm/components/schemas/button.schema.d.ts +0 -1
  650. package/dist/esm/components/schemas/button.schema.d.ts.map +1 -1
  651. package/dist/esm/components/schemas/button.schema.js +1 -1
  652. package/dist/esm/components/schemas/icon-button.schema.d.ts +0 -1
  653. package/dist/esm/components/schemas/icon-button.schema.d.ts.map +1 -1
  654. package/dist/esm/components/schemas/icon-button.schema.js +1 -1
  655. package/dist/esm/components/schemas/index.js +1 -1
  656. package/dist/esm/components/schemas/shell.schema.d.ts +277 -229
  657. package/dist/esm/components/schemas/shell.schema.d.ts.map +1 -1
  658. package/dist/esm/components/schemas/shell.schema.js +1 -1
  659. package/dist/esm/components/schemas/toggle-button.schema.d.ts +0 -1
  660. package/dist/esm/components/schemas/toggle-button.schema.d.ts.map +1 -1
  661. package/dist/esm/components/schemas/toggle-button.schema.js +1 -1
  662. package/dist/esm/components/schemas/toggle-icon-button.schema.d.ts +0 -1
  663. package/dist/esm/components/schemas/toggle-icon-button.schema.d.ts.map +1 -1
  664. package/dist/esm/components/schemas/toggle-icon-button.schema.js +1 -1
  665. package/dist/esm/components/scroll-area.js +1 -1
  666. package/dist/esm/components/section.js +1 -1
  667. package/dist/esm/components/segmented-control.js +1 -1
  668. package/dist/esm/components/select.js +1 -1
  669. package/dist/esm/components/select.props.d.ts +0 -5
  670. package/dist/esm/components/select.props.d.ts.map +1 -1
  671. package/dist/esm/components/select.props.js +1 -1
  672. package/dist/esm/components/separator.js +1 -1
  673. package/dist/esm/components/separator.props.js +1 -1
  674. package/dist/esm/components/sheet.js +1 -1
  675. package/dist/esm/components/shell.context.d.ts +25 -114
  676. package/dist/esm/components/shell.context.d.ts.map +1 -1
  677. package/dist/esm/components/shell.context.js +1 -1
  678. package/dist/esm/components/shell.d.ts +42 -21
  679. package/dist/esm/components/shell.d.ts.map +1 -1
  680. package/dist/esm/components/shell.hooks.d.ts +7 -23
  681. package/dist/esm/components/shell.hooks.d.ts.map +1 -1
  682. package/dist/esm/components/shell.hooks.js +1 -1
  683. package/dist/esm/components/shell.js +1 -1
  684. package/dist/esm/components/shell.types.d.ts +19 -2
  685. package/dist/esm/components/shell.types.d.ts.map +1 -1
  686. package/dist/esm/components/shell.types.js +1 -1
  687. package/dist/esm/components/sidebar.d.ts +0 -1
  688. package/dist/esm/components/sidebar.d.ts.map +1 -1
  689. package/dist/esm/components/sidebar.js +1 -1
  690. package/dist/esm/components/sidebar.props.d.ts +0 -5
  691. package/dist/esm/components/sidebar.props.d.ts.map +1 -1
  692. package/dist/esm/components/sidebar.props.js +1 -1
  693. package/dist/esm/components/skeleton.js +1 -1
  694. package/dist/esm/components/slider.js +1 -1
  695. package/dist/esm/components/slider.props.d.ts +0 -5
  696. package/dist/esm/components/slider.props.d.ts.map +1 -1
  697. package/dist/esm/components/slider.props.js +1 -1
  698. package/dist/esm/components/spinner.js +1 -1
  699. package/dist/esm/components/strong.js +1 -1
  700. package/dist/esm/components/strong.props.js +1 -1
  701. package/dist/esm/components/switch.d.ts.map +1 -1
  702. package/dist/esm/components/switch.js +1 -1
  703. package/dist/esm/components/switch.props.d.ts +0 -5
  704. package/dist/esm/components/switch.props.d.ts.map +1 -1
  705. package/dist/esm/components/switch.props.js +1 -1
  706. package/dist/esm/components/tab-nav.js +1 -1
  707. package/dist/esm/components/tab-nav.props.js +1 -1
  708. package/dist/esm/components/table.js +1 -1
  709. package/dist/esm/components/tabs.js +1 -1
  710. package/dist/esm/components/tabs.props.js +1 -1
  711. package/dist/esm/components/text-area.js +1 -1
  712. package/dist/esm/components/text-area.props.js +1 -1
  713. package/dist/esm/components/text-field.js +1 -1
  714. package/dist/esm/components/text-field.props.js +1 -1
  715. package/dist/esm/components/text.js +1 -1
  716. package/dist/esm/components/text.props.d.ts +3 -2
  717. package/dist/esm/components/text.props.d.ts.map +1 -1
  718. package/dist/esm/components/text.props.js +1 -1
  719. package/dist/esm/components/theme-panel.js +1 -1
  720. package/dist/esm/components/theme.js +1 -1
  721. package/dist/esm/components/theme.props.js +1 -1
  722. package/dist/esm/components/toggle-button.js +1 -1
  723. package/dist/esm/components/toggle-icon-button.js +1 -1
  724. package/dist/esm/components/toolbar.js +1 -1
  725. package/dist/esm/components/tooltip.js +1 -1
  726. package/dist/esm/components/user-card.d.ts.map +1 -1
  727. package/dist/esm/components/user-card.js +1 -1
  728. package/dist/esm/components/user-card.props.d.ts +0 -5
  729. package/dist/esm/components/user-card.props.d.ts.map +1 -1
  730. package/dist/esm/components/user-card.props.js +1 -1
  731. package/dist/esm/components/virtual-menu.js +1 -1
  732. package/dist/esm/helpers/extract-props.js +1 -1
  733. package/dist/esm/helpers/get-margin-styles.js +1 -1
  734. package/dist/esm/helpers/get-responsive-styles.js +1 -1
  735. package/dist/esm/helpers/index.js +1 -1
  736. package/dist/esm/hooks/index.js +1 -1
  737. package/dist/esm/hooks/use-breakpoint.d.ts +5 -0
  738. package/dist/esm/hooks/use-breakpoint.d.ts.map +1 -1
  739. package/dist/esm/hooks/use-breakpoint.js +1 -1
  740. package/dist/esm/index.js +1 -1
  741. package/dist/esm/props/color.prop.js +1 -1
  742. package/dist/esm/props/emphasis.prop.d.ts +11 -0
  743. package/dist/esm/props/emphasis.prop.d.ts.map +1 -0
  744. package/dist/esm/props/emphasis.prop.js +2 -0
  745. package/dist/esm/props/emphasis.prop.js.map +7 -0
  746. package/dist/esm/props/index.d.ts +1 -1
  747. package/dist/esm/props/index.d.ts.map +1 -1
  748. package/dist/esm/props/index.js +1 -1
  749. package/package.json +7 -2
  750. package/schemas/base-button.json +0 -5
  751. package/schemas/button.json +0 -5
  752. package/schemas/icon-button.json +0 -5
  753. package/schemas/index.json +1655 -25
  754. package/schemas/shell-bottom.d.ts +2 -0
  755. package/schemas/shell-bottom.json +180 -76
  756. package/schemas/shell-content.d.ts +2 -0
  757. package/schemas/shell-content.json +11 -5
  758. package/schemas/shell-handle.d.ts +2 -0
  759. package/schemas/shell-handle.json +7 -5
  760. package/schemas/shell-header.d.ts +2 -0
  761. package/schemas/shell-header.json +9 -10
  762. package/schemas/shell-inspector.d.ts +2 -0
  763. package/schemas/shell-inspector.json +183 -79
  764. package/schemas/shell-panel.d.ts +2 -0
  765. package/schemas/shell-panel.json +180 -76
  766. package/schemas/shell-rail.d.ts +2 -0
  767. package/schemas/shell-rail.json +137 -64
  768. package/schemas/shell-root.d.ts +2 -0
  769. package/schemas/shell-root.json +11 -9
  770. package/schemas/shell-sidebar.d.ts +2 -0
  771. package/schemas/shell-sidebar.json +274 -85
  772. package/schemas/shell-trigger.d.ts +2 -0
  773. package/schemas/shell-trigger.json +29 -17
  774. package/schemas/toggle-button.json +0 -5
  775. package/schemas/toggle-icon-button.json +0 -5
  776. package/src/components/_internal/base-button.css +14 -69
  777. package/src/components/_internal/base-button.props.ts +2 -4
  778. package/src/components/_internal/base-checkbox.css +9 -63
  779. package/src/components/_internal/base-checkbox.props.ts +0 -2
  780. package/src/components/_internal/base-menu.css +7 -59
  781. package/src/components/_internal/base-menu.props.ts +0 -2
  782. package/src/components/_internal/base-radio.css +9 -46
  783. package/src/components/_internal/base-radio.props.ts +0 -2
  784. package/src/components/_internal/base-sidebar-menu.css +3 -3
  785. package/src/components/_internal/base-tab-list.css +1 -7
  786. package/src/components/_internal/base-tab-list.props.ts +0 -2
  787. package/src/components/_internal/shell-bottom.tsx +92 -361
  788. package/src/components/_internal/shell-handles.tsx +193 -108
  789. package/src/components/_internal/shell-inspector.tsx +93 -360
  790. package/src/components/_internal/shell-pane.tsx +283 -0
  791. package/src/components/_internal/shell-resizable.tsx +263 -0
  792. package/src/components/_internal/shell-resize.tsx +11 -3
  793. package/src/components/_internal/shell-rest.ts +45 -0
  794. package/src/components/_internal/shell-sidebar.tsx +130 -441
  795. package/src/components/_internal/shell-store.tsx +204 -0
  796. package/src/components/accordion.css +4 -62
  797. package/src/components/accordion.props.tsx +0 -3
  798. package/src/components/avatar.css +10 -61
  799. package/src/components/avatar.props.tsx +0 -2
  800. package/src/components/badge.css +7 -32
  801. package/src/components/badge.props.tsx +0 -2
  802. package/src/components/blockquote.props.tsx +2 -2
  803. package/src/components/callout.css +5 -25
  804. package/src/components/callout.props.tsx +0 -2
  805. package/src/components/chatbar.tsx +6 -3
  806. package/src/components/checkbox-cards.props.tsx +0 -2
  807. package/src/components/checkbox-cards.tsx +1 -4
  808. package/src/components/checkbox-group.tsx +0 -2
  809. package/src/components/code.css +36 -36
  810. package/src/components/code.props.tsx +2 -2
  811. package/src/components/combobox.css +4 -10
  812. package/src/components/combobox.props.tsx +1 -5
  813. package/src/components/combobox.tsx +4 -8
  814. package/src/components/context-menu.tsx +5 -8
  815. package/src/components/data-list.css +14 -9
  816. package/src/components/data-list.props.tsx +5 -2
  817. package/src/components/dropdown-menu.tsx +5 -9
  818. package/src/components/heading.css +16 -5
  819. package/src/components/heading.props.tsx +2 -2
  820. package/src/components/link.css +3 -4
  821. package/src/components/link.props.tsx +0 -2
  822. package/src/components/progress.css +3 -10
  823. package/src/components/progress.props.tsx +0 -2
  824. package/src/components/radio-cards.css +1 -4
  825. package/src/components/radio-cards.props.tsx +0 -2
  826. package/src/components/radio-group.props.tsx +0 -2
  827. package/src/components/radio-group.tsx +0 -2
  828. package/src/components/schemas/base-button.schema.ts +0 -10
  829. package/src/components/schemas/shell.schema.ts +162 -153
  830. package/src/components/select.css +13 -96
  831. package/src/components/select.props.tsx +0 -2
  832. package/src/components/sheet.tsx +2 -2
  833. package/src/components/shell.context.tsx +112 -124
  834. package/src/components/shell.css +637 -496
  835. package/src/components/shell.hooks.ts +12 -170
  836. package/src/components/shell.tsx +566 -1497
  837. package/src/components/shell.types.ts +22 -2
  838. package/src/components/sidebar.css +21 -115
  839. package/src/components/sidebar.props.tsx +0 -2
  840. package/src/components/sidebar.tsx +2 -5
  841. package/src/components/slider.css +4 -37
  842. package/src/components/slider.props.tsx +0 -2
  843. package/src/components/slider.tsx +1 -1
  844. package/src/components/switch.css +4 -23
  845. package/src/components/switch.props.tsx +0 -2
  846. package/src/components/switch.tsx +1 -3
  847. package/src/components/text.css +16 -5
  848. package/src/components/text.props.tsx +2 -2
  849. package/src/components/theme-panel.tsx +1 -1
  850. package/src/components/user-card.props.tsx +0 -2
  851. package/src/components/user-card.tsx +1 -2
  852. package/src/hooks/use-breakpoint.ts +9 -0
  853. package/src/props/color.prop.ts +1 -1
  854. package/src/props/emphasis.prop.ts +19 -0
  855. package/src/props/index.ts +1 -1
  856. package/src/styles/tokens/color.css +109 -0
  857. package/src/styles/tokens/constants.css +0 -1
  858. package/styles.css +970 -1254
  859. package/tokens/base.css +204 -150
  860. package/tokens.css +204 -151
  861. package/dist/cjs/components/_internal/shell-prop-helpers.d.ts +0 -7
  862. package/dist/cjs/components/_internal/shell-prop-helpers.d.ts.map +0 -1
  863. package/dist/cjs/components/_internal/shell-prop-helpers.js +0 -2
  864. package/dist/cjs/components/_internal/shell-prop-helpers.js.map +0 -7
  865. package/dist/cjs/props/high-contrast.prop.d.ts +0 -9
  866. package/dist/cjs/props/high-contrast.prop.d.ts.map +0 -1
  867. package/dist/cjs/props/high-contrast.prop.js +0 -2
  868. package/dist/cjs/props/high-contrast.prop.js.map +0 -7
  869. package/dist/esm/chunk-3DC63EZP.js +0 -2
  870. package/dist/esm/chunk-3DC63EZP.js.map +0 -7
  871. package/dist/esm/chunk-4JQZUQY7.js +0 -2
  872. package/dist/esm/chunk-4SMJ7D4S.js +0 -2
  873. package/dist/esm/chunk-4SMJ7D4S.js.map +0 -7
  874. package/dist/esm/chunk-4TCXI3L3.js +0 -2
  875. package/dist/esm/chunk-4TCXI3L3.js.map +0 -7
  876. package/dist/esm/chunk-5BYHEYO6.js +0 -2
  877. package/dist/esm/chunk-5BYHEYO6.js.map +0 -7
  878. package/dist/esm/chunk-5LXFJMFB.js +0 -2
  879. package/dist/esm/chunk-5LXFJMFB.js.map +0 -7
  880. package/dist/esm/chunk-5MNBQROW.js +0 -2
  881. package/dist/esm/chunk-5MNBQROW.js.map +0 -7
  882. package/dist/esm/chunk-666GX7O5.js +0 -2
  883. package/dist/esm/chunk-6HEAF5IT.js +0 -2
  884. package/dist/esm/chunk-6HEAF5IT.js.map +0 -7
  885. package/dist/esm/chunk-7ESHXHHO.js +0 -2
  886. package/dist/esm/chunk-7ESHXHHO.js.map +0 -7
  887. package/dist/esm/chunk-A3NH376A.js +0 -2
  888. package/dist/esm/chunk-A3NH376A.js.map +0 -7
  889. package/dist/esm/chunk-BI7W34WW.js +0 -2
  890. package/dist/esm/chunk-BI7W34WW.js.map +0 -7
  891. package/dist/esm/chunk-CBR3VIRS.js +0 -2
  892. package/dist/esm/chunk-CBR3VIRS.js.map +0 -7
  893. package/dist/esm/chunk-CECQNGUL.js +0 -2
  894. package/dist/esm/chunk-CECQNGUL.js.map +0 -7
  895. package/dist/esm/chunk-D2AZAGGP.js +0 -2
  896. package/dist/esm/chunk-D2AZAGGP.js.map +0 -7
  897. package/dist/esm/chunk-DCAZPMOB.js +0 -2
  898. package/dist/esm/chunk-DCAZPMOB.js.map +0 -7
  899. package/dist/esm/chunk-DQAUX5ZL.js +0 -2
  900. package/dist/esm/chunk-DQAUX5ZL.js.map +0 -7
  901. package/dist/esm/chunk-F7IUK2I2.js +0 -2
  902. package/dist/esm/chunk-FLBLS7M4.js +0 -2
  903. package/dist/esm/chunk-FLBLS7M4.js.map +0 -7
  904. package/dist/esm/chunk-FMBECDL4.js +0 -2
  905. package/dist/esm/chunk-GSIE6SUD.js +0 -2
  906. package/dist/esm/chunk-GSIE6SUD.js.map +0 -7
  907. package/dist/esm/chunk-HOHUDTTL.js +0 -2
  908. package/dist/esm/chunk-HOHUDTTL.js.map +0 -7
  909. package/dist/esm/chunk-HSAG7C53.js +0 -2
  910. package/dist/esm/chunk-HUKPWYG2.js +0 -2
  911. package/dist/esm/chunk-HUKPWYG2.js.map +0 -7
  912. package/dist/esm/chunk-IDYHZIS6.js +0 -2
  913. package/dist/esm/chunk-IDYHZIS6.js.map +0 -7
  914. package/dist/esm/chunk-IGQRZCAI.js +0 -2
  915. package/dist/esm/chunk-IGQRZCAI.js.map +0 -7
  916. package/dist/esm/chunk-ILRJA7FU.js +0 -2
  917. package/dist/esm/chunk-ILRJA7FU.js.map +0 -7
  918. package/dist/esm/chunk-JJKQ7CGI.js +0 -2
  919. package/dist/esm/chunk-KFA53SVQ.js.map +0 -7
  920. package/dist/esm/chunk-KRDP5SQ7.js +0 -2
  921. package/dist/esm/chunk-KRDP5SQ7.js.map +0 -7
  922. package/dist/esm/chunk-KTAFIHJY.js +0 -2
  923. package/dist/esm/chunk-KTAFIHJY.js.map +0 -7
  924. package/dist/esm/chunk-MCQAJV4K.js +0 -2
  925. package/dist/esm/chunk-MCQAJV4K.js.map +0 -7
  926. package/dist/esm/chunk-MCQCG6AS.js +0 -2
  927. package/dist/esm/chunk-MJ47O7KH.js +0 -2
  928. package/dist/esm/chunk-MJ47O7KH.js.map +0 -7
  929. package/dist/esm/chunk-N2B7TWIP.js +0 -2
  930. package/dist/esm/chunk-N2B7TWIP.js.map +0 -7
  931. package/dist/esm/chunk-NIQT45PJ.js +0 -2
  932. package/dist/esm/chunk-NKEJTTIL.js +0 -2
  933. package/dist/esm/chunk-NKEJTTIL.js.map +0 -7
  934. package/dist/esm/chunk-NNO7M466.js +0 -2
  935. package/dist/esm/chunk-NNO7M466.js.map +0 -7
  936. package/dist/esm/chunk-PTS6QYQW.js +0 -2
  937. package/dist/esm/chunk-PTS6QYQW.js.map +0 -7
  938. package/dist/esm/chunk-RLPKKCBL.js +0 -2
  939. package/dist/esm/chunk-RLPKKCBL.js.map +0 -7
  940. package/dist/esm/chunk-SNHEJU2S.js +0 -2
  941. package/dist/esm/chunk-SNHEJU2S.js.map +0 -7
  942. package/dist/esm/chunk-SO67YEVQ.js +0 -2
  943. package/dist/esm/chunk-SZTZ2XLI.js +0 -2
  944. package/dist/esm/chunk-T2FZN7G3.js +0 -2
  945. package/dist/esm/chunk-T2FZN7G3.js.map +0 -7
  946. package/dist/esm/chunk-TBJ6L4NL.js +0 -2
  947. package/dist/esm/chunk-TBJ6L4NL.js.map +0 -7
  948. package/dist/esm/chunk-TGN5ZJU5.js +0 -2
  949. package/dist/esm/chunk-TGN5ZJU5.js.map +0 -7
  950. package/dist/esm/chunk-TLWTUKKL.js +0 -2
  951. package/dist/esm/chunk-TLWTUKKL.js.map +0 -7
  952. package/dist/esm/chunk-UIRSGVJG.js +0 -2
  953. package/dist/esm/chunk-UMX5MGLG.js +0 -2
  954. package/dist/esm/chunk-UMX5MGLG.js.map +0 -7
  955. package/dist/esm/chunk-WR7YLY46.js +0 -2
  956. package/dist/esm/chunk-WR7YLY46.js.map +0 -7
  957. package/dist/esm/chunk-WZETC7WV.js +0 -2
  958. package/dist/esm/chunk-WZETC7WV.js.map +0 -7
  959. package/dist/esm/chunk-XGGLYV5D.js +0 -2
  960. package/dist/esm/chunk-XGGLYV5D.js.map +0 -7
  961. package/dist/esm/chunk-XI5YXUCK.js +0 -2
  962. package/dist/esm/chunk-XKASPWCJ.js +0 -2
  963. package/dist/esm/chunk-XKASPWCJ.js.map +0 -7
  964. package/dist/esm/chunk-ZRKE3NVU.js +0 -2
  965. package/dist/esm/chunk-ZRKE3NVU.js.map +0 -7
  966. package/dist/esm/chunk-ZWYYPFZW.js +0 -2
  967. package/dist/esm/chunk-ZWYYPFZW.js.map +0 -7
  968. package/dist/esm/chunk-ZXZOH63L.js +0 -2
  969. package/dist/esm/chunk-ZXZOH63L.js.map +0 -7
  970. package/dist/esm/components/_internal/shell-prop-helpers.d.ts +0 -7
  971. package/dist/esm/components/_internal/shell-prop-helpers.d.ts.map +0 -1
  972. package/dist/esm/components/_internal/shell-prop-helpers.js +0 -2
  973. package/dist/esm/props/high-contrast.prop.d.ts +0 -9
  974. package/dist/esm/props/high-contrast.prop.d.ts.map +0 -1
  975. package/dist/esm/props/high-contrast.prop.js +0 -2
  976. package/src/components/_internal/shell-prop-helpers.ts +0 -54
  977. package/src/props/high-contrast.prop.ts +0 -13
  978. /package/dist/esm/{chunk-MBCBP73P.js.map → chunk-25X75TI7.js.map} +0 -0
  979. /package/dist/esm/{chunk-GLERJXVS.js.map → chunk-2Q7BJ7YG.js.map} +0 -0
  980. /package/dist/esm/{chunk-CTA5ODAO.js.map → chunk-4WU2WKUJ.js.map} +0 -0
  981. /package/dist/esm/{chunk-F7IUK2I2.js.map → chunk-5SNHUVDA.js.map} +0 -0
  982. /package/dist/esm/{chunk-H7ST535H.js.map → chunk-5TAHT6VC.js.map} +0 -0
  983. /package/dist/esm/{chunk-MHPPVJDB.js.map → chunk-67MKPTZJ.js.map} +0 -0
  984. /package/dist/esm/{chunk-UFI53QUC.js.map → chunk-6J6YX2VX.js.map} +0 -0
  985. /package/dist/esm/{chunk-UUUZXUIP.js.map → chunk-7NYODT3Z.js.map} +0 -0
  986. /package/dist/esm/{chunk-NVDXXGVW.js.map → chunk-7PMMYHZV.js.map} +0 -0
  987. /package/dist/esm/{chunk-UBOOUDS4.js.map → chunk-AO32NT75.js.map} +0 -0
  988. /package/dist/esm/{chunk-JDGJSNWT.js.map → chunk-C5RVO3C3.js.map} +0 -0
  989. /package/dist/esm/{chunk-IHK3H2OM.js.map → chunk-CBNTPHYK.js.map} +0 -0
  990. /package/dist/esm/{chunk-SESAEJ6W.js.map → chunk-CLMOWP5T.js.map} +0 -0
  991. /package/dist/esm/{chunk-BBJUB52V.js.map → chunk-CRBOJ7N7.js.map} +0 -0
  992. /package/dist/esm/{chunk-DUHJVT64.js.map → chunk-CRSHBENJ.js.map} +0 -0
  993. /package/dist/esm/{chunk-56TS6OKQ.js.map → chunk-DCIQHXAR.js.map} +0 -0
  994. /package/dist/esm/{chunk-43A5GUSI.js.map → chunk-EHBAK3LQ.js.map} +0 -0
  995. /package/dist/esm/{chunk-2TIADHPD.js.map → chunk-F3AXE27Q.js.map} +0 -0
  996. /package/dist/esm/{chunk-VA4CTVQL.js.map → chunk-FB3PD4Z3.js.map} +0 -0
  997. /package/dist/esm/{chunk-OYF6YXH7.js.map → chunk-FEAOFF77.js.map} +0 -0
  998. /package/dist/esm/{chunk-ADBLURLJ.js.map → chunk-GDAKJS64.js.map} +0 -0
  999. /package/dist/esm/{chunk-IEWCQU2S.js.map → chunk-GGSJXOKR.js.map} +0 -0
  1000. /package/dist/esm/{chunk-4JQZUQY7.js.map → chunk-GM7KMQDI.js.map} +0 -0
  1001. /package/dist/esm/{chunk-HBR42MIX.js.map → chunk-H4GR4262.js.map} +0 -0
  1002. /package/dist/esm/{chunk-S5C5YRBS.js.map → chunk-IDUVJJYG.js.map} +0 -0
  1003. /package/dist/esm/{chunk-P7IAHW4V.js.map → chunk-IK3MQHA5.js.map} +0 -0
  1004. /package/dist/esm/{chunk-SPIU5JYC.js.map → chunk-JDEBKA56.js.map} +0 -0
  1005. /package/dist/esm/{chunk-E67CIG6A.js.map → chunk-JDWCQ2XP.js.map} +0 -0
  1006. /package/dist/esm/{chunk-JBO5YOUM.js.map → chunk-JQW4XYBS.js.map} +0 -0
  1007. /package/dist/esm/{chunk-P5OSU4NX.js.map → chunk-JRFZ535T.js.map} +0 -0
  1008. /package/dist/esm/{chunk-GYBLXQ4R.js.map → chunk-KEEPKI2X.js.map} +0 -0
  1009. /package/dist/esm/{chunk-WXP6MMUB.js.map → chunk-KOFEFBB3.js.map} +0 -0
  1010. /package/dist/esm/{chunk-YMUGKYGW.js.map → chunk-KV4SZP3F.js.map} +0 -0
  1011. /package/dist/esm/{chunk-FG7XM7KJ.js.map → chunk-LJCUPAOI.js.map} +0 -0
  1012. /package/dist/esm/{chunk-MBE2YSBU.js.map → chunk-MBCQA7UZ.js.map} +0 -0
  1013. /package/dist/esm/{chunk-JJKQ7CGI.js.map → chunk-MM5IHQFM.js.map} +0 -0
  1014. /package/dist/esm/{chunk-YVBCDTTD.js.map → chunk-MN3XALXD.js.map} +0 -0
  1015. /package/dist/esm/{chunk-3R7XMRV5.js.map → chunk-NQXRWBQM.js.map} +0 -0
  1016. /package/dist/esm/{chunk-CSKZZOI2.js.map → chunk-NTNMJX5M.js.map} +0 -0
  1017. /package/dist/esm/{chunk-4ME6O27S.js.map → chunk-O4CSXNST.js.map} +0 -0
  1018. /package/dist/esm/{chunk-HSAG7C53.js.map → chunk-ODCVOXEV.js.map} +0 -0
  1019. /package/dist/esm/{chunk-DMJJM5IS.js.map → chunk-OEEF6KJG.js.map} +0 -0
  1020. /package/dist/esm/{chunk-ABSKRHVM.js.map → chunk-OJSOX3AX.js.map} +0 -0
  1021. /package/dist/esm/{chunk-JGLAE5G7.js.map → chunk-OQU2SKLN.js.map} +0 -0
  1022. /package/dist/esm/{chunk-UWT6TE5D.js.map → chunk-OTXCKEWT.js.map} +0 -0
  1023. /package/dist/esm/{chunk-JUY7CBSL.js.map → chunk-PBFSBHBS.js.map} +0 -0
  1024. /package/dist/esm/{chunk-L6PVH3RM.js.map → chunk-PDUHBDFC.js.map} +0 -0
  1025. /package/dist/esm/{chunk-HW324FK3.js.map → chunk-POG3YABW.js.map} +0 -0
  1026. /package/dist/esm/{chunk-TOOSHJOA.js.map → chunk-PYXMGEO7.js.map} +0 -0
  1027. /package/dist/esm/{chunk-T4UHUQFJ.js.map → chunk-QEGEUD4D.js.map} +0 -0
  1028. /package/dist/esm/{chunk-MCQCG6AS.js.map → chunk-QEL55MLF.js.map} +0 -0
  1029. /package/dist/esm/{chunk-F7IYL2VW.js.map → chunk-QJVAS7AK.js.map} +0 -0
  1030. /package/dist/esm/{chunk-DXL6V2A5.js.map → chunk-SEY4NA45.js.map} +0 -0
  1031. /package/dist/esm/{chunk-TS623UPD.js.map → chunk-TLGXIWAS.js.map} +0 -0
  1032. /package/dist/esm/{chunk-6FLLFCBU.js.map → chunk-UBSLEGQZ.js.map} +0 -0
  1033. /package/dist/esm/{chunk-37OGSEQR.js.map → chunk-UNWPH3SO.js.map} +0 -0
  1034. /package/dist/esm/{chunk-HIKVMKYQ.js.map → chunk-VTIL55SR.js.map} +0 -0
  1035. /package/dist/esm/{chunk-CQNPBTM5.js.map → chunk-W2LD2YE6.js.map} +0 -0
  1036. /package/dist/esm/{chunk-NMKPFUNP.js.map → chunk-WIDJYVZF.js.map} +0 -0
  1037. /package/dist/esm/{chunk-3OBXZUFJ.js.map → chunk-WJBOOAIO.js.map} +0 -0
  1038. /package/dist/esm/{chunk-7FC7HF76.js.map → chunk-WQCB7KSH.js.map} +0 -0
  1039. /package/dist/esm/{chunk-OWAUCLRT.js.map → chunk-WZFVTC7P.js.map} +0 -0
  1040. /package/dist/esm/{chunk-XI5YXUCK.js.map → chunk-XDDKT4NF.js.map} +0 -0
  1041. /package/dist/esm/{chunk-DX5JJYMZ.js.map → chunk-XYVLQDGR.js.map} +0 -0
  1042. /package/dist/esm/{chunk-VNPNEJI6.js.map → chunk-YG66IRW4.js.map} +0 -0
  1043. /package/dist/esm/{chunk-NIQT45PJ.js.map → chunk-ZJ33QP5N.js.map} +0 -0
  1044. /package/dist/esm/{chunk-KPBG7CIL.js.map → chunk-ZO7TTWJI.js.map} +0 -0
  1045. /package/dist/esm/{chunk-OGXZHAQL.js.map → chunk-ZW26J2SA.js.map} +0 -0
  1046. /package/dist/esm/components/_internal/{shell-prop-helpers.js.map → shell-pane.js.map} +0 -0
  1047. /package/dist/esm/{props/high-contrast.prop.js.map → components/_internal/shell-resizable.js.map} +0 -0
@@ -1,801 +1,388 @@
1
1
  /**
2
- * Shell Component - Layout Engine + Chrome
2
+ * Shell: the app frame.
3
3
  *
4
- * Philosophy:
5
- * - Shell = layout engine + chrome
6
- * - Manages layout state: expanded/collapsed, fixed/overlay, sizes
7
- * - Does not manage content/navigation state
8
- * - Provides unstyled primitives (slots, triggers)
9
- * - Enforces composition rules (Rail ↔ Panel dependency, Sidebar exclusivity)
4
+ * Since 0.8.0 the Shell is built on kookie-ui-v2's model, behind v1's API:
10
5
  *
11
- * Core Slots:
12
- * - Header: global top bar
13
- * - Rail: slim nav strip
14
- * - Panel: sidebar next to rail
15
- * - Sidebar: alternative to Rail+Panel (exclusive)
16
- * - Content: main work area
17
- * - Inspector: right-side panel
18
- * - Bottom: bottom panel
19
- *
20
- * Composition Rules:
21
- * - Rail + Panel: valid together (Rail collapse → Panel collapse)
22
- * - Sidebar: cannot coexist with Rail or Panel
23
- * - Content: always required
24
- * - Inspector/Bottom: optional, independent
6
+ * - The Root is a CSS grid and renders its children as given, in JSX order.
7
+ * Each pane claims its own grid area, so the Root never scans or reorders
8
+ * children, any child renders, and a pane mounted after the Root works.
9
+ * - State lives on each pane: `auto` (untouched), `open` or `closed`, and the
10
+ * Sidebar's `thin`. An untouched pane follows the window, resolved by the
11
+ * stylesheet, so first paint needs no script and no open-state callback
12
+ * fires on mount or on a resize.
13
+ * - A pane is one element at every width. `overlay` is a posture of that
14
+ * element, not a Sheet swapped in: crossing a breakpoint keeps its scroll
15
+ * position, its focus and its children's state.
16
+ * - The Root owns what an overlay needs: one scrim, `inert` on everything
17
+ * else, focus moved in and returned, Escape, and a scroll lock.
18
+ * - Nothing links panes to each other. A Rail closing no longer closes the
19
+ * Panel; an app that wants that writes it in `onOpenChange`.
25
20
  */
26
21
  'use client';
27
22
 
28
23
  import * as React from 'react';
29
24
  import classNames from 'classnames';
30
- import * as Sheet from './sheet.js';
31
- import { VisuallyHidden } from './visually-hidden.js';
32
- import { useResponsivePresentation, useResponsiveInitialState } from './shell.hooks.js';
25
+ import { useComposedRefs } from 'radix-ui/internal';
33
26
  import { PaneResizeContext } from './_internal/shell-resize.js';
34
27
  import { PaneHandle, PanelHandle } from './_internal/shell-handles.js';
35
- import { omitPaneProps, extractPaneDomProps, mapResponsiveBooleanToPaneMode } from './_internal/shell-prop-helpers.js';
36
28
  import { Sidebar } from './_internal/shell-sidebar.js';
37
29
  import { Bottom } from './_internal/shell-bottom.js';
38
30
  import { Inspector } from './_internal/shell-inspector.js';
39
- import { _BREAKPOINTS } from './shell.types.js';
40
- import type { PresentationValue, ResponsivePresentation, PaneMode, SidebarMode, PaneSizePersistence, Breakpoint, PaneTarget, Responsive, PaneBaseProps, CSSPropertiesWithVars } from './shell.types.js';
41
- import { normalizeToPx } from '../helpers/normalize-to-px.js';
42
- import { useBreakpoint } from '../hooks/use-breakpoint.js';
31
+ import { usePane, paneAttributes, usePresentationTable } from './_internal/shell-pane.js';
32
+ import { splitHandles, useResizablePane } from './_internal/shell-resizable.js';
43
33
  import {
44
- ShellProvider,
45
- useShell,
46
- LeftModeContext,
47
- useLeftMode,
48
- PanelModeContext,
49
- usePanelMode,
50
- SidebarModeContext,
51
- useSidebarMode,
52
- InspectorModeContext,
53
- useInspectorMode,
54
- BottomModeContext,
55
- useBottomMode,
56
- PresentationContext,
57
- PeekContext,
58
- usePeek,
59
- ActionsContext,
60
- useShellActions,
61
- CompositionContext,
62
- InsetContext,
63
- useInset,
34
+ FIXED_TABLE,
35
+ ShellInsetContext,
36
+ ShellStoreContext,
37
+ createShellStore,
38
+ setShellPeek,
39
+ subscribeShellStore,
40
+ useInsetRegistration,
41
+ usePaneEntry,
42
+ useShellStore,
43
+ warnOnce,
64
44
  type InsetPaneId,
65
- } from './shell.context.js';
66
-
67
- // Shell context is provided via ShellProvider (see shell.context.tsx)
68
-
69
- // Pane resize context moved to ./_internal/shell-resize
70
-
71
- // Local PaneHandle moved to ./_internal/shell-handles
72
- // Removed local PaneHandle implementation; using internal PaneHandle
73
-
74
- // Composed Handle wrappers per pane
75
- // Handles moved to ./_internal/shell-handles
76
-
77
- // Hook to resolve responsive presentation
78
- // useResponsivePresentation moved to shell.hooks.ts
79
-
80
- // Hook to resolve responsive mode defaults
81
- // Removed: defaultMode responsiveness
45
+ } from './_internal/shell-store.js';
46
+ import { navigationRest, detailRest, toPaneValue, startAnchoredGrowth, withoutRemovedPaneProps } from './_internal/shell-rest.js';
47
+ import { useShell, useSidebarMode } from './shell.context.js';
48
+ import { useResponsivePresentation } from './shell.hooks.js';
49
+ import { readBreakpoint } from '../hooks/use-breakpoint.js';
50
+ import type { Breakpoint, CSSPropertiesWithVars, PaneBaseProps, PaneMode, PaneName, PaneTarget, ResponsivePresentation, SidebarMode } from './shell.types.js';
82
51
 
83
- // useBreakpoint hook moved to ../hooks/use-breakpoint.ts
84
-
85
- // Reducer-based pane state management to simplify cascading rules
86
- type PaneState = {
87
- leftMode: PaneMode;
88
- panelMode: PaneMode;
89
- sidebarMode: SidebarMode;
90
- inspectorMode: PaneMode;
91
- bottomMode: PaneMode;
92
- };
93
-
94
- type PaneAction =
95
- | { type: 'SET_LEFT_MODE'; mode: PaneMode }
96
- | { type: 'SET_PANEL_MODE'; mode: PaneMode }
97
- | { type: 'SET_SIDEBAR_MODE'; mode: SidebarMode }
98
- | { type: 'SET_INSPECTOR_MODE'; mode: PaneMode }
99
- | { type: 'SET_BOTTOM_MODE'; mode: PaneMode }
100
- | { type: 'TOGGLE_PANE'; target: PaneTarget }
101
- | { type: 'EXPAND_PANE'; target: PaneTarget }
102
- | { type: 'COLLAPSE_PANE'; target: PaneTarget };
103
-
104
- const SHELL_SLOT = Symbol('rtShellSlot');
105
-
106
- function assignShellSlot<T extends React.ComponentType<any>>(component: T, slot: string): T {
107
- (component as any)[SHELL_SLOT] = slot;
108
- return component;
109
- }
110
-
111
- /**
112
- * Check if an element matches a component by type or displayName.
113
- * Uses displayName comparison to handle minification scenarios.
114
- */
115
- const isShellComponentType = (el: React.ReactElement, comp: React.ComponentType & { displayName?: string }): boolean =>
116
- React.isValidElement(el) && (el.type === comp || (el as any).type?.displayName === comp.displayName);
117
-
118
- // Tag imported slot components so isType remains stable after minification
119
- assignShellSlot(Sidebar as any, 'Shell.Sidebar');
120
- assignShellSlot(Inspector as any, 'Shell.Inspector');
121
- assignShellSlot(Bottom as any, 'Shell.Bottom');
122
-
123
- function paneReducer(state: PaneState, action: PaneAction): PaneState {
124
- switch (action.type) {
125
- case 'SET_LEFT_MODE': {
126
- if (action.mode === 'collapsed') {
127
- if (state.leftMode === 'collapsed' && state.panelMode === 'collapsed') return state;
128
- return { ...state, leftMode: 'collapsed', panelMode: 'collapsed' };
129
- }
130
- if (state.leftMode === action.mode) return state;
131
- return { ...state, leftMode: action.mode };
132
- }
133
- case 'SET_PANEL_MODE': {
134
- if (action.mode === 'expanded' && state.leftMode !== 'expanded') {
135
- return { ...state, leftMode: 'expanded', panelMode: 'expanded' };
136
- }
137
- if (state.panelMode === action.mode) return state;
138
- return { ...state, panelMode: action.mode };
139
- }
140
- case 'SET_SIDEBAR_MODE':
141
- if (state.sidebarMode === action.mode) return state;
142
- return { ...state, sidebarMode: action.mode };
143
- case 'SET_INSPECTOR_MODE':
144
- if (state.inspectorMode === action.mode) return state;
145
- return { ...state, inspectorMode: action.mode };
146
- case 'SET_BOTTOM_MODE':
147
- if (state.bottomMode === action.mode) return state;
148
- return { ...state, bottomMode: action.mode };
149
- case 'TOGGLE_PANE': {
150
- switch (action.target) {
151
- case 'left':
152
- case 'rail':
153
- return { ...state, leftMode: state.leftMode === 'expanded' ? 'collapsed' : 'expanded', panelMode: state.leftMode === 'expanded' ? 'collapsed' : state.panelMode };
154
- case 'panel': {
155
- if (state.leftMode === 'collapsed') {
156
- return { ...state, leftMode: 'expanded', panelMode: 'expanded' };
157
- }
158
- return { ...state, panelMode: state.panelMode === 'expanded' ? 'collapsed' : 'expanded' };
159
- }
160
- case 'sidebar': {
161
- const next: SidebarMode = state.sidebarMode === 'collapsed' ? 'expanded' : state.sidebarMode === 'expanded' ? 'collapsed' : 'expanded';
162
- return { ...state, sidebarMode: next };
163
- }
164
- case 'inspector':
165
- return { ...state, inspectorMode: state.inspectorMode === 'expanded' ? 'collapsed' : 'expanded' };
166
- case 'bottom':
167
- return { ...state, bottomMode: state.bottomMode === 'expanded' ? 'collapsed' : 'expanded' };
168
- default:
169
- return state;
170
- }
171
- }
172
- case 'EXPAND_PANE': {
173
- switch (action.target) {
174
- case 'left':
175
- case 'rail':
176
- if (state.leftMode === 'expanded') return state;
177
- return { ...state, leftMode: 'expanded' };
178
- case 'panel':
179
- if (state.leftMode === 'expanded' && state.panelMode === 'expanded') return state;
180
- return { ...state, leftMode: 'expanded', panelMode: 'expanded' };
181
- case 'sidebar':
182
- if (state.sidebarMode === 'expanded') return state;
183
- return { ...state, sidebarMode: 'expanded' };
184
- case 'inspector':
185
- if (state.inspectorMode === 'expanded') return state;
186
- return { ...state, inspectorMode: 'expanded' };
187
- case 'bottom':
188
- if (state.bottomMode === 'expanded') return state;
189
- return { ...state, bottomMode: 'expanded' };
190
- default:
191
- return state;
192
- }
193
- }
194
- case 'COLLAPSE_PANE': {
195
- switch (action.target) {
196
- case 'left':
197
- case 'rail':
198
- if (state.leftMode === 'collapsed' && state.panelMode === 'collapsed') return state;
199
- return { ...state, leftMode: 'collapsed', panelMode: 'collapsed' };
200
- case 'panel':
201
- if (state.panelMode === 'collapsed') return state;
202
- return { ...state, panelMode: 'collapsed' };
203
- case 'sidebar':
204
- if (state.sidebarMode === 'collapsed') return state;
205
- return { ...state, sidebarMode: 'collapsed' };
206
- case 'inspector':
207
- if (state.inspectorMode === 'collapsed') return state;
208
- return { ...state, inspectorMode: 'collapsed' };
209
- case 'bottom':
210
- if (state.bottomMode === 'collapsed') return state;
211
- return { ...state, bottomMode: 'collapsed' };
212
- default:
213
- return state;
214
- }
215
- }
216
- }
217
- return state;
218
- }
52
+ /* ── Root ──────────────────────────────────────────────────────────────────── */
219
53
 
220
- // Root Component
221
- interface ShellRootProps extends React.ComponentPropsWithoutRef<'div'> {
54
+ export interface ShellRootProps extends React.ComponentPropsWithoutRef<'div'> {
222
55
  children: React.ReactNode;
223
56
  height?: 'full' | 'auto' | string | number;
224
57
  }
225
58
 
226
59
  /**
227
- * Read the pane modes a set of Shell children asks for.
228
- *
229
- * Runs once at mount, for the reducer's initial state, and again whenever a
230
- * pane family enters after mount. Pure - it only reads the children's props.
231
- */
232
- /**
233
- * Pick the entry of a responsive map that applies at `breakpoint`, falling
234
- * back down the scale the way useResponsiveValue does. With no breakpoint it
235
- * takes `initial`, which is what the mount path has always done.
60
+ * Every Shell with a live overlay holds the page still, counted across Shells,
61
+ * through an attribute the stylesheet reads. Saving and restoring the
62
+ * document's inline `overflow` would fight any other scroll lock on the page.
236
63
  */
237
- function pickResponsive<T>(map: Partial<Record<Breakpoint, T>>, breakpoint?: Breakpoint): T | undefined {
238
- if (breakpoint === undefined) return (map.initial ?? Object.values(map)[0]) as T | undefined;
239
- if (map[breakpoint] !== undefined) return map[breakpoint];
240
-
241
- const bpKeys = Object.keys(_BREAKPOINTS) as Array<keyof typeof _BREAKPOINTS>;
242
- const order: Breakpoint[] = ([...bpKeys].reverse() as Breakpoint[]).concat('initial' as Breakpoint);
243
- for (let i = order.indexOf(breakpoint) + 1; i < order.length; i++) {
244
- if (map[order[i]] !== undefined) return map[order[i]];
245
- }
246
- return undefined;
64
+ let pageLockHolders = 0;
65
+ function updatePageLock(delta: 1 | -1) {
66
+ pageLockHolders = Math.max(0, pageLockHolders + delta);
67
+ const doc = document.documentElement;
68
+ if (pageLockHolders > 0) doc.setAttribute('data-rt-shell-lock', '');
69
+ else doc.removeAttribute('data-rt-shell-lock');
247
70
  }
248
71
 
249
- function readPaneStateFromChildren(initialChildren: React.ReactNode, breakpoint?: Breakpoint): PaneState & { hasPanelDefaultOpen: boolean } {
250
- const childArray = React.Children.toArray(initialChildren) as React.ReactElement[];
72
+ /** Marks a child the Root made inert, so closing removes only what the Root added. */
73
+ const INERT_MARK = 'data-rt-shell-inert';
251
74
 
252
- // Compute initial defaults from immediate children (one-time, uncontrolled defaults)
253
- const hasPanelDefaultOpen = childArray.some(
254
- (el) => React.isValidElement(el) && (el as any).type?.displayName === 'Shell.Panel' && Boolean((el as any).props?.defaultOpen),
255
- );
256
-
257
- // Rail defaults to open (true) unless explicitly set to false
258
- // Supports responsive objects: { initial: false, md: true }
259
- const railEl = childArray.find((el) => React.isValidElement(el) && (el as any).type?.displayName === 'Shell.Rail');
260
- const railDefaultOpen = railEl ? (railEl as any).props?.defaultOpen : undefined;
261
- const hasRailDefaultOpen = (() => {
262
- if (!railEl) return false;
263
- if (railDefaultOpen === undefined) return true; // Default to open
264
- if (typeof railDefaultOpen === 'boolean') return railDefaultOpen;
265
- // Responsive object - use 'initial' value, or first defined value, or default true
266
- if (typeof railDefaultOpen === 'object') {
267
- return railDefaultOpen.initial ?? Object.values(railDefaultOpen)[0] ?? true;
268
- }
269
- return true;
270
- })();
271
-
272
- const hasInspectorDefaultOpen = childArray.some(
273
- (el) => React.isValidElement(el) && (el as any).type?.displayName === 'Shell.Inspector' && Boolean((el as any).props?.defaultOpen),
274
- );
275
- const hasInspectorOpenControlled = childArray.some(
276
- (el) =>
277
- React.isValidElement(el) &&
278
- (el as any).type?.displayName === 'Shell.Inspector' &&
279
- typeof (el as any).props?.open !== 'undefined' &&
280
- Boolean((el as any).props?.open),
281
- );
282
-
283
- // Detect Panel controlled open state for initial reducer state
284
- const hasPanelOpenControlled = childArray.some((el) => {
285
- if (!React.isValidElement(el) || (el as any).type?.displayName !== 'Shell.Panel') return false;
286
- const openProp = (el as any).props?.open;
287
- if (typeof openProp === 'undefined') return false;
288
- if (typeof openProp === 'boolean') return openProp;
289
- // Responsive object - check 'initial' or first truthy value
290
- if (typeof openProp === 'object' && openProp !== null) {
291
- return openProp.initial ?? Object.values(openProp)[0] ?? false;
292
- }
293
- return false;
294
- });
75
+ /** How many frames a focus rescue watches after an overlay opens or closes. */
76
+ const RESCUE_FRAMES = 30;
295
77
 
296
- // Detect Sidebar initial state from props
297
- const getSidebarInitialState = (): SidebarMode => {
298
- const sidebarEl = childArray.find((el) => React.isValidElement(el) && (el as any).type?.displayName === 'Shell.Sidebar');
299
- if (!sidebarEl) return 'expanded';
300
- const sidebarProps = (sidebarEl as any).props;
301
- // Check controlled state first
302
- if (typeof sidebarProps?.state !== 'undefined') {
303
- if (typeof sidebarProps.state === 'string') return sidebarProps.state as SidebarMode;
304
- // Responsive object - use 'initial' breakpoint or first defined value
305
- if (typeof sidebarProps.state === 'object') {
306
- return (pickResponsive<SidebarMode>(sidebarProps.state, breakpoint) ?? 'expanded') as SidebarMode;
307
- }
308
- }
309
- // Check defaultState
310
- if (typeof sidebarProps?.defaultState !== 'undefined') {
311
- if (typeof sidebarProps.defaultState === 'string') return sidebarProps.defaultState as SidebarMode;
312
- if (typeof sidebarProps.defaultState === 'object') {
313
- return (pickResponsive<SidebarMode>(sidebarProps.defaultState, breakpoint) ?? 'expanded') as SidebarMode;
314
- }
315
- }
316
- return 'expanded';
317
- };
318
-
319
- // Detect Bottom initial state from props
320
- const getBottomInitialState = (): PaneMode => {
321
- const bottomEl = childArray.find((el) => React.isValidElement(el) && (el as any).type?.displayName === 'Shell.Bottom');
322
- if (!bottomEl) return 'collapsed';
323
- const bottomProps = (bottomEl as any).props;
324
- // Check controlled open first
325
- if (typeof bottomProps?.open !== 'undefined') {
326
- if (typeof bottomProps.open === 'boolean') return bottomProps.open ? 'expanded' : 'collapsed';
327
- // Responsive object - use 'initial' breakpoint or first defined value
328
- if (typeof bottomProps.open === 'object') {
329
- const val = bottomProps.open.initial ?? Object.values(bottomProps.open)[0];
330
- return val ? 'expanded' : 'collapsed';
331
- }
332
- }
333
- // Check defaultOpen
334
- if (typeof bottomProps?.defaultOpen !== 'undefined') {
335
- return bottomProps.defaultOpen ? 'expanded' : 'collapsed';
336
- }
337
- return 'collapsed';
338
- };
78
+ /** Focus that is nowhere useful: the document, or nothing at all. */
79
+ function isNowhere(doc: Document, el: Element | EventTarget | null): boolean {
80
+ return el === null || el === doc || el === doc.body || el === doc.documentElement;
81
+ }
339
82
 
340
- return {
341
- hasPanelDefaultOpen,
342
- leftMode: hasPanelDefaultOpen || hasPanelOpenControlled || hasRailDefaultOpen ? 'expanded' : ('collapsed' as PaneMode),
343
- panelMode: hasPanelDefaultOpen || hasPanelOpenControlled ? 'expanded' : ('collapsed' as PaneMode),
344
- sidebarMode: getSidebarInitialState(),
345
- inspectorMode: hasInspectorDefaultOpen || hasInspectorOpenControlled ? 'expanded' : ('collapsed' as PaneMode),
346
- bottomMode: getBottomInitialState(),
347
- };
83
+ /** A Trigger that drives the pane with this id and can take focus, optionally only inside `within`. */
84
+ function triggerFor(doc: Document, id: string, within?: HTMLElement[]): HTMLElement | null {
85
+ for (const el of doc.querySelectorAll<HTMLElement>('[data-shell-trigger][aria-controls]')) {
86
+ if (el.getAttribute('aria-controls') !== id || el.closest('[inert]')) continue;
87
+ if (within && !within.some((pane) => pane.contains(el))) continue;
88
+ return el;
89
+ }
90
+ return null;
348
91
  }
349
92
 
350
- const Root = React.forwardRef<HTMLDivElement, ShellRootProps>(({ className, children, height = 'full', ...props }, ref) => {
351
- const { breakpoint: currentBreakpoint, ready: currentBreakpointReady } = useBreakpoint();
93
+ type LivePane = { name: PaneName; id: string; el: HTMLElement };
94
+
95
+ const Root = React.forwardRef<HTMLDivElement, ShellRootProps>(({ className, children, height = 'full', style, onKeyDown, onFocus, ...props }, ref) => {
96
+ const [store] = React.useState(createShellStore);
97
+ const subscribe = React.useCallback((listener: () => void) => subscribeShellStore(store, listener), [store]);
98
+ // Subscribed for the re-render, not for a value: a pane opening or closing
99
+ // must bring the Root back so containment and the scrim follow it.
100
+ React.useSyncExternalStore(
101
+ subscribe,
102
+ () => store.version,
103
+ () => 0,
104
+ );
352
105
 
353
- // Store hasPanelDefaultOpen for use in passthrough props (computed once during lazy init)
354
- const hasPanelDefaultOpenRef = React.useRef<boolean>(false);
106
+ const rootRef = React.useRef<HTMLDivElement | null>(null);
107
+ const composedRef = useComposedRefs(ref, rootRef);
355
108
 
356
- // Pane state management via reducer with lazy initialization
357
- // This computation only runs once on mount, not on every render
358
- const [paneState, dispatchPane] = React.useReducer(paneReducer, children, (initialChildren) => {
359
- const { hasPanelDefaultOpen, ...modes } = readPaneStateFromChildren(initialChildren);
360
- // Store for use in passthrough props
361
- hasPanelDefaultOpenRef.current = hasPanelDefaultOpen;
362
- return modes;
363
- });
364
- const setLeftMode = React.useCallback((mode: PaneMode) => dispatchPane({ type: 'SET_LEFT_MODE', mode }), []);
365
- const setPanelMode = React.useCallback((mode: PaneMode) => dispatchPane({ type: 'SET_PANEL_MODE', mode }), []);
366
- const setSidebarMode = React.useCallback((mode: SidebarMode) => dispatchPane({ type: 'SET_SIDEBAR_MODE', mode }), []);
367
- const setInspectorMode = React.useCallback((mode: PaneMode) => dispatchPane({ type: 'SET_INSPECTOR_MODE', mode }), []);
368
- const setBottomMode = React.useCallback((mode: PaneMode) => dispatchPane({ type: 'SET_BOTTOM_MODE', mode }), []);
369
-
370
- // Removed: defaultMode responsiveness and manual change tracking
371
-
372
- // Composition detection
373
- const [hasLeft, setHasLeft] = React.useState(false);
374
- const [hasSidebar, setHasSidebar] = React.useState(false);
375
-
376
- // Customizable sidebar toggle sequencing
377
- const sidebarToggleComputerRef = React.useRef<(current: SidebarMode) => SidebarMode>((current) => (current === 'collapsed' ? 'thin' : current === 'thin' ? 'expanded' : 'collapsed'));
378
- const setSidebarToggleComputer = React.useCallback((fn: (current: SidebarMode) => SidebarMode) => {
379
- sidebarToggleComputerRef.current = fn;
109
+ // Inset: the Root paints the backdrop while any pane is inset.
110
+ const [insetPanes, setInsetPanes] = React.useState<ReadonlySet<InsetPaneId>>(() => new Set());
111
+ const registerInset = React.useCallback((id: InsetPaneId) => {
112
+ setInsetPanes((prev) => (prev.has(id) ? prev : new Set(prev).add(id)));
380
113
  }, []);
114
+ const unregisterInset = React.useCallback((id: InsetPaneId) => {
115
+ setInsetPanes((prev) => {
116
+ if (!prev.has(id)) return prev;
117
+ const next = new Set(prev);
118
+ next.delete(id);
119
+ return next;
120
+ });
121
+ }, []);
122
+ const insetContext = React.useMemo(() => ({ registerInset, unregisterInset }), [registerInset, unregisterInset]);
381
123
 
382
- // Reducer handles left→panel cascade; no effect needed
383
-
384
- // Composition validation
385
- React.useLayoutEffect(() => {
386
- if (hasSidebar && hasLeft) {
387
- console.warn('Shell: Sidebar cannot coexist with Rail or Panel. Use either Rail+Panel OR Sidebar.');
124
+ const closeOverlays = React.useCallback(() => {
125
+ for (const entry of store.entries.values()) {
126
+ if (entry.overlayLive) entry.setValue('closed', 'dismiss');
388
127
  }
389
- }, [hasSidebar, hasLeft]);
390
-
391
- // Left presentation + defaults from children
392
- const [devLeftPres, setDevLeftPres] = React.useState<PresentationValue | undefined>(undefined);
393
- const onLeftPres = React.useCallback((p: PresentationValue) => setDevLeftPres(p), []);
394
- const railDefaultSizeRef = React.useRef<number>(64);
395
- const panelDefaultSizeRef = React.useRef<number>(288);
396
- const onRailDefaults = React.useCallback((size: number) => {
397
- railDefaultSizeRef.current = size;
398
- }, []);
399
- const onPanelDefaults = React.useCallback((size: number) => {
400
- panelDefaultSizeRef.current = size;
401
- }, []);
128
+ }, [store]);
402
129
 
403
- // Determine children presence for left composition
404
- const hasLeftChildren = React.useMemo(() => {
405
- const childArray = React.Children.toArray(children) as React.ReactElement[];
406
- return childArray.some((el) => isShellComponentType(el, Rail) || isShellComponentType(el, Panel));
407
- }, [children]);
408
-
409
- const hasSidebarChildren = React.useMemo(() => {
410
- const childArray = React.Children.toArray(children) as React.ReactElement[];
411
- return childArray.some((el) => isShellComponentType(el, Sidebar));
412
- }, [children]);
413
-
414
- // Re-read the defaults when a pane family enters after mount.
415
- //
416
- // The initial modes are computed once, from the children present at mount.
417
- // That is right until an app swaps families at runtime - a Sidebar giving
418
- // way to Rail+Panel on one route, and back on the next. The entering pane
419
- // then renders against the mode left behind by the family that just went:
420
- // a Rail mounting 'collapsed', at width 0, with its content faded out, put
421
- // right one layout effect later. The reader sees a flicker in place where
422
- // the pane should have been there already.
423
- //
424
- // Adjusting state during render keeps this out of the paint: React re-runs
425
- // Root before the children render, so the entering pane never sees the
426
- // mode of the family it replaced. The ref guard is what makes the update
427
- // terminate - it fires only on the edge, never on a steady render.
428
- const enteredFamilyRef = React.useRef({ left: hasLeftChildren, sidebar: hasSidebarChildren });
429
- if (enteredFamilyRef.current.left !== hasLeftChildren || enteredFamilyRef.current.sidebar !== hasSidebarChildren) {
430
- const leftEntered = hasLeftChildren && !enteredFamilyRef.current.left;
431
- const sidebarEntered = hasSidebarChildren && !enteredFamilyRef.current.sidebar;
432
- enteredFamilyRef.current = { left: hasLeftChildren, sidebar: hasSidebarChildren };
433
-
434
- if (leftEntered || sidebarEntered) {
435
- // The live breakpoint, not the mount default: a responsive
436
- // defaultState like { initial: 'collapsed', md: 'expanded' } must be
437
- // read for the width the reader is on. Taking `initial` would send a
438
- // desktop sidebar in collapsed and let its own start-up effect open it
439
- // again after the paint, which is the blink this whole block exists to
440
- // remove.
441
- const { hasPanelDefaultOpen, ...modes } = readPaneStateFromChildren(children, currentBreakpoint as Breakpoint);
442
- if (leftEntered) {
443
- hasPanelDefaultOpenRef.current = hasPanelDefaultOpen;
444
- // Only when the mode actually differs, so a family that enters
445
- // already in the right mode dispatches nothing.
446
- if (modes.leftMode !== paneState.leftMode) dispatchPane({ type: 'SET_LEFT_MODE', mode: modes.leftMode });
447
- if (modes.panelMode !== paneState.panelMode) dispatchPane({ type: 'SET_PANEL_MODE', mode: modes.panelMode });
448
- }
449
- if (sidebarEntered && modes.sidebarMode !== paneState.sidebarMode) {
450
- dispatchPane({ type: 'SET_SIDEBAR_MODE', mode: modes.sidebarMode });
130
+ const livePanes = React.useCallback(
131
+ (): LivePane[] => [...store.entries.values()].filter((entry) => entry.overlayLive && entry.el).map((entry) => ({ name: entry.name, id: entry.id, el: entry.el as HTMLElement })),
132
+ [store],
133
+ );
134
+ const liveCount = [...store.entries.values()].filter((entry) => entry.overlayLive && entry.el).length;
135
+
136
+ // A Shell given a height of its own sits inside a page, and its overlays
137
+ // cover only its box: it holds no page lock. `full` is the page, and
138
+ // `auto` grows with its content, so its overlays are placed on the window.
139
+ const contained = height !== 'full' && height !== 'auto';
140
+
141
+ /*
142
+ * Containment is the Root's, not the pane's. Only the Root can see every live
143
+ * overlay and every child at once. A per-pane effect, given two overlays,
144
+ * inerts the other live overlay and restores values the other effect wrote,
145
+ * which can leave the whole frame inert for good.
146
+ *
147
+ * Exempt are the scrim and each root child that CONTAINS a live overlay, so
148
+ * a pane wrapped in a plain element is not inerted with its wrapper. A child
149
+ * the Root inerts is marked, and closing clears only marked children, so
150
+ * `inert` the app sets on a child is the app's before, during and after.
151
+ */
152
+ const contain = React.useCallback(() => {
153
+ const rootEl = rootRef.current;
154
+ if (!rootEl) return;
155
+ const liveEls = livePanes().map((pane) => pane.el);
156
+ for (const child of rootEl.children) {
157
+ if (!(child instanceof HTMLElement) || child.classList.contains('rt-ShellScrim')) continue;
158
+ const holdsLive = liveEls.some((el) => child === el || child.contains(el));
159
+ if (liveEls.length === 0 || holdsLive) {
160
+ if (child.hasAttribute(INERT_MARK)) {
161
+ child.removeAttribute(INERT_MARK);
162
+ child.inert = false;
163
+ }
164
+ } else if (!child.inert) {
165
+ child.setAttribute(INERT_MARK, '');
166
+ child.inert = true;
451
167
  }
452
168
  }
453
- }
169
+ }, [livePanes]);
454
170
 
455
- // Keep a ref to sidebar mode so togglePane doesn't depend on it,
456
- // preventing ActionsContext churn on every sidebar mode change
457
- const sidebarModeRef = React.useRef(paneState.sidebarMode);
458
- sidebarModeRef.current = paneState.sidebarMode;
459
-
460
- const togglePane = React.useCallback(
461
- (target: PaneTarget) => {
462
- if (target === 'sidebar') {
463
- const next = sidebarToggleComputerRef.current(sidebarModeRef.current as SidebarMode);
464
- setSidebarMode(next);
465
- return;
466
- }
467
- dispatchPane({ type: 'TOGGLE_PANE', target });
468
- },
469
- [setSidebarMode],
470
- );
171
+ const returnFocusTo = React.useRef<HTMLElement | null>(null);
172
+ const lastLive = React.useRef<LivePane[]>([]);
173
+ const lastFocusInRoot = React.useRef<HTMLElement | null>(null);
174
+ const holdsLock = React.useRef(false);
471
175
 
472
- const expandPane = React.useCallback(
473
- (target: PaneTarget) => {
474
- if (target === 'sidebar') return setSidebarMode('expanded');
475
- dispatchPane({ type: 'EXPAND_PANE', target });
176
+ /*
177
+ * Focus can be taken away after the commit that moved it: a menu that
178
+ * opened or closed a pane restores focus to its own trigger when it
179
+ * finishes closing, which may be inert or hidden by then. For a few frames
180
+ * after an overlay opens or closes, focus that ends up nowhere useful is
181
+ * put back where it belongs.
182
+ */
183
+ const rescueFrame = React.useRef(0);
184
+ const cancelRescue = React.useCallback(() => {
185
+ if (rescueFrame.current) cancelAnimationFrame(rescueFrame.current);
186
+ rescueFrame.current = 0;
187
+ }, []);
188
+ const rescueFocus = React.useCallback(
189
+ (target: HTMLElement, lost: (active: Element | null) => boolean) => {
190
+ cancelRescue();
191
+ let frames = 0;
192
+ const tick = () => {
193
+ rescueFrame.current = 0;
194
+ if (!target.isConnected) return;
195
+ if (lost(target.ownerDocument.activeElement)) {
196
+ target.focus({ preventScroll: true });
197
+ return;
198
+ }
199
+ frames += 1;
200
+ if (frames < RESCUE_FRAMES) rescueFrame.current = requestAnimationFrame(tick);
201
+ };
202
+ rescueFrame.current = requestAnimationFrame(tick);
476
203
  },
477
- [setSidebarMode],
204
+ [cancelRescue],
478
205
  );
479
206
 
480
- const collapsePane = React.useCallback(
481
- (target: PaneTarget) => {
482
- if (target === 'sidebar') return setSidebarMode('collapsed');
483
- dispatchPane({ type: 'COLLAPSE_PANE', target });
207
+ React.useEffect(
208
+ () => () => {
209
+ cancelRescue();
210
+ if (holdsLock.current) {
211
+ holdsLock.current = false;
212
+ updatePageLock(-1);
213
+ }
484
214
  },
485
- [setSidebarMode],
486
- );
487
-
488
- const baseContextValue = React.useMemo(
489
- () => ({
490
- leftMode: paneState.leftMode,
491
- setLeftMode,
492
- panelMode: paneState.panelMode,
493
- setPanelMode,
494
- sidebarMode: paneState.sidebarMode,
495
- setSidebarMode,
496
- inspectorMode: paneState.inspectorMode,
497
- setInspectorMode,
498
- bottomMode: paneState.bottomMode,
499
- setBottomMode,
500
- hasLeft,
501
- setHasLeft,
502
- hasSidebar,
503
- setHasSidebar,
504
- currentBreakpoint,
505
- currentBreakpointReady,
506
- leftResolvedPresentation: devLeftPres,
507
- togglePane,
508
- expandPane,
509
- collapsePane,
510
- setSidebarToggleComputer,
511
- onLeftPres,
512
- onRailDefaults,
513
- onPanelDefaults,
514
- }),
515
- [
516
- paneState.leftMode,
517
- setLeftMode,
518
- paneState.panelMode,
519
- setPanelMode,
520
- paneState.sidebarMode,
521
- setSidebarMode,
522
- paneState.inspectorMode,
523
- setInspectorMode,
524
- paneState.bottomMode,
525
- setBottomMode,
526
- hasLeft,
527
- hasSidebar,
528
- currentBreakpoint,
529
- currentBreakpointReady,
530
- devLeftPres,
531
- togglePane,
532
- expandPane,
533
- collapsePane,
534
- setSidebarToggleComputer,
535
- onLeftPres,
536
- onRailDefaults,
537
- onPanelDefaults,
538
- ],
215
+ [cancelRescue],
539
216
  );
540
217
 
541
- // Organize children by type — single pass instead of 7 filter calls
542
- const { headerEls, railEls, panelEls, sidebarEls, contentEls, inspectorEls, bottomEls } = React.useMemo(() => {
543
- const result = {
544
- headerEls: [] as React.ReactElement[],
545
- railEls: [] as React.ReactElement[],
546
- panelEls: [] as React.ReactElement[],
547
- sidebarEls: [] as React.ReactElement[],
548
- contentEls: [] as React.ReactElement[],
549
- inspectorEls: [] as React.ReactElement[],
550
- bottomEls: [] as React.ReactElement[],
551
- };
552
- for (const el of React.Children.toArray(children) as React.ReactElement[]) {
553
- if (isShellComponentType(el, Header)) result.headerEls.push(el);
554
- else if (isShellComponentType(el, Rail)) result.railEls.push(el);
555
- else if (isShellComponentType(el, Panel)) result.panelEls.push(el);
556
- else if (isShellComponentType(el, Sidebar)) result.sidebarEls.push(el);
557
- else if (isShellComponentType(el, Content)) result.contentEls.push(el);
558
- else if (isShellComponentType(el, Inspector)) result.inspectorEls.push(el);
559
- else if (isShellComponentType(el, Bottom)) result.bottomEls.push(el);
560
- }
561
- return result;
562
- }, [children]);
563
-
564
- // Controlled sync in Root: mirror first Rail/Panel open if provided
565
- const firstRailOpen = (railEls[0] as any)?.props?.open;
566
- const resolvedFirstRailOpen = React.useMemo(() => {
567
- if (typeof firstRailOpen === 'undefined') return undefined;
568
- if (typeof firstRailOpen === 'boolean') return firstRailOpen;
569
- if (typeof firstRailOpen !== 'object' || firstRailOpen === null) return Boolean(firstRailOpen);
570
-
571
- const responsive = firstRailOpen as Partial<Record<Breakpoint, boolean>>;
572
- if (responsive[currentBreakpoint] !== undefined) return responsive[currentBreakpoint];
573
-
574
- const fallbackOrder: Breakpoint[] = ['xl', 'lg', 'md', 'sm', 'xs', 'initial'];
575
- const startIdx = fallbackOrder.indexOf(currentBreakpoint);
576
- for (let i = startIdx + 1; i < fallbackOrder.length; i++) {
577
- const bp = fallbackOrder[i];
578
- if (responsive[bp] !== undefined) return responsive[bp];
579
- }
580
- return undefined;
581
- }, [firstRailOpen, currentBreakpoint]);
582
-
583
- const firstPanelOpen = (panelEls[0] as any)?.props?.open;
584
- const resolvedFirstPanelOpen = React.useMemo(() => {
585
- if (typeof firstPanelOpen === 'undefined') return undefined;
586
- if (typeof firstPanelOpen === 'boolean') return firstPanelOpen;
587
- if (typeof firstPanelOpen !== 'object' || firstPanelOpen === null) return Boolean(firstPanelOpen);
588
-
589
- const responsive = firstPanelOpen as Partial<Record<Breakpoint, boolean>>;
590
- if (responsive[currentBreakpoint] !== undefined) return responsive[currentBreakpoint];
591
-
592
- const fallbackOrder: Breakpoint[] = ['xl', 'lg', 'md', 'sm', 'xs', 'initial'];
593
- const startIdx = fallbackOrder.indexOf(currentBreakpoint);
594
- for (let i = startIdx + 1; i < fallbackOrder.length; i++) {
595
- const bp = fallbackOrder[i];
596
- if (responsive[bp] !== undefined) return responsive[bp];
597
- }
598
- return undefined;
599
- }, [firstPanelOpen, currentBreakpoint]);
600
-
601
- const controlSeqRef = React.useRef(0);
602
- const lastRailChangeRef = React.useRef(0);
603
- const lastPanelChangeRef = React.useRef(0);
604
- const lastRailOpenRef = React.useRef<boolean | undefined>(resolvedFirstRailOpen);
605
- const lastPanelOpenRef = React.useRef<boolean | undefined>(resolvedFirstPanelOpen);
606
-
607
- React.useLayoutEffect(() => {
608
- if (resolvedFirstRailOpen === undefined) {
609
- lastRailOpenRef.current = undefined;
610
- return;
611
- }
612
- if (lastRailOpenRef.current === resolvedFirstRailOpen) return;
613
- lastRailOpenRef.current = resolvedFirstRailOpen;
614
- lastRailChangeRef.current = ++controlSeqRef.current;
615
- }, [resolvedFirstRailOpen]);
616
-
617
- React.useLayoutEffect(() => {
618
- if (resolvedFirstPanelOpen === undefined) {
619
- lastPanelOpenRef.current = undefined;
620
- return;
621
- }
622
- if (lastPanelOpenRef.current === resolvedFirstPanelOpen) return;
623
- lastPanelOpenRef.current = resolvedFirstPanelOpen;
624
- lastPanelChangeRef.current = ++controlSeqRef.current;
625
- }, [resolvedFirstPanelOpen]);
626
-
627
- React.useLayoutEffect(() => {
628
- if (typeof resolvedFirstRailOpen === 'undefined') return;
629
- setLeftMode(resolvedFirstRailOpen ? 'expanded' : 'collapsed');
630
- }, [resolvedFirstRailOpen, setLeftMode]);
631
-
632
- const railOnOpenChange = (railEls[0] as any)?.props?.onOpenChange as
633
- | ((open: boolean, meta: { reason: 'init' | 'toggle' | 'responsive' | 'panel' }) => void)
634
- | undefined;
635
- const panelOnOpenChange = (panelEls[0] as any)?.props?.onOpenChange as
636
- | ((open: boolean, meta: { reason: 'toggle' | 'left' | 'init' | 'responsive' }) => void)
637
- | undefined;
638
- const lastConflictRef = React.useRef<{ railSeq: number; panelSeq: number; action: 'open-rail' | 'close-panel' } | null>(null);
639
-
640
- React.useLayoutEffect(() => {
641
- if (resolvedFirstRailOpen !== false || resolvedFirstPanelOpen !== true) {
642
- lastConflictRef.current = null;
218
+ // No dependency array, on purpose: a pane opening or closing is a render
219
+ // of this component, and so is a child appearing through the Root.
220
+ React.useEffect(() => {
221
+ const rootEl = rootRef.current;
222
+ if (!rootEl) return;
223
+ const doc = rootEl.ownerDocument;
224
+ const live = livePanes();
225
+ const liveEls = live.map((pane) => pane.el);
226
+
227
+ const wantsLock = !contained && live.length > 0;
228
+ if (wantsLock !== holdsLock.current) {
229
+ holdsLock.current = wantsLock;
230
+ updatePageLock(wantsLock ? 1 : -1);
231
+ }
232
+
233
+ const previous = lastLive.current;
234
+ lastLive.current = live;
235
+ // A pane that left the live set because it closed, as opposed to one
236
+ // that is still open but stopped being an overlay at a breakpoint.
237
+ const closed = previous.filter((pane) => {
238
+ if (liveEls.includes(pane.el)) return false;
239
+ const entry = store.entries.get(pane.name);
240
+ return !pane.el.isConnected || !entry || entry.el !== pane.el || entry.value === 'closed';
241
+ });
242
+ const inClosed = (active: Element | null) => active !== null && closed.some((pane) => pane.el.contains(active));
243
+
244
+ // The return target is taken on the opening edge, before inerting: inerting
245
+ // the subtree that holds the trigger blurs it. Focus already inside the
246
+ // overlay (a pane that became one at a breakpoint) is no place to return
247
+ // to, and an opener in a portal (a menu item) goes away with its menu, so
248
+ // the last place focus held inside the frame stands in for it.
249
+ if (previous.length === 0 && live.length > 0) {
250
+ const active = doc.activeElement;
251
+ let target = active instanceof HTMLElement && !isNowhere(doc, active) && !liveEls.some((el) => el.contains(active)) ? active : null;
252
+ if (target && !rootEl.contains(target)) {
253
+ const inRoot = lastFocusInRoot.current;
254
+ if (inRoot && inRoot.isConnected && !liveEls.some((el) => el.contains(inRoot))) target = inRoot;
255
+ }
256
+ returnFocusTo.current = target;
257
+ }
258
+
259
+ contain();
260
+
261
+ if (live.length === 0) {
262
+ const before = returnFocusTo.current;
263
+ returnFocusTo.current = null;
264
+ // Every overlay that left only stopped being one: focus stays where it is.
265
+ if (closed.length === 0) return;
266
+ const usable = (el: HTMLElement | null) => el !== null && el.isConnected && !el.closest('[inert]') && !inClosed(el);
267
+ let target = usable(before) ? before : null;
268
+ for (const pane of closed) target ??= triggerFor(doc, pane.id);
269
+ if (!target) return;
270
+ const lost = (active: Element | null) => isNowhere(doc, active) || inClosed(active);
271
+ if (lost(doc.activeElement)) target.focus({ preventScroll: true });
272
+ else rescueFocus(target, lost);
643
273
  return;
644
274
  }
645
275
 
646
- const panelWins = lastPanelChangeRef.current > lastRailChangeRef.current;
647
- const action: 'open-rail' | 'close-panel' = panelWins ? 'open-rail' : 'close-panel';
648
- const lastConflict = lastConflictRef.current;
649
- if (lastConflict && lastConflict.railSeq === lastRailChangeRef.current && lastConflict.panelSeq === lastPanelChangeRef.current && lastConflict.action === action) {
650
- return;
276
+ // Some overlays closed while others stay: focus left in a closed one goes
277
+ // to the Trigger that opened it, if a live pane holds it, or to the pane
278
+ // on top.
279
+ if (closed.length > 0) {
280
+ const active = doc.activeElement;
281
+ if (isNowhere(doc, active) || inClosed(active)) {
282
+ let target: HTMLElement | null = null;
283
+ for (const pane of closed) target ??= triggerFor(doc, pane.id, liveEls);
284
+ (target ?? liveEls[liveEls.length - 1]).focus({ preventScroll: true });
285
+ }
651
286
  }
652
- lastConflictRef.current = { railSeq: lastRailChangeRef.current, panelSeq: lastPanelChangeRef.current, action };
653
287
 
654
- if (panelWins) {
655
- railOnOpenChange?.(true, { reason: 'panel' });
656
- } else {
657
- panelOnOpenChange?.(false, { reason: 'left' });
288
+ // Focus moves in on the opening edge and nowhere else, and only when it
289
+ // is not already somewhere the user put it inside the live set.
290
+ const opened = liveEls.filter((el) => !previous.some((pane) => pane.el === el));
291
+ const active = doc.activeElement;
292
+ if (opened.length > 0 && !liveEls.some((el) => el.contains(active))) {
293
+ opened[0].focus({ preventScroll: true });
294
+ rescueFocus(opened[0], (now) => isNowhere(doc, now) || (now instanceof Element && now.closest('[inert]') !== null));
658
295
  }
659
- }, [resolvedFirstRailOpen, resolvedFirstPanelOpen, railOnOpenChange, panelOnOpenChange]);
660
-
661
- const leftControlledOpen = resolvedFirstRailOpen;
662
-
663
- const heightStyle = React.useMemo(() => {
664
- if (height === 'full') return { height: '100vh' };
665
- if (height === 'auto') return { height: 'auto' };
666
- if (typeof height === 'string') return { height };
667
- if (typeof height === 'number') return { height: `${height}px` };
668
- return {};
669
- }, [height]);
670
-
671
- // Peek state (layout-only overlay without mode changes)
672
- const [peekTarget, setPeekTarget] = React.useState<PaneTarget | null>(null);
673
- const peekPane = React.useCallback((target: PaneTarget) => setPeekTarget(target), []);
674
- const clearPeek = React.useCallback(() => setPeekTarget(null), []);
675
-
676
- // Memoized slice context values to avoid notifying unrelated consumers
677
- const presentationCtxValue = React.useMemo(() => ({ currentBreakpoint, currentBreakpointReady, leftResolvedPresentation: devLeftPres }), [currentBreakpoint, currentBreakpointReady, devLeftPres]);
678
- const leftModeCtxValue = React.useMemo(() => ({ leftMode: paneState.leftMode, setLeftMode }), [paneState.leftMode, setLeftMode]);
679
- const panelModeCtxValue = React.useMemo(() => ({ panelMode: paneState.panelMode, setPanelMode }), [paneState.panelMode, setPanelMode]);
680
- const sidebarModeCtxValue = React.useMemo(() => ({ sidebarMode: paneState.sidebarMode, setSidebarMode }), [paneState.sidebarMode, setSidebarMode]);
681
- const inspectorModeCtxValue = React.useMemo(() => ({ inspectorMode: paneState.inspectorMode, setInspectorMode }), [paneState.inspectorMode, setInspectorMode]);
682
- const bottomModeCtxValue = React.useMemo(() => ({ bottomMode: paneState.bottomMode, setBottomMode }), [paneState.bottomMode, setBottomMode]);
683
- const compositionCtxValue = React.useMemo(() => ({ hasLeft, setHasLeft, hasSidebar, setHasSidebar }), [hasLeft, setHasLeft, hasSidebar, setHasSidebar]);
684
-
685
- // Inset state management
686
- const [insetPanes, setInsetPanes] = React.useState<Set<InsetPaneId>>(new Set());
687
- const registerInset = React.useCallback((id: InsetPaneId) => {
688
- setInsetPanes((prev) => {
689
- if (prev.has(id)) return prev;
690
- const next = new Set(prev);
691
- next.add(id);
692
- return next;
693
- });
694
- }, []);
695
- const unregisterInset = React.useCallback((id: InsetPaneId) => {
696
- setInsetPanes((prev) => {
697
- if (!prev.has(id)) return prev;
698
- const next = new Set(prev);
699
- next.delete(id);
700
- return next;
701
- });
702
- }, []);
703
- const hasAnyInset = insetPanes.size > 0;
704
- const insetCtxValue = React.useMemo(
705
- () => ({ insetPanes, registerInset, unregisterInset, hasAnyInset }),
706
- [insetPanes, registerInset, unregisterInset, hasAnyInset],
707
- );
708
- const peekCtxValue = React.useMemo(() => ({ peekTarget, setPeekTarget, peekPane, clearPeek }), [peekTarget, setPeekTarget, peekPane, clearPeek]);
709
- const actionsCtxValue = React.useMemo(() => ({ togglePane, expandPane, collapsePane, setSidebarToggleComputer }), [togglePane, expandPane, collapsePane, setSidebarToggleComputer]);
710
-
711
- // Memoized full context value for ShellProvider to prevent unnecessary effect re-runs
712
- const shellContextValue = React.useMemo(
713
- () => ({
714
- ...baseContextValue,
715
- leftControlledOpen,
716
- peekTarget,
717
- setPeekTarget,
718
- peekPane,
719
- clearPeek,
720
- }),
721
- [baseContextValue, leftControlledOpen, peekTarget, setPeekTarget, peekPane, clearPeek],
722
- );
296
+ });
723
297
 
724
- // Memoize the Left content to avoid recreating the IIFE on every render
725
- const leftContent = React.useMemo(() => {
726
- if (!hasLeftChildren || hasSidebarChildren) return null;
727
- const firstRail = railEls[0] as any;
728
- const firstPanel = panelEls[0] as any;
729
- const leftInset = Boolean(firstRail?.props?.inset) || Boolean(firstPanel?.props?.inset);
730
- const passthroughProps = firstRail
731
- ? {
732
- // Notification passthrough used by Left; not spread to DOM in Left
733
- onOpenChange: firstRail.props?.onOpenChange,
734
- open: firstRail.props?.open,
735
- defaultOpen: firstRail.props?.defaultOpen,
736
- presentation: firstRail.props?.presentation,
737
- collapsible: firstRail.props?.collapsible,
738
- onExpand: firstRail.props?.onExpand,
739
- onCollapse: firstRail.props?.onCollapse,
740
- inset: leftInset,
741
- }
742
- : { defaultOpen: hasPanelDefaultOpenRef.current ? true : undefined, inset: leftInset };
743
- return (
744
- <Left {...(passthroughProps as any)}>
745
- {railEls}
746
- {panelEls}
747
- </Left>
748
- );
749
- }, [hasLeftChildren, hasSidebarChildren, railEls, panelEls]);
298
+ // A child that appears through its own state while an overlay is live does
299
+ // not render the Root, so the Root watches its children while one is.
300
+ React.useEffect(() => {
301
+ const rootEl = rootRef.current;
302
+ if (!rootEl || liveCount === 0 || typeof MutationObserver === 'undefined') return;
303
+ const observer = new MutationObserver(contain);
304
+ observer.observe(rootEl, { childList: true, subtree: true, attributes: true, attributeFilter: ['inert'] });
305
+ return () => observer.disconnect();
306
+ }, [liveCount, contain]);
307
+
308
+ /*
309
+ * Escape closes the overlays. It is handled as a React event on the Root, so
310
+ * a component inside a pane that answers Escape in its own onKeyDown runs
311
+ * first, and its preventDefault() or stopPropagation() keeps the pane open.
312
+ * When the Root closes something it stops the event there, so a React
313
+ * Escape handler above the Shell does not act on it too. A layer that
314
+ * listens on the document in the capture phase (Radix dialogs, menus and
315
+ * popovers) answers first and calls preventDefault() when it closes, so an
316
+ * enclosing Kookie Dialog closes before a Shell inside it is asked.
317
+ */
318
+ const handleKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {
319
+ onKeyDown?.(event);
320
+ if (event.key !== 'Escape' || event.defaultPrevented || liveCount === 0) return;
321
+ closeOverlays();
322
+ event.stopPropagation();
323
+ };
324
+
325
+ // With focus on the document itself (a pane closed under it, or a menu that
326
+ // closed and took focus with it), the Root never sees the key. While an
327
+ // overlay is live the document answers that one case.
328
+ React.useEffect(() => {
329
+ const rootEl = rootRef.current;
330
+ if (!rootEl || liveCount === 0) return;
331
+ const doc = rootEl.ownerDocument;
332
+ const onDocumentKeyDown = (event: KeyboardEvent) => {
333
+ if (event.key !== 'Escape' || event.defaultPrevented || !isNowhere(doc, event.target)) return;
334
+ closeOverlays();
335
+ };
336
+ doc.addEventListener('keydown', onDocumentKeyDown);
337
+ return () => doc.removeEventListener('keydown', onDocumentKeyDown);
338
+ }, [liveCount, closeOverlays]);
339
+
340
+ const handleFocus = (event: React.FocusEvent<HTMLDivElement>) => {
341
+ onFocus?.(event);
342
+ if (event.target instanceof HTMLElement && rootRef.current?.contains(event.target)) lastFocusInRoot.current = event.target;
343
+ };
344
+
345
+ // A floating Panel sits beside the Rail when the Rail is showing, and
346
+ // beside its card when the Rail is inset.
347
+ const rail = store.entries.get('rail');
348
+ const railShown = rail !== undefined && rail.value !== undefined && rail.value !== 'closed';
349
+ const railOffset = railShown ? (insetPanes.has('rail') ? `calc(${rail.size}px + 2 * var(--shell-inset-gap))` : `${rail.size}px`) : undefined;
350
+
351
+ // `full` writes no inline height: the stylesheet states it as 100vh with a
352
+ // 100dvh override where supported, and an inline value would beat both.
353
+ const heightStyle: React.CSSProperties = height === 'full' ? {} : height === 'auto' ? { height: 'auto' } : typeof height === 'number' ? { height: `${height}px` } : { height };
750
354
 
751
355
  return (
752
- <div {...props} ref={ref} className={classNames('rt-ShellRoot', className)} style={{ ...heightStyle, ...props.style }}>
753
- <ShellProvider value={shellContextValue}>
754
- <PresentationContext.Provider value={presentationCtxValue}>
755
- <LeftModeContext.Provider value={leftModeCtxValue}>
756
- <PanelModeContext.Provider value={panelModeCtxValue}>
757
- <SidebarModeContext.Provider value={sidebarModeCtxValue}>
758
- <InspectorModeContext.Provider value={inspectorModeCtxValue}>
759
- <BottomModeContext.Provider value={bottomModeCtxValue}>
760
- <CompositionContext.Provider value={compositionCtxValue}>
761
- <PeekContext.Provider value={peekCtxValue}>
762
- <ActionsContext.Provider value={actionsCtxValue}>
763
- <InsetContext.Provider value={insetCtxValue}>
764
- {headerEls}
765
- <div
766
- className="rt-ShellBody"
767
- data-peek-target={peekTarget ?? undefined}
768
- data-has-inset={hasAnyInset || undefined}
769
- style={
770
- peekTarget === 'rail' || peekTarget === 'panel'
771
- ? ({
772
- '--peek-rail-width': `${railDefaultSizeRef.current}px`,
773
- } as CSSPropertiesWithVars)
774
- : undefined
775
- }
776
- >
777
- {leftContent ?? sidebarEls}
778
- {contentEls}
779
- {inspectorEls}
780
- </div>
781
- {bottomEls}
782
- </InsetContext.Provider>
783
- </ActionsContext.Provider>
784
- </PeekContext.Provider>
785
- </CompositionContext.Provider>
786
- </BottomModeContext.Provider>
787
- </InspectorModeContext.Provider>
788
- </SidebarModeContext.Provider>
789
- </PanelModeContext.Provider>
790
- </LeftModeContext.Provider>
791
- </PresentationContext.Provider>
792
- </ShellProvider>
793
- </div>
356
+ <ShellStoreContext.Provider value={store}>
357
+ <ShellInsetContext.Provider value={insetContext}>
358
+ {/* The Root is not a widget: it hears Escape bubbling up from the panes,
359
+ after their own handlers, to close the overlays. */}
360
+ {/* eslint-disable-next-line jsx-a11y/no-static-element-interactions */}
361
+ <div
362
+ {...props}
363
+ ref={composedRef}
364
+ className={classNames('rt-ShellRoot', className)}
365
+ data-height={height === 'auto' ? 'auto' : undefined}
366
+ data-has-inset={insetPanes.size > 0 || undefined}
367
+ data-overlay-live={liveCount > 0 || undefined}
368
+ onKeyDown={handleKeyDown}
369
+ onFocus={handleFocus}
370
+ style={{ ...heightStyle, ...(railOffset ? ({ '--shell-rail-offset': railOffset } as CSSPropertiesWithVars) : {}), ...style }}
371
+ >
372
+ {children}
373
+ {/* Root-owned and always mounted. The stylesheet shows it while an
374
+ overlay is live; containment takes the rest of the frame out of
375
+ the accessibility tree, so the scrim itself is hidden from it. */}
376
+ <div className="rt-ShellScrim" aria-hidden onClick={closeOverlays} />
377
+ </div>
378
+ </ShellInsetContext.Provider>
379
+ </ShellStoreContext.Provider>
794
380
  );
795
- }) as PanelComponent;
381
+ });
796
382
  Root.displayName = 'Shell.Root';
797
383
 
798
- // Header
384
+ /* ── Header ────────────────────────────────────────────────────────────────── */
385
+
799
386
  interface ShellHeaderProps extends React.ComponentPropsWithoutRef<'header'> {
800
387
  height?: number;
801
388
  }
@@ -805,334 +392,105 @@ const Header = React.forwardRef<HTMLElement, ShellHeaderProps>(({ className, hei
805
392
  {...props}
806
393
  ref={ref}
807
394
  className={classNames('rt-ShellHeader', className)}
808
- style={{
809
- ...style,
810
- '--shell-header-height': `${height}px`,
811
- } as CSSPropertiesWithVars}
395
+ style={
396
+ {
397
+ ...style,
398
+ '--shell-header-height': `${height}px`,
399
+ } as CSSPropertiesWithVars
400
+ }
812
401
  />
813
402
  ));
814
403
  Header.displayName = 'Shell.Header';
815
404
 
816
- // Pane Props Interface (shared by Panel, Sidebar, Inspector, Bottom)
817
- type PaneProps = PaneBaseProps;
405
+ /* ── Left (deprecated) ─────────────────────────────────────────────────────── */
818
406
 
819
- // Left container (auto-created for Rail+Panel)
820
407
  interface LeftProps extends React.ComponentPropsWithoutRef<'div'> {
821
408
  presentation?: ResponsivePresentation;
822
- // New: passthrough from Rail
823
409
  open?: boolean;
824
410
  defaultOpen?: boolean;
825
- onOpenChange?: (open: boolean, meta: { reason: 'init' | 'toggle' | 'panel' | 'responsive' }) => void;
411
+ onOpenChange?: (open: boolean, meta: { reason: 'init' | 'toggle' | 'panel' | 'responsive' | 'dismiss' }) => void;
826
412
  collapsible?: boolean;
827
413
  onExpand?: () => void;
828
414
  onCollapse?: () => void;
829
- mode?: never;
830
- defaultMode?: never;
831
- onModeChange?: never;
832
- /** When true, adds margin and triggers gray backdrop on Shell. */
833
415
  inset?: boolean;
834
416
  }
835
417
 
836
- // Rail (special case)
837
- type LeftOpenChangeMeta = { reason: 'init' | 'toggle' | 'responsive' | 'panel' };
418
+ /**
419
+ * @deprecated The Root no longer wraps the Rail and Panel in a Left
420
+ * container: each is its own pane. `Shell.Left` renders its children and
421
+ * ignores its own props. Removed in 1.0.
422
+ */
423
+ const Left = React.forwardRef<HTMLDivElement, LeftProps>(({ children }, _ref) => {
424
+ React.useEffect(() => {
425
+ warnOnce('Shell.Left is deprecated and is removed in 1.0. Render Shell.Rail and Shell.Panel directly in Shell.Root.');
426
+ }, []);
427
+ return <>{children}</>;
428
+ });
429
+ Left.displayName = 'Shell.Left';
430
+
431
+ /* ── Rail ──────────────────────────────────────────────────────────────────── */
838
432
 
839
- type RailControlledProps = { open: boolean | Partial<Record<Breakpoint, boolean>>; onOpenChange?: (open: boolean, meta: LeftOpenChangeMeta) => void; defaultOpen?: never };
840
- type RailUncontrolledProps = { defaultOpen?: boolean | Partial<Record<Breakpoint, boolean>>; onOpenChange?: (open: boolean, meta: LeftOpenChangeMeta) => void; open?: never };
433
+ type RailOpenChangeMeta = { reason: 'init' | 'toggle' | 'responsive' | 'panel' | 'dismiss' };
434
+
435
+ type RailControlledProps = { open: boolean | Partial<Record<Breakpoint, boolean>>; onOpenChange?: (open: boolean, meta: RailOpenChangeMeta) => void; defaultOpen?: never };
436
+ type RailUncontrolledProps = { defaultOpen?: boolean | Partial<Record<Breakpoint, boolean>>; onOpenChange?: (open: boolean, meta: RailOpenChangeMeta) => void; open?: never };
841
437
 
842
438
  type RailProps = React.ComponentPropsWithoutRef<'div'> & {
843
439
  presentation?: ResponsivePresentation;
844
440
  expandedSize?: number;
845
441
  collapsible?: boolean;
442
+ /** @deprecated Use `onOpenChange`. */
846
443
  onExpand?: () => void;
444
+ /** @deprecated Use `onOpenChange`. */
847
445
  onCollapse?: () => void;
848
- /** When true, adds margin to Rail+Panel and triggers gray backdrop on Shell. */
446
+ /** When true, adds margin and triggers the gray backdrop on the Shell. */
849
447
  inset?: boolean;
850
448
  } & (RailControlledProps | RailUncontrolledProps);
851
449
 
852
- // Left container - behaves like Inspector but contains Rail+Panel
853
- const LEFT_DOM_OMIT_PROPS = ['open', 'defaultOpen', 'onOpenChange', 'mode', 'defaultMode', 'onModeChange'] as const;
854
-
855
- const Left = React.forwardRef<HTMLDivElement, LeftProps>((initialProps, ref) => {
856
- const { className, presentation = { initial: 'fixed', sm: 'fixed' }, collapsible: _collapsible = true, onExpand, onCollapse, children, style, inset, ...restProps } = initialProps;
857
- const { registerInset, unregisterInset } = useInset();
858
-
859
- // Register/unregister inset
860
- React.useEffect(() => {
861
- if (inset) {
862
- registerInset('left');
863
- return () => unregisterInset('left');
864
- }
865
- }, [inset, registerInset, unregisterInset]);
866
- const propsOpen = restProps.open;
867
- const propsDefaultOpen = restProps.defaultOpen;
868
- const propsOnOpenChange = restProps.onOpenChange;
869
- const domProps = omitPaneProps(restProps, LEFT_DOM_OMIT_PROPS);
870
- const shell = useShell();
871
- const { setHasLeft } = shell;
872
- const resolvedPresentation = useResponsivePresentation(presentation);
873
- const isOverlay = resolvedPresentation === 'overlay';
874
- const isStacked = resolvedPresentation === 'stacked';
875
- const localRef = React.useRef<HTMLDivElement | null>(null);
876
- // Publish resolved presentation so Root can gate peeking in overlay
877
- React.useEffect(() => {
878
- shell.onLeftPres?.(resolvedPresentation);
879
- }, [shell, resolvedPresentation]);
880
- const setRef = React.useCallback(
881
- (node: HTMLDivElement | null) => {
882
- localRef.current = node;
883
- if (typeof ref === 'function') ref(node);
884
- else if (ref) (ref as React.MutableRefObject<HTMLDivElement | null>).current = node;
885
- },
886
- [ref],
887
- );
888
-
889
- // Register with shell
890
- React.useEffect(() => {
891
- setHasLeft(true);
892
- return () => setHasLeft(false);
893
- }, [setHasLeft]);
894
-
895
- const lastLeftModeRef = React.useRef<PaneMode | null>(null);
896
- const lastResolvedLeftControlledRef = React.useRef<PaneMode | undefined>(undefined);
897
- const normalizedLeftControlled = React.useMemo(() => {
898
- if (typeof propsOpen === 'undefined') return undefined;
899
- return propsOpen ? 'expanded' : 'collapsed';
900
- }, [propsOpen]);
901
- const normalizedLeftDefault = React.useMemo(() => mapResponsiveBooleanToPaneMode(propsDefaultOpen), [propsDefaultOpen]);
902
-
903
- // Stable refs for notification callbacks to avoid effect dep churn
904
- const propsOnOpenChangeRef = React.useRef(propsOnOpenChange);
905
- const propsOpenRef = React.useRef(propsOpen);
906
- React.useLayoutEffect(() => {
907
- propsOnOpenChangeRef.current = propsOnOpenChange;
908
- propsOpenRef.current = propsOpen;
909
- });
910
-
911
- const { resolvedControlled: resolvedLeftControlled } = useResponsiveInitialState<PaneMode>({
912
- controlledValue: normalizedLeftControlled,
913
- defaultValue: normalizedLeftDefault,
914
- currentValue: shell.leftMode,
915
- setValue: shell.setLeftMode,
916
- breakpointReady: shell.currentBreakpointReady,
917
- onInit: (initial) => propsOnOpenChangeRef.current?.(initial === 'expanded', { reason: 'init' }),
918
- });
919
-
920
- // Emit mode changes for user/internal transitions.
921
- // In controlled mode, skip when the mode matches the controlled prop (prop-driven sync).
922
- const prevPanelModeRef = React.useRef<PaneMode | null>(null);
923
- React.useEffect(() => {
924
- const prevLeftMode = lastLeftModeRef.current;
925
- const prevPanelMode = prevPanelModeRef.current;
926
-
927
- const prevResolvedControlled = lastResolvedLeftControlledRef.current;
928
- const controlledChanged = prevResolvedControlled !== resolvedLeftControlled;
929
-
930
- if (prevLeftMode !== null && prevLeftMode !== shell.leftMode) {
931
- const isControlled = typeof propsOpenRef.current !== 'undefined';
932
- const controlledTarget = resolvedLeftControlled === undefined ? undefined : resolvedLeftControlled === 'expanded';
933
- const nextOpen = shell.leftMode === 'expanded';
934
-
935
- // In controlled mode, only notify when internal mode diverges from the
936
- // controlled prop — that means a trigger/cascade changed it, not a prop sync.
937
- if (!isControlled || (!controlledChanged && nextOpen !== controlledTarget)) {
938
- let reason: LeftOpenChangeMeta['reason'] = 'toggle';
939
- const panelDrivenOpen = prevPanelMode !== null && prevPanelMode !== shell.panelMode && prevLeftMode === 'collapsed' && shell.leftMode === 'expanded' && shell.panelMode === 'expanded';
940
- if (panelDrivenOpen) {
941
- reason = 'panel';
942
- }
943
- propsOnOpenChangeRef.current?.(nextOpen, { reason });
944
- }
945
- }
946
-
947
- lastLeftModeRef.current = shell.leftMode;
948
- prevPanelModeRef.current = shell.panelMode;
949
- lastResolvedLeftControlledRef.current = resolvedLeftControlled;
950
- }, [shell.leftMode, shell.panelMode, resolvedLeftControlled]);
951
-
952
- // Emit expand/collapse events.
953
- // Use callback refs to avoid re-running effect when inline callbacks change,
954
- // matching the pattern used by Inspector and Bottom.
955
- const onExpandRef = React.useRef(onExpand);
956
- const onCollapseRef = React.useRef(onCollapse);
957
- React.useLayoutEffect(() => {
958
- onExpandRef.current = onExpand;
959
- onCollapseRef.current = onCollapse;
450
+ const RAIL_PROP_NAMES = { controlled: 'open', default: 'defaultOpen' };
451
+
452
+ const Rail = React.forwardRef<HTMLDivElement, RailProps>((props, ref) => {
453
+ const { className, presentation, expandedSize = 64, collapsible: _collapsible, onExpand, onCollapse, children, style, open, defaultOpen, onOpenChange, inset, id, ...domProps } = props;
454
+ const { table, attributes } = usePresentationTable(presentation, 'fixed');
455
+ const pane = usePane({
456
+ name: 'rail',
457
+ label: 'Rail',
458
+ propNames: RAIL_PROP_NAMES,
459
+ id,
460
+ controlled: toPaneValue(open),
461
+ defaultValue: toPaneValue(defaultOpen),
462
+ presentationTable: table,
463
+ builtIn: navigationRest,
464
+ onChange: (value, reason) => onOpenChange?.(value !== 'closed', { reason }),
465
+ onExpand,
466
+ onCollapse,
467
+ size: expandedSize,
960
468
  });
469
+ useInsetRegistration('rail', inset);
470
+ const composedRef = useComposedRefs(ref, pane.setElement);
961
471
 
962
- const prevLeftModeForCallbackRef = React.useRef<PaneMode | null>(null);
963
- const hasLeftInitializedRef = React.useRef(false);
964
- React.useEffect(() => {
965
- const currentMode = shell.leftMode;
966
-
967
- if (!shell.currentBreakpointReady) {
968
- prevLeftModeForCallbackRef.current = currentMode;
969
- return;
970
- }
971
-
972
- if (!hasLeftInitializedRef.current) {
973
- hasLeftInitializedRef.current = true;
974
- prevLeftModeForCallbackRef.current = currentMode;
975
- return;
976
- }
977
-
978
- const prevMode = prevLeftModeForCallbackRef.current;
979
-
980
- if (prevMode !== null && prevMode !== currentMode) {
981
- if (currentMode === 'expanded') {
982
- onExpandRef.current?.();
983
- } else if (currentMode === 'collapsed') {
984
- onCollapseRef.current?.();
985
- }
986
- prevLeftModeForCallbackRef.current = currentMode;
987
- }
988
- }, [shell.leftMode, shell.currentBreakpointReady]);
989
-
990
- const _isExpanded = shell.leftMode === 'expanded';
991
-
992
- // Left is not resizable; width derives from Rail/Panel.
993
-
994
- if (isOverlay) {
995
- const open = shell.leftMode === 'expanded';
996
- // Compute overlay width from child Rail/Panel expanded sizes
997
- const childArray = React.Children.toArray(children) as React.ReactElement[];
998
- const railEl = childArray.find((el) => isShellComponentType(el, Rail));
999
- const panelEl = childArray.find((el) => isShellComponentType(el, Panel));
1000
- const railSize = typeof (railEl as any)?.props?.expandedSize === 'number' ? (railEl as any).props.expandedSize : 64;
1001
- const panelSize = typeof (panelEl as any)?.props?.expandedSize === 'number' ? (panelEl as any).props.expandedSize : 288;
1002
- const hasRail = Boolean(railEl);
1003
- const hasPanel = Boolean(panelEl);
1004
- const overlayPx = (hasRail ? railSize : 0) + (shell.panelMode === 'expanded' && hasPanel ? panelSize : 0);
1005
- return (
1006
- <Sheet.Root open={open} onOpenChange={(o) => shell.setLeftMode(o ? 'expanded' : 'collapsed')}>
1007
- <Sheet.Content
1008
- side="start"
1009
- style={{ padding: 0 }}
1010
- aria-label="Navigation"
1011
- aria-describedby={undefined}
1012
- width={{
1013
- initial: `${overlayPx}px`,
1014
- }}
1015
- >
1016
- <VisuallyHidden>
1017
- <Sheet.Title>Navigation</Sheet.Title>
1018
- </VisuallyHidden>
1019
- <div className="rt-ShellLeft">{children}</div>
1020
- </Sheet.Content>
1021
- </Sheet.Root>
1022
- );
1023
- }
1024
-
1025
- if (isStacked) {
1026
- const open = shell.leftMode === 'expanded';
1027
- // Compute floating width from child Rail/Panel expanded sizes (like overlay)
1028
- const childArray = React.Children.toArray(children) as React.ReactElement[];
1029
- const railEl = childArray.find((el) => isShellComponentType(el, Rail));
1030
- const panelEl = childArray.find((el) => isShellComponentType(el, Panel));
1031
- const _railSize = typeof (railEl as any)?.props?.expandedSize === 'number' ? (railEl as any).props.expandedSize : 64;
1032
- const _panelSize = typeof (panelEl as any)?.props?.expandedSize === 'number' ? (panelEl as any).props.expandedSize : 288;
1033
- const _hasRail = Boolean(railEl);
1034
- const _hasPanel = Boolean(panelEl);
1035
- const _includePanel = _hasPanel && (shell.panelMode === 'expanded' || shell.peekTarget === 'panel');
1036
-
1037
- // Strip control props from DOM spread
1038
- return (
1039
- <div
1040
- {...domProps}
1041
- ref={setRef}
1042
- className={classNames('rt-ShellLeft', className)}
1043
- data-mode={shell.leftMode}
1044
- data-peek={shell.peekTarget === 'left' || shell.peekTarget === 'rail' || shell.peekTarget === 'panel' || undefined}
1045
- data-presentation={resolvedPresentation}
1046
- data-inset={inset || undefined}
1047
- style={{
1048
- ...style,
1049
- }}
1050
- data-open={open || undefined}
1051
- >
1052
- {children}
1053
- </div>
1054
- );
1055
- }
1056
-
1057
- // Strip control/legacy props from DOM spread
1058
472
  return (
1059
473
  <div
1060
474
  {...domProps}
1061
- ref={setRef}
1062
- className={classNames('rt-ShellLeft', className)}
1063
- data-mode={shell.leftMode}
1064
- data-peek={shell.peekTarget === 'left' || shell.peekTarget === 'rail' || shell.peekTarget === 'panel' || undefined}
1065
- data-presentation={resolvedPresentation}
475
+ id={pane.id}
476
+ ref={composedRef}
477
+ className={classNames('rt-ShellPane', 'rt-ShellRail', className)}
478
+ {...paneAttributes(pane, attributes)}
1066
479
  data-inset={inset || undefined}
1067
- style={{
1068
- ...style,
1069
- }}
480
+ tabIndex={pane.overlaying ? -1 : domProps.tabIndex}
481
+ style={{ ...style, '--rail-size': `${expandedSize}px` } as CSSPropertiesWithVars}
1070
482
  >
1071
- {children}
1072
- </div>
1073
- );
1074
- });
1075
- Left.displayName = 'Shell.Left';
1076
- assignShellSlot(Left as any, 'Shell.Left');
1077
-
1078
- const Rail = React.forwardRef<HTMLDivElement, RailProps>((initialProps, ref) => {
1079
- const { className, presentation, expandedSize = 64, collapsible, onExpand, onCollapse, children, style, open, defaultOpen, onOpenChange, inset: _inset, ...domProps } = initialProps;
1080
- const shell = useShell();
1081
-
1082
- // Dev guards
1083
- const wasControlledRef = React.useRef<boolean | null>(null);
1084
- if (process.env.NODE_ENV !== 'production') {
1085
- if (typeof open !== 'undefined' && typeof defaultOpen !== 'undefined') {
1086
- console.error('Shell.Rail: Do not pass both `open` and `defaultOpen`. Choose one.');
1087
- }
1088
- }
1089
-
1090
- // Warn on controlled/uncontrolled mode switch
1091
- React.useEffect(() => {
1092
- const isControlled = typeof open !== 'undefined';
1093
- if (wasControlledRef.current === null) {
1094
- wasControlledRef.current = isControlled;
1095
- return;
1096
- }
1097
- if (wasControlledRef.current !== isControlled) {
1098
- console.warn('Shell.Rail: Switching between controlled and uncontrolled `open` is not supported.');
1099
- wasControlledRef.current = isControlled;
1100
- }
1101
- }, [open]);
1102
-
1103
- // Register expanded size with Left container
1104
- React.useEffect(() => {
1105
- shell.onRailDefaults?.(expandedSize);
1106
- }, [shell, expandedSize]);
1107
-
1108
- const isExpanded = shell.leftMode === 'expanded';
1109
-
1110
- // Strip unknown open/defaultOpen props from DOM by not spreading them
1111
- return (
1112
- <div
1113
- {...domProps}
1114
- ref={ref}
1115
- className={classNames('rt-ShellRail', className)}
1116
- data-mode={shell.leftMode}
1117
- data-peek={(shell.currentBreakpointReady && shell.leftResolvedPresentation !== 'overlay' && shell.peekTarget === 'rail') || undefined}
1118
- style={{
1119
- ...style,
1120
- '--rail-size': `${expandedSize}px`,
1121
- } as CSSPropertiesWithVars}
1122
- >
1123
- <div className="rt-ShellRailContent" data-visible={(shell.currentBreakpointReady && (isExpanded || (shell.leftResolvedPresentation !== 'overlay' && shell.peekTarget === 'rail'))) || undefined}>
1124
- {children}
1125
- </div>
483
+ <div className="rt-ShellRailContent">{children}</div>
1126
484
  </div>
1127
485
  );
1128
486
  });
1129
487
  Rail.displayName = 'Shell.Rail';
1130
- assignShellSlot(Rail as any, 'Shell.Rail');
1131
488
 
1132
- // Panel
489
+ /* ── Panel ─────────────────────────────────────────────────────────────────── */
490
+
1133
491
  type HandleComponent = React.ForwardRefExoticComponent<React.ComponentPropsWithoutRef<'div'> & React.RefAttributes<HTMLDivElement>>;
1134
492
 
1135
- type PanelOpenChangeMeta = { reason: 'toggle' | 'left' | 'init' | 'responsive' };
493
+ type PanelOpenChangeMeta = { reason: 'toggle' | 'left' | 'init' | 'responsive' | 'dismiss' };
1136
494
  type PanelControlledProps = { open: boolean | Partial<Record<Breakpoint, boolean>>; onOpenChange?: (open: boolean, meta: PanelOpenChangeMeta) => void; defaultOpen?: never };
1137
495
  type PanelUncontrolledProps = { defaultOpen?: boolean | Partial<Record<Breakpoint, boolean>>; onOpenChange?: (open: boolean, meta: PanelOpenChangeMeta) => void; open?: never };
1138
496
 
@@ -1140,520 +498,232 @@ type PanelSizeControlledProps = { size: number | string; defaultSize?: never };
1140
498
  type PanelSizeUncontrolledProps = { defaultSize?: number | string; size?: never };
1141
499
 
1142
500
  type PanelSizeChangeMeta = { reason: 'init' | 'resize' | 'controlled' };
1143
- type PanelPublicProps = Omit<PaneProps, 'presentation' | 'defaultMode'> &
501
+ type PanelPublicProps = PaneBaseProps &
1144
502
  (PanelControlledProps | PanelUncontrolledProps) &
1145
503
  (PanelSizeControlledProps | PanelSizeUncontrolledProps) & {
1146
504
  onSizeChange?: (size: number, meta: PanelSizeChangeMeta) => void;
1147
505
  sizeUpdate?: 'throttle' | 'debounce';
1148
506
  sizeUpdateMs?: number;
1149
- /** When true, adds margin to Rail+Panel and triggers gray backdrop on Shell. */
507
+ /** When true, adds margin and triggers the gray backdrop on the Shell. */
1150
508
  inset?: boolean;
1151
509
  };
1152
510
  type PanelComponent = React.ForwardRefExoticComponent<PanelPublicProps & React.RefAttributes<HTMLDivElement>> & {
1153
511
  Handle: HandleComponent;
1154
512
  };
1155
513
 
1156
- type _SidebarComponent = React.ForwardRefExoticComponent<
1157
- (Omit<PaneProps, 'mode' | 'defaultMode' | 'onModeChange'> & {
1158
- state?: Responsive<SidebarMode>;
1159
- defaultState?: SidebarMode;
1160
- onStateChange?: (mode: SidebarMode) => void;
1161
- thinSize?: number;
1162
- toggleModes?: 'both' | 'single';
1163
- }) &
1164
- React.RefAttributes<HTMLDivElement>
1165
- > & { Handle: HandleComponent };
1166
-
1167
- type _InspectorComponent = React.ForwardRefExoticComponent<PaneProps & React.RefAttributes<HTMLDivElement>> & { Handle: HandleComponent };
1168
-
1169
- type _BottomComponent = React.ForwardRefExoticComponent<PaneProps & React.RefAttributes<HTMLDivElement>> & { Handle: HandleComponent };
1170
-
1171
- const PANEL_DOM_PROP_KEYS = [
1172
- 'className',
1173
- 'children',
1174
- 'defaultOpen',
1175
- 'open',
1176
- 'onOpenChange',
1177
- 'size',
1178
- 'defaultSize',
1179
- 'onSizeChange',
1180
- 'sizeUpdate',
1181
- 'sizeUpdateMs',
1182
- 'style',
1183
- ] as const satisfies readonly (keyof PanelPublicProps)[];
1184
-
1185
- const Panel = assignShellSlot(
1186
- React.forwardRef<HTMLDivElement, PanelPublicProps>((initialProps, ref) => {
1187
- const {
1188
- className,
1189
- defaultOpen,
1190
- open,
1191
- onOpenChange,
1192
- size,
1193
- defaultSize,
1194
- expandedSize = 288,
1195
- minSize,
1196
- maxSize,
1197
- resizable,
1198
- collapsible = true,
1199
- onExpand: _onExpand,
1200
- onCollapse: _onCollapse,
1201
- onResize,
1202
- onResizeStart,
1203
- onResizeEnd,
1204
- snapPoints,
1205
- snapTolerance,
1206
- collapseThreshold,
1207
- paneId,
1208
- persistence,
1209
- children,
1210
- style,
1211
- onSizeChange,
1212
- sizeUpdate,
1213
- sizeUpdateMs = 50,
1214
- } = initialProps;
1215
- const panelDomProps = extractPaneDomProps(initialProps, PANEL_DOM_PROP_KEYS);
1216
- // Ref for debounce cleanup
1217
- const debounceTimeoutRef = React.useRef<ReturnType<typeof setTimeout> | null>(null);
1218
- // Cleanup debounce timeout on unmount or when dependencies change
1219
- React.useLayoutEffect(() => {
1220
- return () => {
1221
- if (debounceTimeoutRef.current) {
1222
- clearTimeout(debounceTimeoutRef.current);
1223
- debounceTimeoutRef.current = null;
1224
- }
1225
- };
1226
- }, [onSizeChange, sizeUpdate, sizeUpdateMs]);
1227
- // Throttled/debounced emitter for onSizeChange
1228
- const emitSizeChange = React.useMemo(() => {
1229
- if (!onSizeChange) return () => {};
1230
- if (sizeUpdate === 'debounce') {
1231
- const fn = (s: number, meta: PanelSizeChangeMeta) => {
1232
- if (debounceTimeoutRef.current) clearTimeout(debounceTimeoutRef.current);
1233
- debounceTimeoutRef.current = setTimeout(() => {
1234
- onSizeChange?.(s, meta);
1235
- debounceTimeoutRef.current = null;
1236
- }, sizeUpdateMs);
1237
- };
1238
- return fn;
1239
- }
1240
- if (sizeUpdate === 'throttle') {
1241
- let last = 0;
1242
- return (s: number, meta: PanelSizeChangeMeta) => {
1243
- const now = Date.now();
1244
- if (now - last >= sizeUpdateMs) {
1245
- last = now;
1246
- onSizeChange?.(s, meta);
1247
- }
1248
- };
1249
- }
1250
- return (s: number, meta: PanelSizeChangeMeta) => onSizeChange?.(s, meta);
1251
- }, [onSizeChange, sizeUpdate, sizeUpdateMs]);
1252
- const shell = useShell();
1253
- const prevPanelModeRef = React.useRef<PaneMode | null>(null);
1254
- const prevLeftModeRef = React.useRef<PaneMode | null>(null);
1255
- const lastResolvedPanelControlledRef = React.useRef<PaneMode | undefined>(undefined);
1256
- // Dev-only runtime guard
1257
- if (process.env.NODE_ENV !== 'production') {
1258
- if (typeof open !== 'undefined' && typeof defaultOpen !== 'undefined') {
1259
- console.error('Shell.Panel: Do not pass both `open` and `defaultOpen`. Choose one.');
1260
- }
1261
- if (typeof size !== 'undefined' && typeof defaultSize !== 'undefined') {
1262
- console.error('Shell.Panel: Do not pass both `size` and `defaultSize`. Choose one.');
1263
- }
1264
- }
514
+ const PANEL_PROP_NAMES = { controlled: 'open', default: 'defaultOpen' };
1265
515
 
1266
- // Normalize responsive open/defaultOpen to PaneMode
1267
- const normalizedControlledOpen = React.useMemo(() => mapResponsiveBooleanToPaneMode(open), [open]);
1268
- const normalizedDefaultOpen = React.useMemo(() => mapResponsiveBooleanToPaneMode(defaultOpen), [defaultOpen]);
1269
- const openIsResponsive = typeof open === 'object' && open !== null;
1270
-
1271
- // Stable ref for onOpenChange to avoid effect dep churn
1272
- const onOpenChangeRef = React.useRef(onOpenChange);
1273
- React.useLayoutEffect(() => {
1274
- onOpenChangeRef.current = onOpenChange;
1275
- });
516
+ /**
517
+ * A Panel with a `presentation` of its own uses it. One without follows the
518
+ * Rail rendered before it, which is how 0.7 placed a Panel; the stylesheet
519
+ * reads the Rail's attributes for the first paint and the registry carries
520
+ * the Rail's table for the JS mirror.
521
+ */
522
+ const Panel = React.forwardRef<HTMLDivElement, PanelPublicProps>((props, ref) => {
523
+ const {
524
+ className,
525
+ presentation,
526
+ defaultOpen,
527
+ open,
528
+ onOpenChange,
529
+ size,
530
+ defaultSize,
531
+ expandedSize = 288,
532
+ minSize = 100,
533
+ maxSize = 800,
534
+ resizable = false,
535
+ collapsible = true,
536
+ onExpand,
537
+ onCollapse,
538
+ onResize,
539
+ onResizeStart,
540
+ onResizeEnd,
541
+ snapPoints,
542
+ snapTolerance,
543
+ collapseThreshold,
544
+ paneId,
545
+ persistence,
546
+ children,
547
+ style,
548
+ onSizeChange,
549
+ sizeUpdate,
550
+ sizeUpdateMs = 50,
551
+ inset,
552
+ id,
553
+ ...domProps
554
+ } = props;
555
+ const store = useShellStore('Shell.Panel');
556
+ const rail = usePaneEntry(store, 'rail');
557
+ const own = usePresentationTable(presentation, 'fixed');
558
+ const followsRail = presentation === undefined;
559
+ const presentationTable = followsRail ? (rail?.presentationTable ?? FIXED_TABLE) : own.table;
560
+ const presentationAttributes = followsRail ? { 'data-presentation-follows': '' } : own.attributes;
561
+
562
+ const pane = usePane({
563
+ name: 'panel',
564
+ label: 'Panel',
565
+ propNames: PANEL_PROP_NAMES,
566
+ id,
567
+ controlled: toPaneValue(open),
568
+ defaultValue: toPaneValue(defaultOpen),
569
+ presentationTable,
570
+ builtIn: detailRest,
571
+ onChange: (value, reason) => onOpenChange?.(value !== 'closed', { reason }),
572
+ onExpand,
573
+ onCollapse,
574
+ size: expandedSize,
575
+ });
576
+ useInsetRegistration('panel', inset);
1276
577
 
1277
- // Use responsive initial state hook for proper breakpoint handling
1278
- const { resolvedControlled: resolvedPanelControlled } = useResponsiveInitialState<PaneMode>({
1279
- controlledValue: normalizedControlledOpen,
1280
- defaultValue: normalizedDefaultOpen,
1281
- currentValue: shell.panelMode,
1282
- setValue: (mode) => {
1283
- // Ensure Left is expanded when Panel is expanded unless Rail is controlled closed
1284
- if (mode === 'expanded' && shell.leftMode !== 'expanded' && shell.leftControlledOpen !== false) {
1285
- shell.setLeftMode('expanded');
1286
- }
1287
- shell.setPanelMode(mode);
1288
- },
1289
- breakpointReady: shell.currentBreakpointReady,
1290
- controlledIsResponsive: openIsResponsive,
1291
- onResponsiveChange: (next) => onOpenChangeRef.current?.(next === 'expanded', { reason: 'responsive' }),
1292
- onInit: (initial) => {
1293
- if (typeof open === 'undefined') {
1294
- onOpenChangeRef.current?.(initial === 'expanded', { reason: 'init' });
1295
- }
1296
- },
1297
- });
578
+ React.useEffect(() => {
579
+ if (snapPoints !== undefined || collapseThreshold !== undefined || paneId !== undefined || persistence !== undefined) {
580
+ warnOnce('Shell.Panel: `snapPoints`, `collapseThreshold`, `paneId` and `persistence` are deprecated and are removed in 1.0. Keep the size in your own state with `size`/`onSizeChange`.');
581
+ }
582
+ }, [snapPoints, collapseThreshold, paneId, persistence]);
583
+
584
+ const elementRef = React.useRef<HTMLElement | null>(null);
585
+ const composedRef = useComposedRefs(ref, pane.setElement, elementRef);
586
+
587
+ const resize = useResizablePane({
588
+ name: 'panel',
589
+ elementId: pane.id,
590
+ elementRef,
591
+ cssVarName: '--panel-size',
592
+ orientation: 'vertical',
593
+ edge: 'end',
594
+ growth: startAnchoredGrowth,
595
+ expandedSize,
596
+ minSize,
597
+ maxSize,
598
+ resizable,
599
+ collapsible,
600
+ size,
601
+ defaultSize,
602
+ onSizeChange,
603
+ sizeUpdate,
604
+ sizeUpdateMs,
605
+ onResize,
606
+ onResizeStart,
607
+ onResizeEnd,
608
+ snapPoints,
609
+ snapTolerance,
610
+ collapseThreshold,
611
+ paneId,
612
+ persistence,
613
+ overlaying: pane.overlaying,
614
+ // Asked when the effect runs: the Rail registers its table after this
615
+ // Panel first renders, so the render's answer can be out of date.
616
+ overlayingNow: () => {
617
+ const table = followsRail ? (store.entries.get('rail')?.presentationTable ?? FIXED_TABLE) : own.table;
618
+ return table[readBreakpoint()] === 'overlay';
619
+ },
620
+ requestCollapse: () => pane.setValue('closed', 'toggle'),
621
+ requestToggle: () => pane.toggle('toggle'),
622
+ });
1298
623
 
1299
- // Dev-only warning if switching controlled/uncontrolled between renders
1300
- const wasControlledRef = React.useRef<boolean | null>(null);
1301
- React.useEffect(() => {
1302
- const isControlled = typeof open !== 'undefined';
1303
- if (wasControlledRef.current === null) {
1304
- wasControlledRef.current = isControlled;
1305
- return;
1306
- }
1307
- if (wasControlledRef.current !== isControlled) {
1308
- console.warn('Shell.Panel: Switching between controlled and uncontrolled `open` is not supported.');
1309
- wasControlledRef.current = isControlled;
1310
- }
1311
- }, [open]);
1312
-
1313
- React.useEffect(() => {
1314
- shell.onPanelDefaults?.(expandedSize);
1315
- }, [shell, expandedSize]);
1316
- const localRef = React.useRef<HTMLDivElement | null>(null);
1317
- const setRef = React.useCallback(
1318
- (node: HTMLDivElement | null) => {
1319
- localRef.current = node;
1320
- if (typeof ref === 'function') ref(node);
1321
- else if (ref) (ref as React.MutableRefObject<HTMLDivElement | null>).current = node;
1322
- },
1323
- [ref],
1324
- );
1325
- const childArray = React.Children.toArray(children) as React.ReactElement[];
1326
- const handleChildren = childArray.filter((el: React.ReactElement) => React.isValidElement(el) && el.type === PanelHandle);
1327
- const contentChildren = childArray.filter((el: React.ReactElement) => !(React.isValidElement(el) && el.type === PanelHandle));
1328
-
1329
- const isOverlay = shell.leftResolvedPresentation === 'overlay';
1330
-
1331
- // Normalize CSS lengths to px helper
1332
- const normalizeSizeToPx = React.useCallback((value: number | string | undefined) => normalizeToPx(value, 'horizontal'), []);
1333
-
1334
- // Derive a default persistence adapter from paneId if none provided
1335
- const persistenceAdapter = React.useMemo(() => {
1336
- if (!paneId || persistence) return persistence;
1337
- const key = `kookie-ui:shell:panel:${paneId}`;
1338
- const adapter: PaneSizePersistence = {
1339
- load: () => {
1340
- if (typeof window === 'undefined') return undefined;
1341
- try {
1342
- const v = window.localStorage.getItem(key);
1343
- return v ? Number(v) : undefined;
1344
- } catch (err) {
1345
- if (process.env.NODE_ENV !== 'production') {
1346
- console.warn('Shell.Panel: failed to load persisted size', err);
1347
- }
1348
- return undefined;
1349
- }
1350
- },
1351
- save: (size: number) => {
1352
- if (typeof window === 'undefined') return;
1353
- try {
1354
- window.localStorage.setItem(key, String(size));
1355
- } catch (err) {
1356
- if (process.env.NODE_ENV !== 'production') {
1357
- console.warn('Shell.Panel: failed to save persisted size', err);
1358
- }
1359
- }
1360
- },
1361
- };
1362
- return adapter;
1363
- }, [paneId, persistence]);
1364
-
1365
- // Load persisted size if configured (only in fixed presentation)
1366
- React.useEffect(() => {
1367
- let mounted = true;
1368
- (async () => {
1369
- if (!resizable || !persistenceAdapter?.load || isOverlay) return;
1370
- const loaded = await persistenceAdapter.load();
1371
- if (mounted && typeof loaded === 'number' && localRef.current) {
1372
- localRef.current.style.setProperty('--panel-size', `${loaded}px`);
1373
- onResize?.(loaded);
1374
- }
1375
- })();
1376
- return () => {
1377
- mounted = false;
1378
- };
1379
- }, [resizable, persistenceAdapter, onResize, isOverlay]);
624
+ const { handles, content } = splitHandles(children, PanelHandle);
625
+ const handle = resizable && pane.shown !== false && !pane.overlaying ? <PaneResizeContext.Provider value={resize}>{handles.length > 0 ? handles : <PaneHandle />}</PaneResizeContext.Provider> : null;
1380
626
 
1381
- // In overlay, ensure panel uses the fixed expandedSize, ignoring any persisted size
1382
- React.useEffect(() => {
1383
- if (!localRef.current) return;
1384
- if (isOverlay) {
1385
- localRef.current.style.setProperty('--panel-size', `${expandedSize}px`);
1386
- }
1387
- }, [isOverlay, expandedSize]);
1388
-
1389
- // Apply defaultSize on mount when uncontrolled
1390
- React.useEffect(() => {
1391
- if (!localRef.current) return;
1392
- if (typeof size === 'undefined' && typeof defaultSize !== 'undefined') {
1393
- const px = normalizeSizeToPx(defaultSize);
1394
- if (typeof px === 'number' && Number.isFinite(px)) {
1395
- // Clamp to min/max if provided
1396
- const minPx = typeof minSize === 'number' ? minSize : undefined;
1397
- const maxPx = typeof maxSize === 'number' ? maxSize : undefined;
1398
- const clamped = Math.min(maxPx ?? px, Math.max(minPx ?? px, px));
1399
- localRef.current.style.setProperty('--panel-size', `${clamped}px`);
1400
- emitSizeChange(clamped, { reason: 'init' });
1401
- }
1402
- }
1403
- // Intentionally run only on mount - defaultSize is an uncontrolled initial value
1404
- // that should not trigger re-application when props change
1405
- // eslint-disable-next-line react-hooks/exhaustive-deps
1406
- }, []);
1407
-
1408
- // Controlled size sync
1409
- React.useEffect(() => {
1410
- if (!localRef.current) return;
1411
- if (typeof size === 'undefined') return;
1412
- const px = normalizeSizeToPx(size);
1413
- if (typeof px === 'number' && Number.isFinite(px)) {
1414
- const minPx = typeof minSize === 'number' ? minSize : undefined;
1415
- const maxPx = typeof maxSize === 'number' ? maxSize : undefined;
1416
- const clamped = Math.min(maxPx ?? px, Math.max(minPx ?? px, px));
1417
- localRef.current.style.setProperty('--panel-size', `${clamped}px`);
1418
- emitSizeChange(clamped, { reason: 'controlled' });
1419
- }
1420
- }, [size, minSize, maxSize, normalizeSizeToPx, emitSizeChange]);
1421
-
1422
- // Ensure Left container width is auto whenever Panel is expanded in fixed presentation
1423
- React.useEffect(() => {
1424
- if (!localRef.current) return;
1425
- if (shell.leftResolvedPresentation !== 'overlay' && shell.leftMode === 'expanded' && shell.panelMode === 'expanded') {
1426
- const leftEl = (localRef.current.parentElement as HTMLElement) || null;
1427
- try {
1428
- leftEl?.style.removeProperty('width');
1429
- } catch (e) {
1430
- // Style manipulation can fail in edge cases (e.g., detached elements)
1431
- if (process.env.NODE_ENV !== 'production') {
1432
- console.warn('[Shell.Panel] Style cleanup warning:', e);
1433
- }
1434
- }
1435
- }
1436
- }, [shell.leftResolvedPresentation, shell.leftMode, shell.panelMode]);
1437
-
1438
- const isExpanded = shell.leftMode === 'expanded' && shell.panelMode === 'expanded';
1439
-
1440
- // Notify on internal toggles and left cascade.
1441
- // In controlled mode, skip when the mode matches the controlled prop (prop-driven sync).
1442
- React.useEffect(() => {
1443
- const prevPanel = prevPanelModeRef.current;
1444
- const prevLeft = prevLeftModeRef.current;
1445
- const prevResolvedControlled = lastResolvedPanelControlledRef.current;
1446
- const controlledChanged = prevResolvedControlled !== resolvedPanelControlled;
1447
- if (prevPanel !== null && prevPanel !== shell.panelMode) {
1448
- const nextOpen = shell.panelMode === 'expanded';
1449
- const isControlled = typeof open !== 'undefined';
1450
- const controlledTarget = resolvedPanelControlled === undefined ? undefined : resolvedPanelControlled === 'expanded';
1451
-
1452
- if (!isControlled || (!controlledChanged && nextOpen !== controlledTarget)) {
1453
- let reason: PanelOpenChangeMeta['reason'] = 'toggle';
1454
- if (prevLeft !== shell.leftMode && shell.leftMode === 'collapsed' && !nextOpen) {
1455
- reason = 'left';
1456
- }
1457
- onOpenChangeRef.current?.(nextOpen, { reason });
1458
- }
1459
- }
1460
- prevPanelModeRef.current = shell.panelMode;
1461
- prevLeftModeRef.current = shell.leftMode;
1462
- lastResolvedPanelControlledRef.current = resolvedPanelControlled;
1463
- }, [shell.panelMode, shell.leftMode, open, resolvedPanelControlled]);
1464
-
1465
- // Provide resizer handle when fixed (not overlay)
1466
- const handleEl =
1467
- resizable && shell.leftResolvedPresentation !== 'overlay' && isExpanded ? (
1468
- <PaneResizeContext.Provider
1469
- value={{
1470
- containerRef: localRef,
1471
- cssVarName: '--panel-size',
1472
- minSize: typeof minSize === 'number' ? minSize : 100,
1473
- maxSize: typeof maxSize === 'number' ? maxSize : 800,
1474
- defaultSize: expandedSize,
1475
- orientation: 'vertical',
1476
- edge: 'end',
1477
- computeNext: (client, startClient, startSize) => {
1478
- const isRtl = getComputedStyle(localRef.current!).direction === 'rtl';
1479
- const delta = client - startClient;
1480
- return startSize + (isRtl ? -delta : delta);
1481
- },
1482
- onResize,
1483
- onResizeStart: (size) => {
1484
- // Ensure Left container is not stuck with a fixed width in stacked
1485
- const panelEl = localRef.current as HTMLElement | null;
1486
- const leftEl = panelEl?.parentElement as HTMLElement | null;
1487
- try {
1488
- leftEl?.style.removeProperty('width');
1489
- } catch (e) {
1490
- // Style manipulation can fail in edge cases
1491
- if (process.env.NODE_ENV !== 'production') {
1492
- console.warn('[Shell.Panel] Resize start style cleanup warning:', e);
1493
- }
1494
- }
1495
- onResizeStart?.(size);
1496
- },
1497
- onResizeEnd: (size) => {
1498
- onResizeEnd?.(size);
1499
- emitSizeChange(size, { reason: 'resize' });
1500
- persistenceAdapter?.save?.(size);
1501
- },
1502
- target: 'panel',
1503
- collapsible: Boolean(collapsible),
1504
- snapPoints,
1505
- snapTolerance: snapTolerance ?? 8,
1506
- collapseThreshold,
1507
- requestCollapse: () => shell.setPanelMode('collapsed'),
1508
- requestToggle: () => shell.togglePane('panel'),
1509
- }}
1510
- >
1511
- {handleChildren.length > 0 ? handleChildren.map((el, i) => React.cloneElement(el, { key: el.key ?? i })) : <PaneHandle />}
1512
- </PaneResizeContext.Provider>
1513
- ) : null;
1514
-
1515
- return (
1516
- <div
1517
- {...panelDomProps}
1518
- ref={setRef}
1519
- className={classNames('rt-ShellPanel', className)}
1520
- data-mode={shell.panelMode}
1521
- data-visible={(shell.currentBreakpointReady && (isExpanded || (shell.leftResolvedPresentation !== 'overlay' && shell.peekTarget === 'panel'))) || undefined}
1522
- data-peek={(shell.currentBreakpointReady && shell.leftResolvedPresentation !== 'overlay' && shell.peekTarget === 'panel') || undefined}
1523
- style={{
627
+ return (
628
+ <div
629
+ {...withoutRemovedPaneProps(domProps)}
630
+ id={pane.id}
631
+ ref={composedRef}
632
+ className={classNames('rt-ShellPane', 'rt-ShellPanel', className)}
633
+ {...paneAttributes(pane, presentationAttributes)}
634
+ data-inset={inset || undefined}
635
+ tabIndex={pane.overlaying ? -1 : domProps.tabIndex}
636
+ style={
637
+ {
1524
638
  ...style,
1525
- '--panel-size': `${expandedSize}px`,
1526
- } as CSSPropertiesWithVars}
1527
- >
1528
- <div className="rt-ShellPanelContent" data-visible={isExpanded || undefined}>
1529
- {contentChildren}
1530
- </div>
1531
- {handleEl}
1532
- </div>
1533
- );
1534
- }),
1535
- 'Shell.Panel',
1536
- ) as PanelComponent;
639
+ '--panel-expanded-size': `${expandedSize}px`,
640
+ } as CSSPropertiesWithVars
641
+ }
642
+ >
643
+ <div className="rt-ShellPanelContent">{content}</div>
644
+ {handle}
645
+ </div>
646
+ );
647
+ }) as PanelComponent;
1537
648
  Panel.displayName = 'Shell.Panel';
1538
649
  Panel.Handle = PanelHandle;
1539
650
 
1540
- // Sidebar moved to ./_internal/shell-sidebar
651
+ /* ── Content ───────────────────────────────────────────────────────────────── */
1541
652
 
1542
- // Content (always required)
1543
653
  interface ShellContentProps extends React.ComponentPropsWithoutRef<'main'> {
1544
- /** When true, adds margin and triggers gray backdrop on Shell. */
654
+ /** When true, adds margin and triggers the gray backdrop on the Shell. */
1545
655
  inset?: boolean;
1546
656
  }
1547
657
 
1548
658
  const Content = React.forwardRef<HTMLElement, ShellContentProps>(({ className, inset, ...props }, ref) => {
1549
- const { registerInset, unregisterInset } = useInset();
1550
-
1551
- // Register/unregister inset
1552
- React.useEffect(() => {
1553
- if (inset) {
1554
- registerInset('content');
1555
- return () => unregisterInset('content');
1556
- }
1557
- }, [inset, registerInset, unregisterInset]);
1558
-
659
+ useInsetRegistration('content', inset);
1559
660
  return <main {...props} ref={ref} className={classNames('rt-ShellContent', className)} data-inset={inset || undefined} />;
1560
661
  });
1561
662
  Content.displayName = 'Shell.Content';
1562
- assignShellSlot(Content as any, 'Shell.Content');
1563
-
1564
- // Inspector moved to ./_internal/shell-inspector
1565
663
 
1566
- // Bottom
1567
- // Bottom moved to ./_internal/shell-bottom
1568
- // (Bottom implementation extracted)
664
+ /* ── Trigger ───────────────────────────────────────────────────────────────── */
1569
665
 
1570
- // Trigger
1571
- // PaneTarget type moved to shell.types.ts
1572
666
  type TriggerAction = 'toggle' | 'expand' | 'collapse';
1573
667
 
1574
668
  interface TriggerProps extends React.ComponentPropsWithoutRef<'button'> {
1575
669
  target: PaneTarget;
1576
670
  action?: TriggerAction;
1577
671
  /**
1578
- * Whether to show peek preview on hover when the target pane is collapsed.
1579
- * Defaults to false.
672
+ * Whether to show a preview of the target pane on hover while it is closed
673
+ * and not an overlay. Defaults to false.
674
+ *
675
+ * @deprecated Removed in 1.0. A preview reachable only by mouse hover has no
676
+ * keyboard or touch equivalent; open the pane instead.
1580
677
  */
1581
678
  peekOnHover?: boolean;
1582
679
  }
1583
680
 
681
+ /**
682
+ * A button that drives a pane by name, through the registry. It sets
683
+ * `aria-controls` and `aria-expanded` (left off while an untouched pane
684
+ * cannot know its state yet), renders `type="button"`, and runs the
685
+ * consumer's `onClick` first: calling `preventDefault()` there cancels it.
686
+ */
1584
687
  const Trigger = React.forwardRef<HTMLButtonElement, TriggerProps>(({ target, action = 'toggle', peekOnHover, onClick, onMouseEnter, onMouseLeave, children, ...props }, ref) => {
1585
- // Slice hooks — Trigger only re-renders when its target pane's slice changes,
1586
- // not on every unrelated shell state update (peek, composition, presentation, etc.)
1587
- const { leftMode } = useLeftMode();
1588
- const { panelMode } = usePanelMode();
1589
- const { sidebarMode } = useSidebarMode();
1590
- const { inspectorMode } = useInspectorMode();
1591
- const { bottomMode } = useBottomMode();
1592
- const { peekTarget, clearPeek, peekPane } = usePeek();
1593
- const { togglePane, expandPane, collapsePane } = useShellActions();
1594
-
1595
- const handleClick = React.useCallback(
1596
- (event: React.MouseEvent<HTMLButtonElement>) => {
1597
- onClick?.(event);
1598
-
1599
- // Clear any active peek on this target before toggling to avoid sticky peek state
1600
- if (peekTarget === target) {
1601
- clearPeek();
1602
- }
1603
-
1604
- switch (action) {
1605
- case 'toggle':
1606
- togglePane(target);
1607
- break;
1608
- case 'expand':
1609
- expandPane(target);
1610
- break;
1611
- case 'collapse':
1612
- collapsePane(target);
1613
- break;
1614
- }
1615
- },
1616
- [peekTarget, clearPeek, togglePane, expandPane, collapsePane, target, action, onClick],
1617
- );
1618
-
1619
- const isCollapsed = (() => {
1620
- switch (target) {
1621
- case 'left':
1622
- case 'rail':
1623
- return leftMode === 'collapsed';
1624
- case 'panel':
1625
- return leftMode === 'collapsed' || panelMode === 'collapsed';
1626
- case 'sidebar':
1627
- return sidebarMode === 'collapsed';
1628
- case 'inspector':
1629
- return inspectorMode === 'collapsed';
1630
- case 'bottom':
1631
- return bottomMode === 'collapsed';
1632
- }
1633
- })();
688
+ const store = useShellStore('Shell.Trigger');
689
+ React.useEffect(() => {
690
+ if (target === 'left') warnOnce('Shell.Trigger target="left" is deprecated and is removed in 1.0. Use target="rail".');
691
+ if (peekOnHover) warnOnce('Shell.Trigger: `peekOnHover` is deprecated and is removed in 1.0.');
692
+ }, [target, peekOnHover]);
693
+ const name: PaneName = target === 'left' ? 'rail' : target;
694
+ // Subscribes to its own pane only.
695
+ const entry = usePaneEntry(store, name);
696
+ const shown = entry?.value === undefined ? undefined : entry.value !== 'closed';
697
+
698
+ const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
699
+ onClick?.(event);
700
+ if (event.defaultPrevented) return;
701
+ const current = store.entries.get(name);
702
+ if (!current) return;
703
+ if (store.peek === name) setShellPeek(store, null);
704
+ if (action === 'toggle') current.toggle('toggle');
705
+ else if (action === 'expand') current.setValue('open', 'toggle');
706
+ else current.setValue('closed', 'toggle');
707
+ };
1634
708
 
1635
- const handleMouseEnter = React.useCallback(
1636
- (event: React.MouseEvent<HTMLButtonElement>) => {
1637
- onMouseEnter?.(event);
1638
- if (!peekOnHover || !isCollapsed) return;
1639
- peekPane(target);
1640
- },
1641
- [onMouseEnter, peekOnHover, isCollapsed, peekPane, target],
1642
- );
709
+ const handleMouseEnter = (event: React.MouseEvent<HTMLButtonElement>) => {
710
+ onMouseEnter?.(event);
711
+ if (!peekOnHover) return;
712
+ const current = store.entries.get(name);
713
+ if (current && current.value === 'closed' && current.presentation !== 'overlay') setShellPeek(store, name);
714
+ };
1643
715
 
1644
- const handleMouseLeave = React.useCallback(
1645
- (event: React.MouseEvent<HTMLButtonElement>) => {
1646
- onMouseLeave?.(event);
1647
- if (!peekOnHover) return;
1648
- if (peekTarget === target) {
1649
- clearPeek();
1650
- }
1651
- },
1652
- [onMouseLeave, peekOnHover, peekTarget, clearPeek, target],
1653
- );
716
+ const handleMouseLeave = (event: React.MouseEvent<HTMLButtonElement>) => {
717
+ onMouseLeave?.(event);
718
+ if (peekOnHover && store.peek === name) setShellPeek(store, null);
719
+ };
1654
720
 
1655
721
  return (
1656
722
  <button
723
+ // A button's default type is `submit`. Stated before the spread, so a consumer's own wins.
724
+ type="button"
725
+ aria-controls={entry?.id}
726
+ aria-expanded={shown}
1657
727
  {...props}
1658
728
  ref={ref}
1659
729
  onClick={handleClick}
@@ -1661,7 +731,6 @@ const Trigger = React.forwardRef<HTMLButtonElement, TriggerProps>(({ target, act
1661
731
  onMouseLeave={handleMouseLeave}
1662
732
  data-shell-trigger={target}
1663
733
  data-shell-action={action}
1664
- aria-expanded={!isCollapsed}
1665
734
  >
1666
735
  {children}
1667
736
  </button>