@ui-sdk/web 0.0.0-stage → 0.1.0-beta.1

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 (467) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +10 -2
  3. package/browser/web/accordion.js +1 -0
  4. package/browser/web/alert-dialog.js +1 -0
  5. package/browser/web/autocomplete.js +1 -0
  6. package/browser/web/avatar.js +1 -0
  7. package/browser/web/button.js +1 -0
  8. package/browser/web/calendar.js +1 -0
  9. package/browser/web/carousel.js +1 -0
  10. package/browser/web/checkbox.js +1 -0
  11. package/browser/web/chunks/0eRGibL6.js +1 -0
  12. package/browser/web/chunks/2bIEUO6_.js +1 -0
  13. package/browser/web/chunks/5A9w2ULz.js +1 -0
  14. package/browser/web/chunks/5RSyydjV.js +1 -0
  15. package/browser/web/chunks/9pWTy2wl.js +1 -0
  16. package/browser/web/chunks/B0f2j6zz.js +1 -0
  17. package/browser/web/chunks/B1rux6br.js +1 -0
  18. package/browser/web/chunks/B3-APaNf.js +1 -0
  19. package/browser/web/chunks/B7EgSgjQ.js +1 -0
  20. package/browser/web/chunks/B8QcOzJU.js +1 -0
  21. package/browser/web/chunks/BFueEkwm.js +3 -0
  22. package/browser/web/chunks/BJj3oS29.js +1 -0
  23. package/browser/web/chunks/BNSvTCpr.js +1 -0
  24. package/browser/web/chunks/BPD0kAZB.js +1 -0
  25. package/browser/web/chunks/BQeduZqT.js +1 -0
  26. package/browser/web/chunks/B_CVFyiz.js +1 -0
  27. package/browser/web/chunks/B_ns1YHO.js +1 -0
  28. package/browser/web/chunks/BcwkVTsR.js +1 -0
  29. package/browser/web/chunks/BeaQ6TYM.js +1 -0
  30. package/browser/web/chunks/BgBB013u.js +1 -0
  31. package/browser/web/chunks/BgsKhHDm.js +1 -0
  32. package/browser/web/chunks/BjMcbuhi.js +9 -0
  33. package/browser/web/chunks/Bjiy_F2N.js +1 -0
  34. package/browser/web/chunks/BqScCLwv.js +1 -0
  35. package/browser/web/chunks/BqX3Utqx.js +1 -0
  36. package/browser/web/chunks/BtVkQf3z.js +1 -0
  37. package/browser/web/chunks/By30h-7B.js +1 -0
  38. package/browser/web/chunks/C1zqYpy2.js +1 -0
  39. package/browser/web/chunks/C436juFf.js +1 -0
  40. package/browser/web/chunks/C4_bULs1.js +1 -0
  41. package/browser/web/chunks/C4omqJEz.js +1 -0
  42. package/browser/web/chunks/C7tt0T3n.js +1 -0
  43. package/browser/web/chunks/C8w7s5dg.js +1 -0
  44. package/browser/web/chunks/CElY4erO.js +1 -0
  45. package/browser/web/chunks/CFODo-m2.js +1 -0
  46. package/browser/web/chunks/CL4wjam9.js +1 -0
  47. package/browser/web/chunks/CMg-8UVf.js +1 -0
  48. package/browser/web/chunks/COWKfakj.js +1 -0
  49. package/browser/web/chunks/CQBU0qZ4.js +1 -0
  50. package/browser/web/chunks/CV6uABgc.js +1 -0
  51. package/browser/web/chunks/C_SWFpWQ.js +1 -0
  52. package/browser/web/chunks/C_Uanbrl.js +1 -0
  53. package/browser/web/chunks/Ce_CSanC.js +1 -0
  54. package/browser/web/chunks/Cg-ZmRhS.js +1 -0
  55. package/browser/web/chunks/Cgf2wPI_.js +1 -0
  56. package/browser/web/chunks/Cuep_3Vf.js +1 -0
  57. package/browser/web/chunks/D02PaHn6.js +1 -0
  58. package/browser/web/chunks/D5LiaI5R.js +1 -0
  59. package/browser/web/chunks/D9UgVYvF.js +1 -0
  60. package/browser/web/chunks/DC08tnkE.js +2 -0
  61. package/browser/web/chunks/DG8YGSvu.js +1 -0
  62. package/browser/web/chunks/DIQd0FYD.js +1 -0
  63. package/browser/web/chunks/DMLqacE8.js +1 -0
  64. package/browser/web/chunks/DSUI3yI-.js +1 -0
  65. package/browser/web/chunks/DT3Hb76X.js +1 -0
  66. package/browser/web/chunks/DY75g3-W.js +1 -0
  67. package/browser/web/chunks/DZpNQKZ9.js +1 -0
  68. package/browser/web/chunks/Db-W1wrC.js +1 -0
  69. package/browser/web/chunks/Dc1xK3Ii.js +1 -0
  70. package/browser/web/chunks/DdF6awFs.js +1 -0
  71. package/browser/web/chunks/DdaCLml8.js +1 -0
  72. package/browser/web/chunks/Dh8MLjQO.js +1 -0
  73. package/browser/web/chunks/DiuslJRy.js +1 -0
  74. package/browser/web/chunks/DjRcw3Y0.js +1 -0
  75. package/browser/web/chunks/Djdv-16J.js +1 -0
  76. package/browser/web/chunks/DnFXe_lF.js +1 -0
  77. package/browser/web/chunks/DneGv1oC.js +1 -0
  78. package/browser/web/chunks/DsVxP-p-.js +1 -0
  79. package/browser/web/chunks/DwDilCo2.js +1 -0
  80. package/browser/web/chunks/DwV48AXv.js +1 -0
  81. package/browser/web/chunks/F37aF4-L.js +1 -0
  82. package/browser/web/chunks/LyB6XIbN.js +1 -0
  83. package/browser/web/chunks/NKnbYGjC.js +1 -0
  84. package/browser/web/chunks/Vk-rVi16.js +1 -0
  85. package/browser/web/chunks/XsM0J1Ex.js +1 -0
  86. package/browser/web/chunks/asSN9iEp.js +1 -0
  87. package/browser/web/chunks/c-AjHfdF.js +1 -0
  88. package/browser/web/chunks/dR-12TPY.js +1 -0
  89. package/browser/web/chunks/hR4xM0EC.js +1 -0
  90. package/browser/web/chunks/hqOaBxAg.js +1 -0
  91. package/browser/web/chunks/kMKqqeG4.js +1 -0
  92. package/browser/web/chunks/kXboBcfi.js +1 -0
  93. package/browser/web/chunks/l4aQIg22.js +1 -0
  94. package/browser/web/chunks/tJC0JSU4.js +1 -0
  95. package/browser/web/chunks/wHdS_QYM.js +1 -0
  96. package/browser/web/chunks/yv8dTvNI.js +1 -0
  97. package/browser/web/chunks/yw9M3nfi.js +1 -0
  98. package/browser/web/collapsible.js +1 -0
  99. package/browser/web/color-picker.js +1 -0
  100. package/browser/web/combobox.js +2 -0
  101. package/browser/web/command.js +1 -0
  102. package/browser/web/core.js +5 -0
  103. package/browser/web/date-input.js +1 -0
  104. package/browser/web/date-picker.js +1 -0
  105. package/browser/web/dialog.js +1 -0
  106. package/browser/web/drawer.js +1 -0
  107. package/browser/web/field.js +1 -0
  108. package/browser/web/file-input.js +1 -0
  109. package/browser/web/hover-card.js +1 -0
  110. package/browser/web/image-cropper.js +1 -0
  111. package/browser/web/input.js +1 -0
  112. package/browser/web/label.js +1 -0
  113. package/browser/web/listbox.js +1 -0
  114. package/browser/web/menu.js +1 -0
  115. package/browser/web/menubar.js +1 -0
  116. package/browser/web/meter.js +1 -0
  117. package/browser/web/navigation-menu.js +1 -0
  118. package/browser/web/number-input.js +1 -0
  119. package/browser/web/otp-input.js +2 -0
  120. package/browser/web/overlays.js +1 -0
  121. package/browser/web/pagination.js +1 -0
  122. package/browser/web/password-input.js +1 -0
  123. package/browser/web/popover.js +1 -0
  124. package/browser/web/preferences.js +1 -0
  125. package/browser/web/progress.js +1 -0
  126. package/browser/web/radio.js +1 -0
  127. package/browser/web/rating.js +1 -0
  128. package/browser/web/resizable.js +1 -0
  129. package/browser/web/scroll-area.js +1 -0
  130. package/browser/web/segmented-control.js +1 -0
  131. package/browser/web/select.js +1 -0
  132. package/browser/web/separator.js +1 -0
  133. package/browser/web/slider.js +1 -0
  134. package/browser/web/switch.js +1 -0
  135. package/browser/web/tabs.js +1 -0
  136. package/browser/web/textarea.js +1 -0
  137. package/browser/web/time-input.js +1 -0
  138. package/browser/web/timeline.js +1 -0
  139. package/browser/web/toast.js +1 -0
  140. package/browser/web/toggle.js +1 -0
  141. package/browser/web/token-input.js +8 -0
  142. package/browser/web/toolbar.js +1 -0
  143. package/browser/web/tooltip.js +1 -0
  144. package/browser/web/tree.js +1 -0
  145. package/browser/web/trigger-menu.js +4 -0
  146. package/browser/web/waterfall.js +1 -0
  147. package/browser/web.css +3378 -0
  148. package/browser/web.js +3 -0
  149. package/custom-elements.json +32315 -0
  150. package/dist/accordion.d.ts +2 -0
  151. package/dist/accordion.js +57 -0
  152. package/dist/action.d.ts +16 -0
  153. package/dist/action.js +39 -0
  154. package/dist/agent.d.ts +2 -0
  155. package/dist/agent.js +7 -0
  156. package/dist/autocomplete.d.ts +2 -0
  157. package/dist/autocomplete.js +120 -0
  158. package/dist/autoload.d.ts +18 -0
  159. package/dist/autoload.js +63 -0
  160. package/dist/avatar.d.ts +2 -0
  161. package/dist/avatar.js +27 -0
  162. package/dist/browser-core.d.ts +2 -0
  163. package/dist/browser-core.js +8 -0
  164. package/dist/button.d.ts +2 -0
  165. package/dist/button.js +35 -0
  166. package/dist/calendar.d.ts +23 -0
  167. package/dist/calendar.js +429 -0
  168. package/dist/carousel.d.ts +2 -0
  169. package/dist/carousel.js +54 -0
  170. package/dist/checkbox.d.ts +4 -0
  171. package/dist/checkbox.js +75 -0
  172. package/dist/collapsible.d.ts +2 -0
  173. package/dist/collapsible.js +28 -0
  174. package/dist/color-picker.d.ts +2 -0
  175. package/dist/color-picker.js +64 -0
  176. package/dist/combobox.d.ts +2 -0
  177. package/dist/combobox.js +334 -0
  178. package/dist/command.d.ts +2 -0
  179. package/dist/command.js +122 -0
  180. package/dist/date-input.d.ts +3 -0
  181. package/dist/date-input.js +87 -0
  182. package/dist/date-picker.d.ts +2 -0
  183. package/dist/date-picker.js +174 -0
  184. package/dist/default-text.d.ts +3 -0
  185. package/dist/default-text.js +24 -0
  186. package/dist/define-element.d.ts +404 -0
  187. package/dist/define-element.js +1489 -0
  188. package/dist/dialog.d.ts +3 -0
  189. package/dist/dialog.js +94 -0
  190. package/dist/drawer.d.ts +2 -0
  191. package/dist/drawer.js +96 -0
  192. package/dist/entries/accordion.d.ts +3 -0
  193. package/dist/entries/accordion.js +7 -0
  194. package/dist/entries/alert-dialog.d.ts +3 -0
  195. package/dist/entries/alert-dialog.js +13 -0
  196. package/dist/entries/autocomplete.d.ts +3 -0
  197. package/dist/entries/autocomplete.js +7 -0
  198. package/dist/entries/avatar.d.ts +2 -0
  199. package/dist/entries/avatar.js +3 -0
  200. package/dist/entries/button.d.ts +2 -0
  201. package/dist/entries/button.js +3 -0
  202. package/dist/entries/calendar.d.ts +3 -0
  203. package/dist/entries/calendar.js +7 -0
  204. package/dist/entries/carousel.d.ts +3 -0
  205. package/dist/entries/carousel.js +7 -0
  206. package/dist/entries/checkbox.d.ts +3 -0
  207. package/dist/entries/checkbox.js +15 -0
  208. package/dist/entries/collapsible.d.ts +3 -0
  209. package/dist/entries/collapsible.js +7 -0
  210. package/dist/entries/color-picker.d.ts +3 -0
  211. package/dist/entries/color-picker.js +7 -0
  212. package/dist/entries/combobox.d.ts +3 -0
  213. package/dist/entries/combobox.js +7 -0
  214. package/dist/entries/command.d.ts +3 -0
  215. package/dist/entries/command.js +7 -0
  216. package/dist/entries/date-input.d.ts +3 -0
  217. package/dist/entries/date-input.js +7 -0
  218. package/dist/entries/date-picker.d.ts +3 -0
  219. package/dist/entries/date-picker.js +7 -0
  220. package/dist/entries/dialog.d.ts +3 -0
  221. package/dist/entries/dialog.js +7 -0
  222. package/dist/entries/drawer.d.ts +3 -0
  223. package/dist/entries/drawer.js +8 -0
  224. package/dist/entries/field.d.ts +2 -0
  225. package/dist/entries/field.js +3 -0
  226. package/dist/entries/file-input.d.ts +3 -0
  227. package/dist/entries/file-input.js +13 -0
  228. package/dist/entries/hover-card.d.ts +3 -0
  229. package/dist/entries/hover-card.js +7 -0
  230. package/dist/entries/image-cropper.d.ts +3 -0
  231. package/dist/entries/image-cropper.js +7 -0
  232. package/dist/entries/input.d.ts +3 -0
  233. package/dist/entries/input.js +8 -0
  234. package/dist/entries/label.d.ts +2 -0
  235. package/dist/entries/label.js +3 -0
  236. package/dist/entries/listbox.d.ts +3 -0
  237. package/dist/entries/listbox.js +7 -0
  238. package/dist/entries/menu.d.ts +3 -0
  239. package/dist/entries/menu.js +7 -0
  240. package/dist/entries/menubar.d.ts +3 -0
  241. package/dist/entries/menubar.js +7 -0
  242. package/dist/entries/meter.d.ts +2 -0
  243. package/dist/entries/meter.js +3 -0
  244. package/dist/entries/navigation-menu.d.ts +3 -0
  245. package/dist/entries/navigation-menu.js +7 -0
  246. package/dist/entries/number-input.d.ts +3 -0
  247. package/dist/entries/number-input.js +7 -0
  248. package/dist/entries/otp-input.d.ts +3 -0
  249. package/dist/entries/otp-input.js +7 -0
  250. package/dist/entries/overlays.d.ts +2 -0
  251. package/dist/entries/overlays.js +3 -0
  252. package/dist/entries/pagination.d.ts +3 -0
  253. package/dist/entries/pagination.js +11 -0
  254. package/dist/entries/password-input.d.ts +3 -0
  255. package/dist/entries/password-input.js +7 -0
  256. package/dist/entries/popover.d.ts +3 -0
  257. package/dist/entries/popover.js +7 -0
  258. package/dist/entries/preferences.d.ts +3 -0
  259. package/dist/entries/preferences.js +13 -0
  260. package/dist/entries/progress.d.ts +2 -0
  261. package/dist/entries/progress.js +3 -0
  262. package/dist/entries/radio.d.ts +3 -0
  263. package/dist/entries/radio.js +7 -0
  264. package/dist/entries/rating.d.ts +3 -0
  265. package/dist/entries/rating.js +8 -0
  266. package/dist/entries/resizable.d.ts +3 -0
  267. package/dist/entries/resizable.js +11 -0
  268. package/dist/entries/scroll-area.d.ts +3 -0
  269. package/dist/entries/scroll-area.js +7 -0
  270. package/dist/entries/segmented-control.d.ts +3 -0
  271. package/dist/entries/segmented-control.js +7 -0
  272. package/dist/entries/select.d.ts +3 -0
  273. package/dist/entries/select.js +7 -0
  274. package/dist/entries/separator.d.ts +2 -0
  275. package/dist/entries/separator.js +3 -0
  276. package/dist/entries/slider.d.ts +3 -0
  277. package/dist/entries/slider.js +7 -0
  278. package/dist/entries/switch.d.ts +3 -0
  279. package/dist/entries/switch.js +7 -0
  280. package/dist/entries/tabs.d.ts +3 -0
  281. package/dist/entries/tabs.js +7 -0
  282. package/dist/entries/textarea.d.ts +3 -0
  283. package/dist/entries/textarea.js +7 -0
  284. package/dist/entries/time-input.d.ts +3 -0
  285. package/dist/entries/time-input.js +7 -0
  286. package/dist/entries/timeline.d.ts +3 -0
  287. package/dist/entries/timeline.js +7 -0
  288. package/dist/entries/toast.d.ts +2 -0
  289. package/dist/entries/toast.js +3 -0
  290. package/dist/entries/toggle.d.ts +3 -0
  291. package/dist/entries/toggle.js +12 -0
  292. package/dist/entries/token-input.d.ts +3 -0
  293. package/dist/entries/token-input.js +17 -0
  294. package/dist/entries/toolbar.d.ts +3 -0
  295. package/dist/entries/toolbar.js +7 -0
  296. package/dist/entries/tooltip.d.ts +3 -0
  297. package/dist/entries/tooltip.js +7 -0
  298. package/dist/entries/tree.d.ts +3 -0
  299. package/dist/entries/tree.js +17 -0
  300. package/dist/entries/trigger-menu.d.ts +3 -0
  301. package/dist/entries/trigger-menu.js +11 -0
  302. package/dist/entries/waterfall.d.ts +3 -0
  303. package/dist/entries/waterfall.js +11 -0
  304. package/dist/events.d.ts +1658 -0
  305. package/dist/events.js +0 -0
  306. package/dist/field.d.ts +2 -0
  307. package/dist/field.js +101 -0
  308. package/dist/file-input.d.ts +2 -0
  309. package/dist/file-input.js +140 -0
  310. package/dist/forward-attributes.d.ts +2 -0
  311. package/dist/forward-attributes.js +22 -0
  312. package/dist/history.d.ts +2 -0
  313. package/dist/history.js +11 -0
  314. package/dist/hover-card.d.ts +2 -0
  315. package/dist/hover-card.js +31 -0
  316. package/dist/image-cropper.d.ts +2 -0
  317. package/dist/image-cropper.js +66 -0
  318. package/dist/index.d.ts +66 -0
  319. package/dist/index.js +269 -0
  320. package/dist/input.d.ts +3 -0
  321. package/dist/input.js +69 -0
  322. package/dist/label.d.ts +2 -0
  323. package/dist/label.js +11 -0
  324. package/dist/list.d.ts +40 -0
  325. package/dist/list.js +192 -0
  326. package/dist/listbox.d.ts +2 -0
  327. package/dist/listbox.js +84 -0
  328. package/dist/menu.d.ts +4 -0
  329. package/dist/menu.js +295 -0
  330. package/dist/menubar.d.ts +4 -0
  331. package/dist/menubar.js +30 -0
  332. package/dist/meter.d.ts +2 -0
  333. package/dist/meter.js +22 -0
  334. package/dist/navigation-menu.d.ts +2 -0
  335. package/dist/navigation-menu.js +114 -0
  336. package/dist/number-input.d.ts +2 -0
  337. package/dist/number-input.js +73 -0
  338. package/dist/observe.d.ts +2 -0
  339. package/dist/observe.js +7 -0
  340. package/dist/otp-input.d.ts +2 -0
  341. package/dist/otp-input.js +72 -0
  342. package/dist/overlays.d.ts +13 -0
  343. package/dist/overlays.js +156 -0
  344. package/dist/pagination.d.ts +2 -0
  345. package/dist/pagination.js +127 -0
  346. package/dist/password-input.d.ts +2 -0
  347. package/dist/password-input.js +57 -0
  348. package/dist/popover.d.ts +2 -0
  349. package/dist/popover.js +64 -0
  350. package/dist/popup.d.ts +40 -0
  351. package/dist/popup.js +112 -0
  352. package/dist/preferences.d.ts +2 -0
  353. package/dist/preferences.js +56 -0
  354. package/dist/progress.d.ts +2 -0
  355. package/dist/progress.js +22 -0
  356. package/dist/radio.d.ts +2 -0
  357. package/dist/radio.js +33 -0
  358. package/dist/rating.d.ts +2 -0
  359. package/dist/rating.js +64 -0
  360. package/dist/resizable.d.ts +2 -0
  361. package/dist/resizable.js +42 -0
  362. package/dist/scroll-area.d.ts +2 -0
  363. package/dist/scroll-area.js +45 -0
  364. package/dist/segmented-control.d.ts +2 -0
  365. package/dist/segmented-control.js +28 -0
  366. package/dist/select.d.ts +2 -0
  367. package/dist/select.js +239 -0
  368. package/dist/separator.d.ts +2 -0
  369. package/dist/separator.js +11 -0
  370. package/dist/slider.d.ts +2 -0
  371. package/dist/slider.js +77 -0
  372. package/dist/tabs.d.ts +2 -0
  373. package/dist/tabs.js +37 -0
  374. package/dist/timeline.d.ts +2 -0
  375. package/dist/timeline.js +27 -0
  376. package/dist/toast.d.ts +20 -0
  377. package/dist/toast.js +177 -0
  378. package/dist/toggle.d.ts +3 -0
  379. package/dist/toggle.js +64 -0
  380. package/dist/token-input.d.ts +2 -0
  381. package/dist/token-input.js +103 -0
  382. package/dist/toolbar.d.ts +2 -0
  383. package/dist/toolbar.js +36 -0
  384. package/dist/tooltip.d.ts +2 -0
  385. package/dist/tooltip.js +35 -0
  386. package/dist/tree.d.ts +2 -0
  387. package/dist/tree.js +147 -0
  388. package/dist/trigger-menu.d.ts +2 -0
  389. package/dist/trigger-menu.js +133 -0
  390. package/dist/waterfall.d.ts +2 -0
  391. package/dist/waterfall.js +140 -0
  392. package/docs/README.md +89 -0
  393. package/docs/agents.md +1523 -0
  394. package/docs/components/accordion.md +1401 -0
  395. package/docs/components/alert-dialog.md +788 -0
  396. package/docs/components/autocomplete.md +1692 -0
  397. package/docs/components/avatar.md +261 -0
  398. package/docs/components/button.md +441 -0
  399. package/docs/components/calendar.md +1536 -0
  400. package/docs/components/carousel.md +1055 -0
  401. package/docs/components/checkbox.md +1045 -0
  402. package/docs/components/collapsible.md +535 -0
  403. package/docs/components/color-picker.md +651 -0
  404. package/docs/components/combobox.md +3274 -0
  405. package/docs/components/command.md +1431 -0
  406. package/docs/components/date-input.md +563 -0
  407. package/docs/components/date-picker.md +1136 -0
  408. package/docs/components/dialog.md +1360 -0
  409. package/docs/components/drawer.md +1201 -0
  410. package/docs/components/field.md +519 -0
  411. package/docs/components/file-input.md +617 -0
  412. package/docs/components/hover-card.md +486 -0
  413. package/docs/components/image-cropper.md +489 -0
  414. package/docs/components/input.md +327 -0
  415. package/docs/components/label.md +208 -0
  416. package/docs/components/listbox.md +1015 -0
  417. package/docs/components/menu.md +1212 -0
  418. package/docs/components/menubar.md +460 -0
  419. package/docs/components/meter.md +298 -0
  420. package/docs/components/navigation-menu.md +1573 -0
  421. package/docs/components/number-input.md +1087 -0
  422. package/docs/components/otp-input.md +558 -0
  423. package/docs/components/pagination.md +639 -0
  424. package/docs/components/password-input.md +649 -0
  425. package/docs/components/popover.md +1433 -0
  426. package/docs/components/preferences.md +243 -0
  427. package/docs/components/progress.md +406 -0
  428. package/docs/components/radio.md +855 -0
  429. package/docs/components/rating.md +431 -0
  430. package/docs/components/resizable.md +866 -0
  431. package/docs/components/scroll-area.md +898 -0
  432. package/docs/components/segmented-control.md +421 -0
  433. package/docs/components/select.md +1957 -0
  434. package/docs/components/separator.md +238 -0
  435. package/docs/components/slider.md +1018 -0
  436. package/docs/components/switch.md +583 -0
  437. package/docs/components/tabs.md +948 -0
  438. package/docs/components/textarea.md +331 -0
  439. package/docs/components/time-input.md +235 -0
  440. package/docs/components/timeline.md +622 -0
  441. package/docs/components/toast.md +1223 -0
  442. package/docs/components/toggle.md +522 -0
  443. package/docs/components/token-input.md +854 -0
  444. package/docs/components/toolbar.md +815 -0
  445. package/docs/components/tooltip.md +860 -0
  446. package/docs/components/tree.md +1243 -0
  447. package/docs/components/trigger-menu.md +1110 -0
  448. package/docs/components/waterfall.md +709 -0
  449. package/docs/controllers.md +66 -0
  450. package/docs/core.md +8027 -0
  451. package/docs/custom-parts.md +91 -0
  452. package/docs/first-component.md +88 -0
  453. package/docs/forms.md +125 -0
  454. package/docs/installation.md +141 -0
  455. package/docs/introduction.md +32 -0
  456. package/docs/lists-and-menus.md +166 -0
  457. package/docs/llms.txt +1566 -0
  458. package/docs/parts-and-composition.md +57 -0
  459. package/docs/popups.md +92 -0
  460. package/docs/rendering.md +71 -0
  461. package/docs/server-rendering.md +118 -0
  462. package/docs/state-and-events.md +134 -0
  463. package/docs/styling-and-animation.md +104 -0
  464. package/docs/utilities/async-options.md +332 -0
  465. package/docs/utilities/shortcuts.md +184 -0
  466. package/html-custom-data.json +14792 -0
  467. package/package.json +302 -3
@@ -0,0 +1,866 @@
1
+ # Resizable
2
+
3
+ Resize, collapse, and save panel layouts with pointer and keyboard controls.
4
+
5
+ Use a resizable group to let people size the panes of a layout, like a file list beside an editor, by dragging the handle between them or with the keyboard.
6
+
7
+ ```ts title="basic.ts"
8
+ import "@ui-sdk/web/resizable"
9
+
10
+ function mount(root: HTMLElement) {
11
+ root.innerHTML = `
12
+ <ui-resizable>
13
+ <ui-resizable-panel default-size="35" min-size="20">
14
+ <h3>Files</h3>
15
+ <ul>
16
+ <li>page.tsx</li>
17
+ <li>layout.tsx</li>
18
+ <li>globals.css</li>
19
+ </ul>
20
+ </ui-resizable-panel>
21
+ <ui-resizable-handle aria-label="Resize files"></ui-resizable-handle>
22
+ <ui-resizable-panel default-size="65" min-size="40">
23
+ <ui-resizable orientation="vertical">
24
+ <ui-resizable-panel default-size="60" min-size="30">
25
+ <h3>page.tsx</h3>
26
+ <span data-slot="hint">Saved just now</span>
27
+ </ui-resizable-panel>
28
+ <ui-resizable-handle aria-label="Resize editor"></ui-resizable-handle>
29
+ <ui-resizable-panel default-size="40" min-size="30">
30
+ <h3>Terminal</h3>
31
+ <span data-slot="hint">Ready on port 3000</span>
32
+ </ui-resizable-panel>
33
+ </ui-resizable>
34
+ </ui-resizable-panel>
35
+ </ui-resizable>
36
+ `
37
+ }
38
+
39
+ export { mount }
40
+ ```
41
+
42
+ Drag the handle beside Files, then the one between page.tsx and Terminal.
43
+
44
+ ## Installation
45
+
46
+ ```bash
47
+ npm install @ui-sdk/web @ui-sdk/core
48
+ ```
49
+
50
+ Importing the component defines its elements. On the server the import does nothing.
51
+
52
+ ```ts
53
+ import "@ui-sdk/web/resizable"
54
+ ```
55
+
56
+ ## Composition
57
+
58
+ Use the following composition to build a `ui-resizable`:
59
+
60
+ ```text
61
+ ui-resizable
62
+ ├── ui-resizable-panel
63
+ ├── ui-resizable-handle
64
+ └── ui-resizable-panel
65
+ ```
66
+
67
+ Put a handle between the panels you want to resize, and name it with `aria-label`, like "Resize files". The group lays its panels out in a row, so give it a size, and each panel's size is a percentage of the space the panels share. A group can sit inside a panel, like an editor above a terminal.
68
+
69
+ ## Usage
70
+
71
+ Import the parts and put them together:
72
+
73
+ ```html
74
+ <script type="module">
75
+ import "@ui-sdk/web/resizable"
76
+ </script>
77
+
78
+ <ui-resizable>
79
+ <ui-resizable-panel default-size="30">Files</ui-resizable-panel>
80
+ <ui-resizable-handle aria-label="Resize files"></ui-resizable-handle>
81
+ <ui-resizable-panel>Editor</ui-resizable-panel>
82
+ </ui-resizable>
83
+ ```
84
+
85
+ The panel without `default-size` takes what's left, here 70%.
86
+
87
+ ## Build Your Own
88
+
89
+ `@ui-sdk/web/resizable` comes with ready-made `ui-resizable` elements. If you'd like to build your own, with your own element names, start from the `resizable` primitive in `@ui-sdk/core`:
90
+
91
+ ```ts title="split-view-elements.ts"
92
+ import { resizable } from "@ui-sdk/core/resizable"
93
+ import { createParts } from "@ui-sdk/web"
94
+
95
+ createParts(resizable, {
96
+ root: { tag: "split-view", display: "block" },
97
+ panel: { tag: "split-view-pane", display: "block" },
98
+ handle: { tag: "split-view-divider", display: "block" },
99
+ })
100
+ ```
101
+
102
+ ```html
103
+ <split-view>
104
+ <split-view-pane default-size="30">Files</split-view-pane>
105
+ <split-view-divider aria-label="Resize files"></split-view-divider>
106
+ <split-view-pane>Editor</split-view-pane>
107
+ </split-view>
108
+ ```
109
+
110
+ Each element keeps the behavior, state and data attributes of its ready-made counterpart: the root lays the panels out, each pane writes its size to `--resizable-panel-size`, and the divider is the focusable separator. See [Rendering](../rendering.md) and [Custom Parts](../custom-parts.md) for more.
111
+
112
+ ## Vertical
113
+
114
+ Set `orientation="vertical"` to stack the panels, and give the group a height. ArrowUp and ArrowDown move the handle. Every part gets `data-orientation` with the group's direction, so a vertical group's handle is `[data-slot="resizable-handle"][data-orientation="vertical"]`.
115
+
116
+ ```ts title="vertical.ts"
117
+ import "@ui-sdk/web/resizable"
118
+
119
+ function mount(root: HTMLElement) {
120
+ root.innerHTML = `
121
+ <ui-resizable orientation="vertical">
122
+ <ui-resizable-panel default-size="45" min-size="25">
123
+ <h3>Inbox</h3>
124
+ <span data-slot="hint">3 unread messages</span>
125
+ </ui-resizable-panel>
126
+ <ui-resizable-handle aria-label="Resize inbox"></ui-resizable-handle>
127
+ <ui-resizable-panel default-size="55" min-size="25">
128
+ <h3>Quarterly report</h3>
129
+ <span data-slot="hint">From Hollis Grant</span>
130
+ </ui-resizable-panel>
131
+ </ui-resizable>
132
+ `
133
+ }
134
+
135
+ export { mount }
136
+ ```
137
+
138
+ Drag the handle between Inbox and Quarterly report, or focus it and use ArrowUp and ArrowDown.
139
+
140
+ ## Handle
141
+
142
+ Put anything inside a handle, like a grip that shows it can be dragged. The handle can stay a thin line: its hit area is at least 10 pixels across, centered on it, and 24 for touch, without any styles.
143
+
144
+ ```ts title="handle.ts"
145
+ import "@ui-sdk/web/resizable"
146
+
147
+ function mount(root: HTMLElement) {
148
+ root.innerHTML = `
149
+ <ui-resizable>
150
+ <ui-resizable-panel default-size="35" min-size="20">
151
+ <h3>Channels</h3>
152
+ <ul>
153
+ <li>general</li>
154
+ <li>design</li>
155
+ <li>releases</li>
156
+ </ul>
157
+ </ui-resizable-panel>
158
+ <ui-resizable-handle aria-label="Resize channels"><div></div></ui-resizable-handle>
159
+ <ui-resizable-panel default-size="65" min-size="20">
160
+ <h3>general</h3>
161
+ <span data-slot="hint">Kofi Mensah: The release notes are ready.</span>
162
+ </ui-resizable-panel>
163
+ </ui-resizable>
164
+ `
165
+ }
166
+
167
+ export { mount }
168
+ ```
169
+
170
+ Grab the grip beside Channels, or focus the handle and use the arrow keys.
171
+
172
+ ## Collapsible
173
+
174
+ `collapsible` lets a panel collapse below its `min-size` to `collapsed-size`, 0 by default: by dragging past the midpoint to its collapsed size, with Enter or a double-click on its handle, or through the controller. Dragging back past the same point opens it at its minimum, and Enter restores the size it had. A collapsed panel gets `data-collapsed`, and at size 0 its content leaves the tab order and the accessibility tree.
175
+
176
+ ```ts title="collapsible.ts"
177
+ import "@ui-sdk/web/resizable"
178
+ import { createElement, Folder, Search, Settings } from "lucide"
179
+
180
+ function mount(root: HTMLElement) {
181
+ root.innerHTML = `
182
+ <ui-resizable>
183
+ <ui-resizable-panel default-size="30" min-size="25" collapsible collapsed-size="48px">
184
+ <ul>
185
+ <li data-slot="row">
186
+ ${createElement(Folder, { "aria-hidden": "true" }).outerHTML}
187
+ <span>Files</span>
188
+ </li>
189
+ <li data-slot="row">
190
+ ${createElement(Search, { "aria-hidden": "true" }).outerHTML}
191
+ <span>Search</span>
192
+ </li>
193
+ <li data-slot="row">
194
+ ${createElement(Settings, { "aria-hidden": "true" }).outerHTML}
195
+ <span>Settings</span>
196
+ </li>
197
+ </ul>
198
+ </ui-resizable-panel>
199
+ <ui-resizable-handle aria-label="Resize sidebar"><div></div></ui-resizable-handle>
200
+ <ui-resizable-panel min-size="40">
201
+ <h3>README.md</h3>
202
+ <span data-slot="hint">Edited by Inès Moreau</span>
203
+ </ui-resizable-panel>
204
+ </ui-resizable>
205
+ `
206
+ }
207
+
208
+ export { mount }
209
+ ```
210
+
211
+ Drag the sidebar closed to leave only its icons, or focus its handle and press Enter to collapse and restore it.
212
+
213
+ ## Sizes in Pixels
214
+
215
+ Sizes are percentages as numbers, or strings with `%`, `px` or `rem`. Pixel and rem bounds hold as the group resizes, so a navigation with `min-size="160px"` never gets narrower, and a change they cause reports the `resize` reason.
216
+
217
+ ```ts title="sizes.ts"
218
+ import "@ui-sdk/web/resizable"
219
+
220
+ function mount(root: HTMLElement) {
221
+ root.innerHTML = `
222
+ <ui-resizable>
223
+ <ui-resizable-panel default-size="200px" min-size="160px" max-size="320px">
224
+ <h3>Docs</h3>
225
+ <ul>
226
+ <li>Getting Started</li>
227
+ <li>Components</li>
228
+ <li>Guides</li>
229
+ </ul>
230
+ </ui-resizable-panel>
231
+ <ui-resizable-handle aria-label="Resize navigation"><div></div></ui-resizable-handle>
232
+ <ui-resizable-panel min-size="30">
233
+ <h3>Getting Started</h3>
234
+ <span data-slot="hint">Install the packages</span>
235
+ </ui-resizable-panel>
236
+ </ui-resizable>
237
+ `
238
+ }
239
+
240
+ export { mount }
241
+ ```
242
+
243
+ Resize Docs. It stays between 160 and 320 pixels wide, whatever the width of the group.
244
+
245
+ ## Default Layout
246
+
247
+ `default-layout` sets every panel's size at once, in order, like `"25,35,40"`. Otherwise panels without `default-size` share what's left evenly.
248
+
249
+ ```ts title="default-layout.ts"
250
+ import "@ui-sdk/web/resizable"
251
+
252
+ function mount(root: HTMLElement) {
253
+ root.innerHTML = `
254
+ <ui-resizable default-layout="25,35,40">
255
+ <ui-resizable-panel min-size="15">
256
+ <h3>Mail</h3>
257
+ <ul>
258
+ <li>Inbox</li>
259
+ <li>Drafts</li>
260
+ <li>Sent</li>
261
+ </ul>
262
+ </ui-resizable-panel>
263
+ <ui-resizable-handle aria-label="Resize folders"></ui-resizable-handle>
264
+ <ui-resizable-panel min-size="15">
265
+ <h3>Inbox</h3>
266
+ <ul>
267
+ <li>Hollis Grant</li>
268
+ <li>Inès Moreau</li>
269
+ <li>Kofi Mensah</li>
270
+ </ul>
271
+ </ui-resizable-panel>
272
+ <ui-resizable-handle aria-label="Resize inbox"></ui-resizable-handle>
273
+ <ui-resizable-panel min-size="15">
274
+ <h3>Quarterly report</h3>
275
+ <span data-slot="hint">From Hollis Grant</span>
276
+ </ui-resizable-panel>
277
+ </ui-resizable>
278
+ `
279
+ }
280
+
281
+ export { mount }
282
+ ```
283
+
284
+ The three mail panels start at 25, 35 and 40 percent. Resize any of them.
285
+
286
+ ## Controlled
287
+
288
+ Set the element's `layout` property, and listen for `layoutchange` for the reason. The layout is one percentage per panel, in order, adding up to 100. Every change carries a [reason](#reasons), like `drag`, `step-key` or `collapse`, and `event.preventDefault()` keeps the current layout. Setting `layout` fires `layoutchange` too, with the `imperative` reason.
289
+
290
+ ```ts title="controlled.ts"
291
+ import "@ui-sdk/web/resizable"
292
+ import { log } from "./log"
293
+
294
+ const format = (layout: number[]) => layout.map(Math.round).join(" / ")
295
+
296
+ function mount(root: HTMLElement) {
297
+ root.innerHTML = `
298
+ <div data-slot="stack">
299
+ <div data-slot="controls">
300
+ <button type="button" data-layout="50,50">Split Evenly</button>
301
+ <button type="button" data-layout="30,70">Reset</button>
302
+ </div>
303
+ <ui-resizable default-layout="30,70">
304
+ <ui-resizable-panel min-size="20">
305
+ <h3>Files</h3>
306
+ <ul>
307
+ <li>page.tsx</li>
308
+ <li>layout.tsx</li>
309
+ <li>globals.css</li>
310
+ </ul>
311
+ </ui-resizable-panel>
312
+ <ui-resizable-handle aria-label="Resize files"></ui-resizable-handle>
313
+ <ui-resizable-panel min-size="20">
314
+ <h3>page.tsx</h3>
315
+ <span data-slot="hint">Saved just now</span>
316
+ </ui-resizable-panel>
317
+ </ui-resizable>
318
+ </div>
319
+ `
320
+ const group = root.querySelector("ui-resizable")!
321
+ let layout = [30, 70]
322
+ group.addEventListener("layoutchange", (event) => {
323
+ const { value, reason } = event.detail
324
+ if (format(value) !== format(layout)) {
325
+ log(root, `${format(value)} (${reason})`)
326
+ }
327
+ layout = value
328
+ })
329
+ root
330
+ .querySelectorAll<HTMLButtonElement>("[data-layout]")
331
+ .forEach((button) => {
332
+ button.addEventListener(
333
+ "click",
334
+ () => (group.layout = button.dataset.layout!.split(",").map(Number))
335
+ )
336
+ })
337
+ }
338
+
339
+ export { mount }
340
+ ```
341
+
342
+ Resize Files to log the layout and its reason. Split Evenly and Reset set the layout from outside.
343
+
344
+ ## Saving on Complete
345
+
346
+ `layoutchange` fires on every frame of a drag. `layoutcommit` fires once, when the interaction that changed the layout ends: the pointer lifts, the key comes up, or a panel collapses. Save there.
347
+
348
+ ```ts title="complete.ts"
349
+ import "@ui-sdk/web/resizable"
350
+ import { log } from "./log"
351
+
352
+ function mount(root: HTMLElement) {
353
+ root.innerHTML = `
354
+ <ui-resizable>
355
+ <ui-resizable-panel default-size="40" min-size="20">
356
+ <h3>Files</h3>
357
+ <ul>
358
+ <li>page.tsx</li>
359
+ <li>layout.tsx</li>
360
+ <li>globals.css</li>
361
+ </ul>
362
+ </ui-resizable-panel>
363
+ <ui-resizable-handle aria-label="Resize files"></ui-resizable-handle>
364
+ <ui-resizable-panel min-size="20">
365
+ <h3>page.tsx</h3>
366
+ <span data-slot="hint">Saved just now</span>
367
+ </ui-resizable-panel>
368
+ </ui-resizable>
369
+ `
370
+ root
371
+ .querySelector("ui-resizable")!
372
+ .addEventListener("layoutcommit", (event) => {
373
+ log(
374
+ root,
375
+ `Saved ${event.detail.value.map(Math.round).join(" / ")} (${event.detail.reason})`
376
+ )
377
+ })
378
+ }
379
+
380
+ export { mount }
381
+ ```
382
+
383
+ Drag the handle and release it, or press an arrow key. The console logs the layout once, when you let go.
384
+
385
+ ## Persistence
386
+
387
+ `auto-save-id` saves the layout in `localStorage` when an interaction completes and restores it when the group attaches in the browser. Server markup starts with the default sizes. Each set of panels keeps its own layout, so a panel that comes and goes gets its sizes back. Give panels an `id` so the saved layout survives changes elsewhere on the page.
388
+
389
+ It's the same idea as [Preferences](./preferences.md), which saves one choice between visits, like a theme. Resizable saves the whole layout, under its `auto-save-id`.
390
+
391
+ ```ts title="persistence.ts"
392
+ import "@ui-sdk/web/resizable"
393
+
394
+ function mount(root: HTMLElement) {
395
+ root.innerHTML = `
396
+ <ui-resizable auto-save-id="docs-persistence">
397
+ <ui-resizable-panel id="docs-sidebar" default-size="30" min-size="20">
398
+ <h3>Outline</h3>
399
+ <ul>
400
+ <li>Introduction</li>
401
+ <li>Installation</li>
402
+ <li>Usage</li>
403
+ </ul>
404
+ </ui-resizable-panel>
405
+ <ui-resizable-handle aria-label="Resize outline"><div></div></ui-resizable-handle>
406
+ <ui-resizable-panel id="docs-content" min-size="30">
407
+ <h3>Introduction</h3>
408
+ <span data-slot="hint">Last edited by Wren Takahashi</span>
409
+ </ui-resizable-panel>
410
+ </ui-resizable>
411
+ `
412
+ }
413
+
414
+ export { mount }
415
+ ```
416
+
417
+ Resize Outline, then reload this page to restore its saved width.
418
+
419
+ ## Storage
420
+
421
+ The `storage` property takes anything with `getItem` and `setItem`, like `sessionStorage` or a cookie. That's the browser's storage shape, not the [storage](./preferences.md#save-the-value) helpers Preferences takes, such as `createLocalStorage`, which each keep one value. Choose between local storage, session storage and a cookie as you would for a preference, under [Remember the Choice](../core.md#remember-the-choice).
422
+
423
+ This example keeps the layout in `sessionStorage`, for the tab's session. It sets `storage` before the group is in the page, so the group restores from it when it attaches:
424
+
425
+ ```ts title="storage.ts"
426
+ import "@ui-sdk/web/resizable"
427
+ import type { ResizableStorage } from "@ui-sdk/web"
428
+
429
+ const session: ResizableStorage = {
430
+ getItem: (key) => sessionStorage.getItem(key),
431
+ setItem: (key, value) => sessionStorage.setItem(key, value),
432
+ }
433
+
434
+ function mount(root: HTMLElement) {
435
+ const group = document.createElement("ui-resizable")
436
+ group.storage = session
437
+ group.setAttribute("auto-save-id", "docs-storage")
438
+ group.innerHTML = `
439
+ <ui-resizable-panel id="session-chats" default-size="35" min-size="20">
440
+ <h3>Messages</h3>
441
+ <ul>
442
+ <li>Inès Moreau</li>
443
+ <li>Kofi Mensah</li>
444
+ <li>Wren Takahashi</li>
445
+ </ul>
446
+ </ui-resizable-panel>
447
+ <ui-resizable-handle aria-label="Resize messages"></ui-resizable-handle>
448
+ <ui-resizable-panel id="session-thread" min-size="20">
449
+ <h3>Inès Moreau</h3>
450
+ <span data-slot="hint">Can we move the review to Friday?</span>
451
+ </ui-resizable-panel>
452
+ `
453
+ root.replaceChildren(group)
454
+ }
455
+
456
+ export { mount }
457
+ ```
458
+
459
+ Resize Messages, then reload. The width comes back in this tab, but not in a new one.
460
+
461
+ A server can't read `localStorage`, so it renders each panel's `default-size` and the saved layout arrives when the elements attach. To render the saved layout on the first paint, keep it in a cookie and write the sizes into each panel's `default-size`. Here your server reads them from the request's `Cookie` header. It imports `resizableStorageKey`, which names the cookie:
462
+
463
+ ```ts title="server.ts"
464
+ import { resizableStorageKey } from "@ui-sdk/core/resizable"
465
+
466
+ function editor(cookie: string | null) {
467
+ const value = cookie?.match(
468
+ new RegExp(`(?:^|; )${resizableStorageKey("editor")}=([^;]*)`)
469
+ )?.[1]
470
+ const saved = value ? JSON.parse(decodeURIComponent(value)) : {}
471
+ const [sidebar = 25, main = 75] = saved["sidebar,main"] ?? []
472
+ return `<ui-resizable auto-save-id="editor">
473
+ <ui-resizable-panel id="sidebar" default-size="${sidebar}"></ui-resizable-panel>
474
+ <ui-resizable-handle aria-label="Resize sidebar"></ui-resizable-handle>
475
+ <ui-resizable-panel id="main" default-size="${main}"></ui-resizable-panel>
476
+ </ui-resizable>`
477
+ }
478
+ ```
479
+
480
+ ```ts title="page.ts"
481
+ import "@ui-sdk/web/resizable"
482
+ import type { ResizableStorage } from "@ui-sdk/web"
483
+
484
+ const cookieStorage: ResizableStorage = {
485
+ getItem: (key) => {
486
+ const value = document.cookie.match(
487
+ new RegExp(`(?:^|; )${key}=([^;]*)`)
488
+ )?.[1]
489
+ return value === undefined ? null : decodeURIComponent(value)
490
+ },
491
+ setItem: (key, value) => {
492
+ document.cookie = `${key}=${encodeURIComponent(value)}; path=/; max-age=31536000`
493
+ },
494
+ }
495
+
496
+ document.querySelector("ui-resizable")!.storage = cookieStorage
497
+ ```
498
+
499
+ ## Controller
500
+
501
+ The element's `api` collapses, expands and resizes panels from anywhere, by id or index, and reads the layout with `getLayout()`. Changes it makes report the `imperative` reason.
502
+
503
+ ```ts title="controller.ts"
504
+ import "@ui-sdk/web/resizable"
505
+ import { log } from "./log"
506
+
507
+ function mount(root: HTMLElement) {
508
+ root.innerHTML = `
509
+ <div data-slot="stack">
510
+ <div data-slot="controls">
511
+ <button type="button" data-action="collapse">Collapse</button>
512
+ <button type="button" data-action="expand">Expand</button>
513
+ <button type="button" data-action="resize">240px</button>
514
+ <button type="button" data-action="read">Read</button>
515
+ </div>
516
+ <ui-resizable>
517
+ <ui-resizable-panel id="controller-sidebar" default-size="30" min-size="20" collapsible>
518
+ <h3>Files</h3>
519
+ <ul>
520
+ <li>page.tsx</li>
521
+ <li>layout.tsx</li>
522
+ <li>globals.css</li>
523
+ </ul>
524
+ </ui-resizable-panel>
525
+ <ui-resizable-handle aria-label="Resize files"></ui-resizable-handle>
526
+ <ui-resizable-panel min-size="30">
527
+ <h3>page.tsx</h3>
528
+ <span data-slot="hint">Saved just now</span>
529
+ </ui-resizable-panel>
530
+ </ui-resizable>
531
+ </div>
532
+ `
533
+ const editor = root.querySelector("ui-resizable")!.api
534
+ const actions: Record<string, () => void> = {
535
+ collapse: () => editor.collapse("controller-sidebar"),
536
+ expand: () => editor.expand("controller-sidebar"),
537
+ resize: () => editor.resize("controller-sidebar", "240px"),
538
+ read: () =>
539
+ log(
540
+ root,
541
+ `Layout ${editor.getLayout().map(Math.round).join(" / ")}${editor.isCollapsed("controller-sidebar") ? ", collapsed" : ""}`
542
+ ),
543
+ }
544
+ root
545
+ .querySelectorAll<HTMLButtonElement>("[data-action]")
546
+ .forEach((button) => {
547
+ button.addEventListener("click", () => actions[button.dataset.action!]())
548
+ })
549
+ }
550
+
551
+ export { mount }
552
+ ```
553
+
554
+ Use Collapse, Expand and 240px to move Files from outside the group, and Read to log its sizes.
555
+
556
+ ## Step Size
557
+
558
+ `step` sets how far an arrow key moves a handle, 1% by default, and `large-step` how far Shift with an arrow moves it, 10% by default.
559
+
560
+ ```ts title="keyboard.ts"
561
+ import "@ui-sdk/web/resizable"
562
+
563
+ function mount(root: HTMLElement) {
564
+ root.innerHTML = `
565
+ <ui-resizable step="5" large-step="25">
566
+ <ui-resizable-panel default-size="50" min-size="20">
567
+ <h3>Original</h3>
568
+ <span data-slot="hint">v1.2.0</span>
569
+ </ui-resizable-panel>
570
+ <ui-resizable-handle aria-label="Resize original"></ui-resizable-handle>
571
+ <ui-resizable-panel default-size="50" min-size="20">
572
+ <h3>Changes</h3>
573
+ <span data-slot="hint">v1.3.0</span>
574
+ </ui-resizable-panel>
575
+ </ui-resizable>
576
+ `
577
+ }
578
+
579
+ export { mount }
580
+ ```
581
+
582
+ Focus the handle between Original and Changes. The arrow keys move it 5%, Shift with an arrow 25%, and Home and End as far as it goes.
583
+
584
+ ## Disabled
585
+
586
+ `disabled` on a handle fixes it in place. On the group it fixes every handle. Disabled handles leave the tab order, and their panels keep their sizes. A disabled `<fieldset>` around the group fixes every handle too.
587
+
588
+ ```ts title="disabled.ts"
589
+ import "@ui-sdk/web/checkbox"
590
+ import "@ui-sdk/web/resizable"
591
+ import { Check, createElement } from "lucide"
592
+
593
+ function mount(root: HTMLElement) {
594
+ root.innerHTML = `
595
+ <div data-slot="stack">
596
+ <div data-slot="controls">
597
+ <label data-slot="label">
598
+ <ui-checkbox>
599
+ <ui-checkbox-indicator>
600
+ ${createElement(Check, { "aria-hidden": "true" }).outerHTML}
601
+ </ui-checkbox-indicator>
602
+ </ui-checkbox>
603
+ Lock layout
604
+ </label>
605
+ </div>
606
+ <ui-resizable>
607
+ <ui-resizable-panel min-size="15">
608
+ <h3>Pinned</h3>
609
+ <span data-slot="hint">2 notes</span>
610
+ </ui-resizable-panel>
611
+ <ui-resizable-handle disabled aria-label="Resize pinned"></ui-resizable-handle>
612
+ <ui-resizable-panel min-size="15">
613
+ <h3>Inbox</h3>
614
+ <span data-slot="hint">3 unread</span>
615
+ </ui-resizable-panel>
616
+ <ui-resizable-handle aria-label="Resize inbox"></ui-resizable-handle>
617
+ <ui-resizable-panel min-size="15">
618
+ <h3>Message</h3>
619
+ <span data-slot="hint">From Kofi Mensah</span>
620
+ </ui-resizable-panel>
621
+ </ui-resizable>
622
+ </div>
623
+ `
624
+ const group = root.querySelector("ui-resizable")!
625
+ root
626
+ .querySelector("ui-checkbox")!
627
+ .addEventListener("checkedchange", (event) => {
628
+ group.toggleAttribute("disabled", event.detail.value === true)
629
+ })
630
+ }
631
+
632
+ export { mount }
633
+ ```
634
+
635
+ The handle after Pinned stays fixed. Drag the one after Inbox, then check Lock layout to fix it too.
636
+
637
+ ## Custom Rendering
638
+
639
+ Elements have no render functions. Style each part from its data attributes, like a panel's `data-collapsed` or a handle's `data-dragging`, and read sizes from `--resizable-panel-size` or `layoutchange`, as this example does. See [Parts and Composition](../parts-and-composition.md) for choosing the elements parts bind.
640
+
641
+ ```ts title="render.ts"
642
+ import "@ui-sdk/web/resizable"
643
+
644
+ function mount(root: HTMLElement) {
645
+ root.innerHTML = `
646
+ <ui-resizable>
647
+ <ui-resizable-panel default-size="35" min-size="20" collapsible>
648
+ <h3>Files</h3>
649
+ <span data-slot="hint">35%</span>
650
+ </ui-resizable-panel>
651
+ <ui-resizable-handle aria-label="Resize files"></ui-resizable-handle>
652
+ <ui-resizable-panel min-size="30">
653
+ <h3>Editor</h3>
654
+ <span data-slot="hint">65%</span>
655
+ </ui-resizable-panel>
656
+ </ui-resizable>
657
+ `
658
+ const [files, editor] = root.querySelectorAll("[data-slot=hint]")
659
+ root
660
+ .querySelector("ui-resizable")!
661
+ .addEventListener("layoutchange", (event) => {
662
+ const [filesSize, editorSize] = event.detail.value
663
+ files.textContent =
664
+ filesSize === 0 ? "Collapsed" : `${Math.round(filesSize)}%`
665
+ editor.textContent = `${Math.round(editorSize)}%`
666
+ })
667
+ }
668
+
669
+ export { mount }
670
+ ```
671
+
672
+ Resize Files to see both panels report their size, or collapse it to see Collapsed.
673
+
674
+ The primitive writes drag sizes directly to panel styles. A `layoutchange` listener also runs on every frame of the drag.
675
+
676
+ ## Styling
677
+
678
+ Parts are unstyled, apart from the layout they need: the group is a flex row or column, panels take their size as a flex basis, and handles don't shrink and take `touch-action: none`. Give the group a size, the handle a width or height and a background, and style it with `data-hovering`, `data-dragging` and `:focus-visible`. While a handle is hovered or dragged, its cursor shows over the whole page, and points the only way it can go at a limit.
679
+
680
+ Each part has a `data-slot`, such as `resizable-handle`, and its state attributes are listed under [Data Attributes](#data-attributes).
681
+
682
+ ### `<ui-resizable-panel>`
683
+ - `--resizable-panel-size`: The panel's share of the group, as a percentage. Written on every frame of a drag, without a render.
684
+
685
+ ## Data Attributes
686
+
687
+ ### `<ui-resizable>`
688
+ `[data-slot="resizable"]`
689
+
690
+ - `data-orientation` (`horizontal`, `vertical`): The group's direction, on every part. A handle's own `aria-orientation` is the other one, since it runs across the group.
691
+ - `data-disabled`: Present when the group, or this handle, is disabled.
692
+ - `data-dragging`: Present while a handle of the group is being dragged.
693
+
694
+ ### `<ui-resizable-panel>`
695
+ `[data-slot="resizable-panel"]`
696
+
697
+ - `data-orientation` (`horizontal`, `vertical`): The group's direction, on every part. A handle's own `aria-orientation` is the other one, since it runs across the group.
698
+ - `data-collapsed`: Present while a collapsible panel is collapsed.
699
+
700
+ ### `<ui-resizable-handle>`
701
+ `[data-slot="resizable-handle"]`
702
+
703
+ - `data-orientation` (`horizontal`, `vertical`): The group's direction, on every part. A handle's own `aria-orientation` is the other one, since it runs across the group.
704
+ - `data-disabled`: Present when the group, or this handle, is disabled.
705
+ - `data-dragging`: Present while this handle is being dragged.
706
+ - `data-hovering`: Present while the pointer is over the handle or within its hit area, which reaches past the handle itself.
707
+
708
+ ## API Reference
709
+
710
+ Props are attributes in kebab case, like `default-size` and `auto-save-id`. A layout is written as `"30,70"`. `storage` and `controller` are properties. Callbacks are DOM events.
711
+
712
+ ### Resizable
713
+
714
+ - `layout?` (`number[]`): Each panel's size in percent, in panel order, like `[25, 75]`. Pass it to control the group.
715
+ - `defaultLayout?` (`number[]`): The layout at first, when uncontrolled. Panels' own `defaultSize` is what a server renders, so prefer that with server rendering.
716
+ - `layoutchange event`: Runs while the layout changes: on every frame of a drag and every key. `details.cancel()` keeps the layout.
717
+ - `layoutcommit event`: Runs once an interaction that changed the layout ends: the pointer lifts, the key comes up, or a panel collapses. For saving.
718
+ - `orientation?` (`"horizontal" | "vertical"`): The direction panels are laid out in. Horizontal panels sit side by side, vertical ones stack.
719
+ - `disabled?` (`boolean`): Stops every handle: no drags, no keys, and handles leave the tab order.
720
+ - `step?` (`number`): How far an arrow key moves a handle, in percent.
721
+ - `largeStep?` (`number`): How far Shift with an arrow key moves a handle, in percent.
722
+ - `autoSaveId?` (`string`): Saves the layout when an interaction completes and restores it on the next visit, under this key. Give panels an `id` so it survives changes elsewhere on the page.
723
+ - `storage?` (`ResizableStorage`): Where `autoSaveId` saves: anything with `getItem` and `setItem`, like a cookie store a server can read.
724
+ - `controller?` (`object`): Resizes the group from anywhere. Create one with `createResizableController()`.
725
+ - `debug?` (`boolean`): Logs every state change with its reason to the console, in development builds.
726
+
727
+ ### ResizablePanel
728
+
729
+ - `id?` (`string`): Identifies the panel for the controller, `aria-controls` and saved layouts. It's the element's id. Generated when left out.
730
+ - `defaultSize?` (`ResizableSize`): Where the panel starts, in percent or with a unit, like `30` or `"240px"`. Without one, panels share what's left evenly. A server renders this size.
731
+ - `minSize?` (`ResizableSize`): The smallest the panel gets while open.
732
+ - `maxSize?` (`ResizableSize`): The largest the panel gets.
733
+ - `collapsible?` (`boolean`): Lets the panel collapse below its minimum to `collapsedSize`: by dragging past half the way there, with Enter or a double-click on its handle, or through the controller.
734
+ - `collapsedSize?` (`ResizableSize`): The size a collapsible panel collapses to. At 0, its content leaves the tab order and the accessibility tree.
735
+
736
+ ### ResizableHandle
737
+
738
+ - `disabled?` (`boolean`): Stops this handle: no drags and no keys, and it leaves the tab order.
739
+
740
+ ### State
741
+
742
+ The same state shows as data attributes on each element.
743
+
744
+ - `orientation` (`"horizontal" | "vertical"`): The direction panels are laid out in.
745
+ - `disabled` (`boolean`): Whether the group is disabled.
746
+ - `dragging` (`boolean`): Whether a handle is being dragged.
747
+ - `layout` (`number[]`): Each panel's size in percent. Reading it renders on every frame of a drag.
748
+
749
+ Panels:
750
+
751
+ - `orientation` (`"horizontal" | "vertical"`): The direction panels are laid out in.
752
+ - `size` (`number`): The panel's size in percent. Reading it renders on every frame of a drag.
753
+ - `collapsed` (`boolean`): Whether the panel is down at its `collapsedSize`, below its minimum.
754
+ - `collapsible` (`boolean`): Whether the panel can collapse.
755
+
756
+ Handles:
757
+
758
+ - `orientation` (`"horizontal" | "vertical"`): The direction panels are laid out in. The separator itself runs across it.
759
+ - `disabled` (`boolean`): Whether the handle can't move.
760
+ - `dragging` (`boolean`): Whether the handle is being dragged.
761
+ - `hovering` (`boolean`): Whether the pointer is over the handle or within its hit area.
762
+
763
+ ### Reasons
764
+
765
+ `event.detail.reason` says why the layout changed.
766
+
767
+ - `drag` (`PointerEvent`): A slider thumb or a resize handle was dragged, or an item was dragged to a new place in a list.
768
+ - `step-key` (`KeyboardEvent`): Arrow, Page Up, Page Down, Home or End stepped a slider or a number input.
769
+ - `collapse` (`MouseEvent | KeyboardEvent`): Enter or a double-click on a resize handle collapsed the panel beside it, or restored it.
770
+ - `resize` (`none`): The group changed size, so panels with sizes in pixels moved to stay within their bounds.
771
+ - `imperative` (`none`): A controller or `api` call, or a property set on a web component.
772
+
773
+ ### Controller
774
+
775
+ The element's `api` property has the same methods. The `layout` property reads and sets the layout.
776
+
777
+ Write methods take an optional `{ reason, event }`, fire the change event like a drag, and return `false` when nothing changed or the change was canceled.
778
+
779
+ - `getLayout()` (`() => number[]`): Each panel's size in percent, in order.
780
+ - `setLayout(layout, options?)` (`(layout: number[], options?: ResizableChangeOptions | undefined) => boolean`): Sets every panel's size at once, in percent. It's fitted to the panels' bounds and adds up to 100. Returns whether anything changed.
781
+ - `collapse(panel, options?)` (`(panel: string | number, options?: ResizableChangeOptions | undefined) => boolean`): Collapses a collapsible panel, by its id or its index. Returns whether it collapsed.
782
+ - `expand(panel, options?)` (`(panel: string | number, options?: ResizableChangeOptions | undefined) => boolean`): Expands a collapsed panel to the size it had before it collapsed, or its minimum. Returns whether it expanded.
783
+ - `resize(panel, size, options?)` (`(panel: string | number, size: ResizableSize, options?: ResizableChangeOptions | undefined) => boolean`): Resizes one panel, by its id or its index, like `resize("sidebar", "240px")`. Its neighbours give or take the difference.
784
+ - `isCollapsed(panel)` (`(panel: string | number) => boolean`): Whether a panel is collapsed.
785
+
786
+ ### Events
787
+
788
+ Events fire on their own element and don't bubble, with the layout in `event.detail.value` and the `reason`, `event` and `source` beside it. Calling `preventDefault()` on `layoutchange` cancels the change.
789
+
790
+ | Member | On | Description |
791
+ | ---------------------------- | -------------- | ----------------------------------------------------------- |
792
+ | `layout` property, attribute | `ui-resizable` | The layout. The attribute sets it as text, like `"30,70"` |
793
+ | `api` property | `ui-resizable` | The [controller](#controller) |
794
+ | `layoutchange` event | `ui-resizable` | `detail: { value, reason, event, source }`, on every change |
795
+ | `layoutcommit` event | `ui-resizable` | `detail: { value, reason, event, source }`, once it ends |
796
+
797
+ ## Accessibility
798
+
799
+ Handles follow the [WAI-ARIA window splitter pattern](https://www.w3.org/WAI/ARIA/apg/patterns/windowsplitter/). Each is a focusable `separator` whose `aria-valuenow` is the size of the panel before it, with `aria-valuemin` and `aria-valuemax` as far as the panels allow, `aria-controls` pointing at that panel, and `aria-orientation` running across the group. Name each handle with `aria-label`.
800
+
801
+ ### Keyboard
802
+
803
+ Focus a handle and press the arrow keys along the group's axis to move it by `step`, or with Shift by `large-step`. Home and End move it as far as the panels allow, and Enter collapses or restores a collapsible panel beside it. A panel at its minimum passes the rest of a move on to the next one. Disabled handles leave the tab order.
804
+
805
+ ### Tested Behavior
806
+
807
+ Every line below is an automated test.
808
+
809
+ **Keyboard**
810
+
811
+ - Starts at each panel's default size, and panels without one share the rest.
812
+ - ArrowRight grows the panel before the handle by one step, and ArrowLeft shrinks it.
813
+ - Shift with an arrow key moves by the large step.
814
+ - Arrows across the group's axis do nothing.
815
+ - ArrowDown and ArrowUp move a vertical group's handle.
816
+ - Home collapses a collapsible panel, and End grows it to its maximum.
817
+ - Home stops at the minimum of a panel that can't collapse.
818
+ - Enter collapses the panel before the handle, and restores its size.
819
+ - Enter collapses the panel after the handle when only that one can collapse.
820
+ - One step past a collapsible panel's minimum collapses it.
821
+ - A panel at its minimum passes the rest on to the next one.
822
+ - End stops where the panels' bounds meet.
823
+ - Keys pressed without waiting all land.
824
+ - Keys complete the change once they come up.
825
+ - Step and large step set how far keys move.
826
+ - A canceled change keeps the layout.
827
+ - A controlled group follows its layout.
828
+ - A controlled group that ignores a change completes nothing. React and Vue only.
829
+ - A disabled handle stops a move from the next one, so the panels past it keep their sizes.
830
+ - DefaultLayout sets where the panels start.
831
+ - A disabled group's handles leave the tab order and ignore drags.
832
+
833
+ **Pointer**
834
+
835
+ - Dragging a handle moves it with the pointer.
836
+ - A drag reports its moves with the drag reason and completes once.
837
+ - Dragging past a disabled handle moves nothing beyond it.
838
+ - Dragging a vertical group's handle moves it up and down.
839
+ - Dragging past half a collapsible panel's minimum collapses it, and back opens it.
840
+ - A drag stops at the panels' bounds.
841
+ - A double-click on a handle collapses its panel, and another restores it.
842
+ - A press just beside the thin handle drags it.
843
+ - A press farther from the handle doesn't drag.
844
+ - Where two handles meet, one drag moves both.
845
+ - A drag shows the axis cursor over the whole page until it ends.
846
+
847
+ **Controller**
848
+
849
+ - Collapses and expands a panel, with the imperative reason.
850
+ - Resizes a panel to a size in pixels.
851
+
852
+ **Container**
853
+
854
+ - A panel with a minimum in pixels keeps it as the group shrinks.
855
+ - Panels keep their share as the group grows.
856
+
857
+ **Pages around a group**
858
+
859
+ - A layer above a handle keeps its presses.
860
+ - A press beside a handle doesn't click what's under it.
861
+ - Only the main button drags.
862
+ - An iframe under the pointer doesn't stop a drag.
863
+ - At a limit, the cursor points the only way a handle can go.
864
+ - A saved layout is there on the first paint.
865
+
866
+ Runs in React, Vue and web components.