@remix-run/ui 0.3.0 → 0.5.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 (434) hide show
  1. package/README.md +116 -157
  2. package/dist/accordion/index.d.ts +46 -0
  3. package/dist/accordion/index.js +142 -0
  4. package/dist/accordion/index.js.map +1 -0
  5. package/dist/accordion/primitives.d.ts +104 -0
  6. package/dist/accordion/primitives.js +312 -0
  7. package/dist/accordion/primitives.js.map +1 -0
  8. package/dist/{components/anchor/anchor.js → anchor/index.js} +1 -1
  9. package/dist/anchor/index.js.map +1 -0
  10. package/dist/animation/animate-layout-mixin.js +1 -1
  11. package/dist/animation/animate-layout-mixin.js.map +1 -1
  12. package/dist/animation/animate-mixins.js +2 -2
  13. package/dist/animation/animate-mixins.js.map +1 -1
  14. package/dist/animation/demos/color-interpolation.js +1 -1
  15. package/dist/animation/demos/color-interpolation.js.map +1 -1
  16. package/dist/animation/demos/drag-release.d.ts +1 -1
  17. package/dist/animation/demos/hold-to-confirm.d.ts +3 -3
  18. package/dist/animation/demos/material-ripple.js +1 -3
  19. package/dist/animation/demos/material-ripple.js.map +1 -1
  20. package/dist/animation/demos/reordering.js +9 -6
  21. package/dist/animation/demos/reordering.js.map +1 -1
  22. package/dist/animation/index.js +4 -4
  23. package/dist/animation/spring.js.map +1 -1
  24. package/dist/{components/breadcrumbs/breadcrumbs.js → breadcrumbs/index.js} +19 -19
  25. package/dist/breadcrumbs/index.js.map +1 -0
  26. package/dist/button/index.d.ts +15 -0
  27. package/dist/button/index.js +128 -0
  28. package/dist/button/index.js.map +1 -0
  29. package/dist/checkbox/index.d.ts +14 -0
  30. package/dist/checkbox/index.js +127 -0
  31. package/dist/checkbox/index.js.map +1 -0
  32. package/dist/combobox/index.d.ts +21 -0
  33. package/dist/combobox/index.js +58 -0
  34. package/dist/combobox/index.js.map +1 -0
  35. package/dist/{components/combobox/combobox.d.ts → combobox/primitives.d.ts} +4 -8
  36. package/dist/{components/combobox/combobox.js → combobox/primitives.js} +8 -61
  37. package/dist/combobox/primitives.js.map +1 -0
  38. package/dist/dev/refresh.d.ts +1 -0
  39. package/dist/dev/refresh.js +2 -0
  40. package/dist/dev/refresh.js.map +1 -0
  41. package/dist/index.d.ts +1 -1
  42. package/dist/index.js +14 -14
  43. package/dist/input/index.d.ts +13 -0
  44. package/dist/input/index.js +121 -0
  45. package/dist/input/index.js.map +1 -0
  46. package/dist/jsx-runtime.js +2 -2
  47. package/dist/listbox/flash-attribute.js.map +1 -0
  48. package/dist/{components/listbox/listbox.d.ts → listbox/index.d.ts} +2 -6
  49. package/dist/{components/listbox/listbox.js → listbox/index.js} +4 -82
  50. package/dist/listbox/index.js.map +1 -0
  51. package/dist/menu/hover-aim.js.map +1 -0
  52. package/dist/menu/index.d.ts +42 -0
  53. package/dist/menu/index.js +250 -0
  54. package/dist/menu/index.js.map +1 -0
  55. package/dist/{components/menu/menu.d.ts → menu/primitives.d.ts} +4 -33
  56. package/dist/{components/menu/menu.js → menu/primitives.js} +98 -315
  57. package/dist/menu/primitives.js.map +1 -0
  58. package/dist/{components/popover/popover.d.ts → popover/index.d.ts} +2 -4
  59. package/dist/{components/popover/popover.js → popover/index.js} +5 -48
  60. package/dist/popover/index.js.map +1 -0
  61. package/dist/{interactions/outside-click/outside-click-mixin.js → popover/outside-click.js} +1 -1
  62. package/dist/popover/outside-click.js.map +1 -0
  63. package/dist/popover/scroll-lock.d.ts +1 -0
  64. package/dist/{utils → popover}/scroll-lock.js +0 -18
  65. package/dist/popover/scroll-lock.js.map +1 -0
  66. package/dist/radio/index.d.ts +12 -0
  67. package/dist/radio/index.js +77 -0
  68. package/dist/radio/index.js.map +1 -0
  69. package/dist/runtime/client-entry-boundary.d.ts +14 -0
  70. package/dist/runtime/client-entry-boundary.js +29 -0
  71. package/dist/runtime/client-entry-boundary.js.map +1 -0
  72. package/dist/runtime/component.d.ts +19 -4
  73. package/dist/runtime/component.js +39 -9
  74. package/dist/runtime/component.js.map +1 -1
  75. package/dist/runtime/core/attributes.js +36 -3
  76. package/dist/runtime/core/attributes.js.map +1 -1
  77. package/dist/runtime/core/children.d.ts +2 -0
  78. package/dist/runtime/core/children.js +26 -2
  79. package/dist/runtime/core/children.js.map +1 -1
  80. package/dist/runtime/core/props.js +2 -2
  81. package/dist/runtime/core/vnode.d.ts +3 -3
  82. package/dist/runtime/core/vnode.js +22 -1
  83. package/dist/runtime/core/vnode.js.map +1 -1
  84. package/dist/runtime/create-element.d.ts +2 -2
  85. package/dist/runtime/create-element.js +3 -2
  86. package/dist/runtime/create-element.js.map +1 -1
  87. package/dist/runtime/diff-dom.js +294 -219
  88. package/dist/runtime/diff-dom.js.map +1 -1
  89. package/dist/runtime/diff-props.js +3 -3
  90. package/dist/runtime/dom.d.ts +12 -0
  91. package/dist/runtime/element-function.d.ts +3 -0
  92. package/dist/runtime/element-function.js +2 -0
  93. package/dist/runtime/element-function.js.map +1 -0
  94. package/dist/runtime/form-navigation.d.ts +25 -0
  95. package/dist/runtime/form-navigation.js +132 -0
  96. package/dist/runtime/form-navigation.js.map +1 -0
  97. package/dist/runtime/frame-resolution.d.ts +5 -0
  98. package/dist/runtime/frame-resolution.js +10 -0
  99. package/dist/runtime/frame-resolution.js.map +1 -0
  100. package/dist/runtime/frame.d.ts +58 -15
  101. package/dist/runtime/frame.js +367 -114
  102. package/dist/runtime/frame.js.map +1 -1
  103. package/dist/runtime/jsx.d.ts +1 -1
  104. package/dist/runtime/jsx.js +1 -1
  105. package/dist/runtime/jsx.js.map +1 -1
  106. package/dist/runtime/key.d.ts +1 -0
  107. package/dist/runtime/key.js +2 -0
  108. package/dist/runtime/key.js.map +1 -0
  109. package/dist/runtime/mixins/attrs-mixin.js +2 -2
  110. package/dist/runtime/mixins/link-mixin.js +4 -3
  111. package/dist/runtime/mixins/link-mixin.js.map +1 -1
  112. package/dist/runtime/mixins/mixin.d.ts +15 -10
  113. package/dist/runtime/mixins/mixin.js +4 -4
  114. package/dist/runtime/mixins/mixin.js.map +1 -1
  115. package/dist/runtime/mixins/on-mixin.js +1 -1
  116. package/dist/runtime/mixins/ref-mixin.js +1 -1
  117. package/dist/runtime/navigation.d.ts +4 -1
  118. package/dist/runtime/navigation.js +157 -32
  119. package/dist/runtime/navigation.js.map +1 -1
  120. package/dist/runtime/reconcile.d.ts +11 -10
  121. package/dist/runtime/reconcile.js +557 -423
  122. package/dist/runtime/reconcile.js.map +1 -1
  123. package/dist/runtime/refresh.d.ts +28 -0
  124. package/dist/runtime/refresh.js +31 -0
  125. package/dist/runtime/refresh.js.map +1 -0
  126. package/dist/runtime/render.js +1 -1
  127. package/dist/runtime/render.js.map +1 -1
  128. package/dist/runtime/run.d.ts +3 -1
  129. package/dist/runtime/run.js +15 -7
  130. package/dist/runtime/run.js.map +1 -1
  131. package/dist/runtime/scheduler.js +8 -16
  132. package/dist/runtime/scheduler.js.map +1 -1
  133. package/dist/runtime/to-vnode.d.ts +2 -2
  134. package/dist/runtime/to-vnode.js +68 -20
  135. package/dist/runtime/to-vnode.js.map +1 -1
  136. package/dist/runtime/vdom.d.ts +4 -2
  137. package/dist/runtime/vdom.js +89 -41
  138. package/dist/runtime/vdom.js.map +1 -1
  139. package/dist/runtime/vnode.d.ts +138 -67
  140. package/dist/runtime/vnode.js +17 -12
  141. package/dist/runtime/vnode.js.map +1 -1
  142. package/dist/select/index.d.ts +19 -0
  143. package/dist/select/index.js +95 -0
  144. package/dist/select/index.js.map +1 -0
  145. package/dist/select/keydown.js.map +1 -0
  146. package/dist/{components/select/select.d.ts → select/primitives.d.ts} +5 -7
  147. package/dist/{components/select/select.js → select/primitives.js} +11 -63
  148. package/dist/select/primitives.js.map +1 -0
  149. package/dist/server/stream.js +22 -29
  150. package/dist/server/stream.js.map +1 -1
  151. package/dist/shared/focus-styles.d.ts +1 -0
  152. package/dist/shared/focus-styles.js +2 -0
  153. package/dist/shared/focus-styles.js.map +1 -0
  154. package/dist/shared/icons.d.ts +9 -0
  155. package/dist/shared/icons.js +42 -0
  156. package/dist/shared/icons.js.map +1 -0
  157. package/dist/shared/listbox-popover-styles.d.ts +6 -0
  158. package/dist/shared/listbox-popover-styles.js +137 -0
  159. package/dist/shared/listbox-popover-styles.js.map +1 -0
  160. package/dist/shared/style-values.d.ts +78 -0
  161. package/dist/shared/style-values.js +88 -0
  162. package/dist/shared/style-values.js.map +1 -0
  163. package/dist/{interactions/typeahead/typeahead-mixin.js → shared/typeahead.js} +1 -1
  164. package/dist/shared/typeahead.js.map +1 -0
  165. package/dist/shared/wait-for-css-transition.js.map +1 -0
  166. package/dist/shared/wait.js.map +1 -0
  167. package/dist/style/css-mixin.js +3 -3
  168. package/dist/style/index.js +2 -2
  169. package/dist/style/style.js +25 -6
  170. package/dist/style/style.js.map +1 -1
  171. package/dist/style/stylesheet.d.ts +0 -1
  172. package/dist/style/stylesheet.js +13 -54
  173. package/dist/style/stylesheet.js.map +1 -1
  174. package/dist/tabs/index.d.ts +32 -0
  175. package/dist/tabs/index.js +157 -0
  176. package/dist/tabs/index.js.map +1 -0
  177. package/dist/tabs/primitives.d.ts +57 -0
  178. package/dist/tabs/primitives.js +238 -0
  179. package/dist/tabs/primitives.js.map +1 -0
  180. package/dist/test.js +1 -1
  181. package/dist/toggle/index.d.ts +9 -0
  182. package/dist/toggle/index.js +108 -0
  183. package/dist/toggle/index.js.map +1 -0
  184. package/dist/toggle/primitives.d.ts +29 -0
  185. package/dist/toggle/primitives.js +127 -0
  186. package/dist/toggle/primitives.js.map +1 -0
  187. package/package.json +81 -49
  188. package/src/{components/accordion → accordion}/README.md +50 -14
  189. package/src/accordion/index.tsx +285 -0
  190. package/src/accordion/primitives.tsx +512 -0
  191. package/src/{components/anchor → anchor}/README.md +37 -2
  192. package/src/animation/animate-mixins.ts +3 -3
  193. package/src/animation/demos/color-interpolation.tsx +1 -1
  194. package/src/animation/demos/reordering.tsx +9 -6
  195. package/src/{components/breadcrumbs → breadcrumbs}/README.md +4 -4
  196. package/src/{components/breadcrumbs/breadcrumbs.tsx → breadcrumbs/index.tsx} +18 -18
  197. package/src/button/README.md +44 -0
  198. package/src/button/index.ts +168 -0
  199. package/src/checkbox/README.md +59 -0
  200. package/src/checkbox/index.ts +164 -0
  201. package/src/{components/combobox → combobox}/README.md +58 -9
  202. package/src/combobox/index.tsx +112 -0
  203. package/src/{components/combobox/combobox.tsx → combobox/primitives.tsx} +5 -91
  204. package/src/dev/refresh.ts +1 -0
  205. package/src/index.ts +1 -1
  206. package/src/input/README.md +52 -0
  207. package/src/input/index.ts +147 -0
  208. package/src/{components/listbox → listbox}/README.md +9 -41
  209. package/src/{components/listbox/listbox.ts → listbox/index.ts} +2 -87
  210. package/src/{components/menu → menu}/README.md +55 -14
  211. package/src/menu/index.tsx +354 -0
  212. package/src/{components/menu/menu.tsx → menu/primitives.tsx} +99 -413
  213. package/src/{components/popover → popover}/README.md +20 -39
  214. package/src/{components/popover/popover.ts → popover/index.ts} +3 -57
  215. package/src/{utils → popover}/scroll-lock.ts +0 -28
  216. package/src/radio/README.md +53 -0
  217. package/src/radio/index.ts +101 -0
  218. package/src/runtime/client-entry-boundary.ts +54 -0
  219. package/src/runtime/component.ts +65 -16
  220. package/src/runtime/core/attributes.ts +35 -1
  221. package/src/runtime/core/children.ts +24 -2
  222. package/src/runtime/core/vnode.ts +25 -4
  223. package/src/runtime/create-element.ts +6 -5
  224. package/src/runtime/demos/readme.demo.tsx +20 -18
  225. package/src/runtime/diff-dom.ts +358 -243
  226. package/src/runtime/dom.ts +331 -214
  227. package/src/runtime/element-function.ts +1 -0
  228. package/src/runtime/event-listeners.ts +1 -1
  229. package/src/runtime/form-navigation.ts +184 -0
  230. package/src/runtime/frame-resolution.ts +13 -0
  231. package/src/runtime/frame.ts +482 -124
  232. package/src/runtime/jsx.ts +3 -5
  233. package/src/runtime/key.ts +1 -0
  234. package/src/runtime/mixins/link-mixin.ts +1 -0
  235. package/src/runtime/mixins/mixin.ts +21 -18
  236. package/src/runtime/navigation.ts +204 -30
  237. package/src/runtime/reconcile.ts +769 -760
  238. package/src/runtime/refresh.ts +46 -0
  239. package/src/runtime/run.ts +12 -2
  240. package/src/runtime/scheduler.ts +9 -29
  241. package/src/runtime/to-vnode.ts +85 -23
  242. package/src/runtime/vdom.ts +91 -69
  243. package/src/runtime/vnode.ts +192 -88
  244. package/src/{components/select → select}/README.md +29 -19
  245. package/src/select/index.tsx +159 -0
  246. package/src/{components/select/select.tsx → select/primitives.tsx} +10 -98
  247. package/src/server/stream.ts +25 -31
  248. package/src/shared/focus-styles.ts +2 -0
  249. package/src/shared/icons.tsx +62 -0
  250. package/src/shared/listbox-popover-styles.ts +146 -0
  251. package/src/shared/style-values.ts +165 -0
  252. package/src/style/style.ts +25 -6
  253. package/src/style/stylesheet.ts +32 -57
  254. package/src/tabs/README.md +141 -0
  255. package/src/tabs/index.tsx +245 -0
  256. package/src/tabs/primitives.ts +365 -0
  257. package/src/test/README.md +151 -60
  258. package/src/toggle/README.md +56 -0
  259. package/src/toggle/index.tsx +136 -0
  260. package/src/toggle/primitives.ts +192 -0
  261. package/dist/animation/demos/animation.demo.d.ts +0 -5
  262. package/dist/animation/demos/animation.demo.js +0 -92
  263. package/dist/animation/demos/animation.demo.js.map +0 -1
  264. package/dist/animation/demos/spring.demo.d.ts +0 -6
  265. package/dist/animation/demos/spring.demo.js +0 -304
  266. package/dist/animation/demos/spring.demo.js.map +0 -1
  267. package/dist/components/accordion/accordion.d.ts +0 -92
  268. package/dist/components/accordion/accordion.js +0 -335
  269. package/dist/components/accordion/accordion.js.map +0 -1
  270. package/dist/components/accordion/demos/card.demo.d.ts +0 -7
  271. package/dist/components/accordion/demos/card.demo.js +0 -59
  272. package/dist/components/accordion/demos/card.demo.js.map +0 -1
  273. package/dist/components/accordion/demos/multiple.demo.d.ts +0 -7
  274. package/dist/components/accordion/demos/multiple.demo.js +0 -20
  275. package/dist/components/accordion/demos/multiple.demo.js.map +0 -1
  276. package/dist/components/accordion/demos/overview.demo.d.ts +0 -7
  277. package/dist/components/accordion/demos/overview.demo.js +0 -20
  278. package/dist/components/accordion/demos/overview.demo.js.map +0 -1
  279. package/dist/components/anchor/anchor.js.map +0 -1
  280. package/dist/components/breadcrumbs/basic.demo.d.ts +0 -6
  281. package/dist/components/breadcrumbs/basic.demo.js +0 -15
  282. package/dist/components/breadcrumbs/basic.demo.js.map +0 -1
  283. package/dist/components/breadcrumbs/breadcrumbs.js.map +0 -1
  284. package/dist/components/breadcrumbs/separator.demo.d.ts +0 -6
  285. package/dist/components/breadcrumbs/separator.demo.js +0 -15
  286. package/dist/components/breadcrumbs/separator.demo.js.map +0 -1
  287. package/dist/components/button/button.d.ts +0 -105
  288. package/dist/components/button/button.js +0 -207
  289. package/dist/components/button/button.js.map +0 -1
  290. package/dist/components/button/demos/aliases.demo.d.ts +0 -7
  291. package/dist/components/button/demos/aliases.demo.js +0 -19
  292. package/dist/components/button/demos/aliases.demo.js.map +0 -1
  293. package/dist/components/button/demos/basic.demo.d.ts +0 -7
  294. package/dist/components/button/demos/basic.demo.js +0 -20
  295. package/dist/components/button/demos/basic.demo.js.map +0 -1
  296. package/dist/components/button/demos/states.demo.d.ts +0 -7
  297. package/dist/components/button/demos/states.demo.js +0 -30
  298. package/dist/components/button/demos/states.demo.js.map +0 -1
  299. package/dist/components/combobox/combobox.js.map +0 -1
  300. package/dist/components/combobox/overview.demo.d.ts +0 -7
  301. package/dist/components/combobox/overview.demo.js +0 -154
  302. package/dist/components/combobox/overview.demo.js.map +0 -1
  303. package/dist/components/glyph/glyph.d.ts +0 -14
  304. package/dist/components/glyph/glyph.js +0 -65
  305. package/dist/components/glyph/glyph.js.map +0 -1
  306. package/dist/components/listbox/listbox.js.map +0 -1
  307. package/dist/components/listbox/overview.demo.d.ts +0 -7
  308. package/dist/components/listbox/overview.demo.js +0 -65
  309. package/dist/components/listbox/overview.demo.js.map +0 -1
  310. package/dist/components/menu/demos/bubbling.demo.d.ts +0 -6
  311. package/dist/components/menu/demos/bubbling.demo.js +0 -16
  312. package/dist/components/menu/demos/bubbling.demo.js.map +0 -1
  313. package/dist/components/menu/demos/context-trigger.demo.d.ts +0 -7
  314. package/dist/components/menu/demos/context-trigger.demo.js +0 -87
  315. package/dist/components/menu/demos/context-trigger.demo.js.map +0 -1
  316. package/dist/components/menu/demos/overview.demo.d.ts +0 -7
  317. package/dist/components/menu/demos/overview.demo.js +0 -33
  318. package/dist/components/menu/demos/overview.demo.js.map +0 -1
  319. package/dist/components/menu/hover-aim.js.map +0 -1
  320. package/dist/components/menu/menu.js.map +0 -1
  321. package/dist/components/popover/overview.demo.d.ts +0 -7
  322. package/dist/components/popover/overview.demo.js +0 -65
  323. package/dist/components/popover/overview.demo.js.map +0 -1
  324. package/dist/components/popover/popover.js.map +0 -1
  325. package/dist/components/select/deconstructed.demo.d.ts +0 -7
  326. package/dist/components/select/deconstructed.demo.js +0 -54
  327. package/dist/components/select/deconstructed.demo.js.map +0 -1
  328. package/dist/components/select/overview.demo.d.ts +0 -6
  329. package/dist/components/select/overview.demo.js +0 -28
  330. package/dist/components/select/overview.demo.js.map +0 -1
  331. package/dist/components/select/select.js.map +0 -1
  332. package/dist/components/separator/separator.d.ts +0 -2
  333. package/dist/components/separator/separator.js +0 -15
  334. package/dist/components/separator/separator.js.map +0 -1
  335. package/dist/components/tabs/tabs.d.ts +0 -78
  336. package/dist/components/tabs/tabs.js +0 -339
  337. package/dist/components/tabs/tabs.js.map +0 -1
  338. package/dist/interactions/keydown/keydown.js.map +0 -1
  339. package/dist/interactions/outside-click/outside-click-mixin.js.map +0 -1
  340. package/dist/interactions/typeahead/typeahead-mixin.js.map +0 -1
  341. package/dist/runtime/demos/basic.demo.d.ts +0 -6
  342. package/dist/runtime/demos/basic.demo.js +0 -16
  343. package/dist/runtime/demos/basic.demo.js.map +0 -1
  344. package/dist/runtime/demos/controlled-uncontrolled-values.demo.d.ts +0 -6
  345. package/dist/runtime/demos/controlled-uncontrolled-values.demo.js +0 -77
  346. package/dist/runtime/demos/controlled-uncontrolled-values.demo.js.map +0 -1
  347. package/dist/runtime/demos/keyed-list.demo.d.ts +0 -6
  348. package/dist/runtime/demos/keyed-list.demo.js +0 -62
  349. package/dist/runtime/demos/keyed-list.demo.js.map +0 -1
  350. package/dist/runtime/demos/readme.demo.d.ts +0 -5
  351. package/dist/runtime/demos/readme.demo.js +0 -396
  352. package/dist/runtime/demos/readme.demo.js.map +0 -1
  353. package/dist/theme/contract.d.ts +0 -61
  354. package/dist/theme/contract.js +0 -131
  355. package/dist/theme/contract.js.map +0 -1
  356. package/dist/theme/glyph-contract.d.ts +0 -11
  357. package/dist/theme/glyph-contract.js +0 -34
  358. package/dist/theme/glyph-contract.js.map +0 -1
  359. package/dist/theme/presets/rmx-01/glyphs.d.ts +0 -2
  360. package/dist/theme/presets/rmx-01/glyphs.js +0 -252
  361. package/dist/theme/presets/rmx-01/glyphs.js.map +0 -1
  362. package/dist/theme/presets/rmx-01/index.d.ts +0 -4
  363. package/dist/theme/presets/rmx-01/index.js +0 -119
  364. package/dist/theme/presets/rmx-01/index.js.map +0 -1
  365. package/dist/theme/runtime.d.ts +0 -2
  366. package/dist/theme/runtime.js +0 -84
  367. package/dist/theme/runtime.js.map +0 -1
  368. package/dist/theme/theme.d.ts +0 -6
  369. package/dist/theme/theme.js +0 -5
  370. package/dist/theme/theme.js.map +0 -1
  371. package/dist/utils/flash-attribute.js.map +0 -1
  372. package/dist/utils/scroll-lock.d.ts +0 -3
  373. package/dist/utils/scroll-lock.js.map +0 -1
  374. package/dist/utils/wait-for-css-transition.js.map +0 -1
  375. package/dist/utils/wait.js.map +0 -1
  376. package/src/animation/demos/animation.demo.tsx +0 -194
  377. package/src/animation/demos/spring.demo.tsx +0 -385
  378. package/src/components/accordion/accordion.tsx +0 -565
  379. package/src/components/accordion/demos/card.demo.tsx +0 -114
  380. package/src/components/accordion/demos/multiple.demo.tsx +0 -57
  381. package/src/components/accordion/demos/overview.demo.tsx +0 -57
  382. package/src/components/breadcrumbs/basic.demo.tsx +0 -18
  383. package/src/components/breadcrumbs/separator.demo.tsx +0 -19
  384. package/src/components/button/README.md +0 -44
  385. package/src/components/button/button.tsx +0 -286
  386. package/src/components/button/demos/aliases.demo.tsx +0 -28
  387. package/src/components/button/demos/basic.demo.tsx +0 -31
  388. package/src/components/button/demos/states.demo.tsx +0 -53
  389. package/src/components/combobox/overview.demo.tsx +0 -200
  390. package/src/components/glyph/README.md +0 -72
  391. package/src/components/glyph/glyph.tsx +0 -110
  392. package/src/components/listbox/overview.demo.tsx +0 -102
  393. package/src/components/menu/demos/bubbling.demo.tsx +0 -35
  394. package/src/components/menu/demos/context-trigger.demo.tsx +0 -133
  395. package/src/components/menu/demos/overview.demo.tsx +0 -77
  396. package/src/components/popover/overview.demo.tsx +0 -144
  397. package/src/components/select/deconstructed.demo.tsx +0 -96
  398. package/src/components/select/overview.demo.tsx +0 -52
  399. package/src/components/separator/separator.ts +0 -19
  400. package/src/components/tabs/README.md +0 -105
  401. package/src/components/tabs/tabs.tsx +0 -504
  402. package/src/runtime/demos/basic.demo.tsx +0 -21
  403. package/src/runtime/demos/controlled-uncontrolled-values.demo.tsx +0 -177
  404. package/src/runtime/demos/keyed-list.demo.tsx +0 -94
  405. package/src/theme/README.md +0 -103
  406. package/src/theme/contract.ts +0 -215
  407. package/src/theme/glyph-contract.ts +0 -59
  408. package/src/theme/presets/rmx-01/glyphs.tsx +0 -308
  409. package/src/theme/presets/rmx-01/index.ts +0 -123
  410. package/src/theme/runtime.ts +0 -119
  411. package/src/theme/theme.ts +0 -15
  412. package/src/utils/scroll-lock/README.md +0 -33
  413. /package/dist/{components/anchor/anchor.d.ts → anchor/index.d.ts} +0 -0
  414. /package/dist/{components/breadcrumbs/breadcrumbs.d.ts → breadcrumbs/index.d.ts} +0 -0
  415. /package/dist/{utils → listbox}/flash-attribute.d.ts +0 -0
  416. /package/dist/{utils → listbox}/flash-attribute.js +0 -0
  417. /package/dist/{components/menu → menu}/hover-aim.d.ts +0 -0
  418. /package/dist/{components/menu → menu}/hover-aim.js +0 -0
  419. /package/dist/{interactions/outside-click/outside-click-mixin.d.ts → popover/outside-click.d.ts} +0 -0
  420. /package/dist/{interactions/keydown → select}/keydown.d.ts +0 -0
  421. /package/dist/{interactions/keydown → select}/keydown.js +0 -0
  422. /package/dist/{interactions/typeahead/typeahead-mixin.d.ts → shared/typeahead.d.ts} +0 -0
  423. /package/dist/{utils → shared}/wait-for-css-transition.d.ts +0 -0
  424. /package/dist/{utils → shared}/wait-for-css-transition.js +0 -0
  425. /package/dist/{utils → shared}/wait.d.ts +0 -0
  426. /package/dist/{utils → shared}/wait.js +0 -0
  427. /package/src/{components/anchor/anchor.ts → anchor/index.ts} +0 -0
  428. /package/src/{utils → listbox}/flash-attribute.ts +0 -0
  429. /package/src/{components/menu → menu}/hover-aim.ts +0 -0
  430. /package/src/{interactions/outside-click/outside-click-mixin.ts → popover/outside-click.ts} +0 -0
  431. /package/src/{interactions/keydown → select}/keydown.ts +0 -0
  432. /package/src/{interactions/typeahead/typeahead-mixin.ts → shared/typeahead.ts} +0 -0
  433. /package/src/{utils → shared}/wait-for-css-transition.ts +0 -0
  434. /package/src/{utils → shared}/wait.ts +0 -0
@@ -0,0 +1,512 @@
1
+ import {
2
+ attrs,
3
+ createMixin,
4
+ on,
5
+ ref,
6
+ type Dispatched,
7
+ type ElementProps,
8
+ type Handle,
9
+ type MixinHandle,
10
+ type Props,
11
+ type RemixNode,
12
+ } from '@remix-run/ui'
13
+
14
+ const ACCORDION_CHANGE_EVENT = 'rmx:accordion-change' as const
15
+
16
+ type AccordionChangeHandler<target extends HTMLElement> = (
17
+ event: Dispatched<AccordionChangeEvent, target>,
18
+ signal: AbortSignal,
19
+ ) => void | Promise<void>
20
+
21
+ declare global {
22
+ interface HTMLElementEventMap {
23
+ [ACCORDION_CHANGE_EVENT]: AccordionChangeEvent
24
+ }
25
+ }
26
+
27
+ export class AccordionChangeEvent extends Event {
28
+ readonly accordionType: AccordionType
29
+ readonly itemValue: string
30
+ readonly value: AccordionValue
31
+
32
+ constructor(
33
+ value: AccordionValue,
34
+ init: {
35
+ accordionType: AccordionType
36
+ itemValue: string
37
+ },
38
+ ) {
39
+ super(ACCORDION_CHANGE_EVENT, {
40
+ bubbles: true,
41
+ })
42
+ this.accordionType = init.accordionType
43
+ this.itemValue = init.itemValue
44
+ this.value = value
45
+ }
46
+ }
47
+
48
+ export type AccordionType = 'single' | 'multiple'
49
+ export type AccordionValue = string | null | string[]
50
+ export type AccordionSingleValue = string | null
51
+ export type AccordionMultipleValue = string[]
52
+ export type AccordionHeadingLevel = 1 | 2 | 3 | 4 | 5 | 6
53
+
54
+ type FocusDirection = 'first' | 'last' | 'next' | 'previous'
55
+
56
+ type RegisteredItem = {
57
+ disabled: boolean
58
+ getTriggerNode(): HTMLButtonElement | null
59
+ value: string
60
+ }
61
+
62
+ interface AccordionContextValue {
63
+ readonly collapsible: boolean
64
+ readonly disabled: boolean
65
+ readonly headingLevel: AccordionHeadingLevel
66
+ readonly type: AccordionType
67
+ focusItem(value: string, direction: FocusDirection): void
68
+ getPanelId(value: string): string
69
+ getTriggerId(value: string): string | undefined
70
+ isOpen(value: string): boolean
71
+ registerItem(item: RegisteredItem): void
72
+ registerRoot(node: HTMLElement): void
73
+ toggleItem(value: string): void
74
+ unregisterRoot(node: HTMLElement): void
75
+ }
76
+
77
+ interface AccordionItemContextValue {
78
+ readonly disabled: boolean
79
+ readonly headingLevel: AccordionHeadingLevel
80
+ readonly lockedOpen: boolean
81
+ readonly open: boolean
82
+ readonly panelId: string
83
+ readonly triggerId: string
84
+ readonly value: string
85
+ setTriggerNode(node: HTMLButtonElement | null): void
86
+ }
87
+
88
+ export interface AccordionBaseContextProps {
89
+ children?: RemixNode
90
+ disabled?: boolean
91
+ headingLevel?: AccordionHeadingLevel
92
+ }
93
+
94
+ export interface AccordionSingleContextProps extends AccordionBaseContextProps {
95
+ type?: 'single'
96
+ value?: AccordionSingleValue
97
+ defaultValue?: AccordionSingleValue
98
+ onValueChange?: (value: AccordionSingleValue) => void
99
+ collapsible?: boolean
100
+ }
101
+
102
+ export interface AccordionMultipleContextProps extends AccordionBaseContextProps {
103
+ type: 'multiple'
104
+ value?: AccordionMultipleValue
105
+ defaultValue?: AccordionMultipleValue
106
+ onValueChange?: (value: AccordionMultipleValue) => void
107
+ }
108
+
109
+ export type AccordionContextProps = AccordionSingleContextProps | AccordionMultipleContextProps
110
+
111
+ export interface AccordionRootOptions {}
112
+
113
+ export interface AccordionItemOptions {
114
+ disabled?: boolean
115
+ value: string
116
+ }
117
+
118
+ export interface AccordionTriggerOptions {
119
+ disabled?: boolean
120
+ }
121
+
122
+ export interface AccordionContentOptions {}
123
+
124
+ export type AccordionProps = Props<'div'> & AccordionContextProps
125
+
126
+ export type AccordionItemProps = Omit<Props<'div'>, 'children'> &
127
+ AccordionItemOptions & {
128
+ children?: RemixNode
129
+ }
130
+
131
+ export type AccordionTriggerProps = Omit<Props<'button'>, 'children' | 'type'> &
132
+ AccordionTriggerOptions & {
133
+ children?: RemixNode
134
+ type?: 'button' | 'submit' | 'reset'
135
+ }
136
+
137
+ export type AccordionContentProps = Omit<Props<'div'>, 'children'> & {
138
+ children?: RemixNode
139
+ }
140
+
141
+ function isMultipleProps(
142
+ props: AccordionContextProps | null,
143
+ ): props is AccordionMultipleContextProps {
144
+ return props?.type === 'multiple'
145
+ }
146
+
147
+ function getAccordionContext(handle: Handle<unknown, unknown> | MixinHandle) {
148
+ return handle.context.get(AccordionProvider)
149
+ }
150
+
151
+ function getAccordionItemContext(handle: Handle<unknown, unknown> | MixinHandle) {
152
+ return handle.context.get(AccordionItemProvider)
153
+ }
154
+
155
+ function AccordionProvider(
156
+ handle: Handle<AccordionContextProps, AccordionContextValue>,
157
+ ): () => RemixNode {
158
+ let rootNode: HTMLElement | null = null
159
+ let registeredItems: RegisteredItem[] = []
160
+ let uncontrolledSingleValue: string | null = null
161
+ let uncontrolledMultipleValue: string[] = []
162
+ let hasInitializedSingle = false
163
+ let hasInitializedMultiple = false
164
+
165
+ function getType() {
166
+ return isMultipleProps(handle.props) ? 'multiple' : 'single'
167
+ }
168
+
169
+ function getSingleValue() {
170
+ if (isMultipleProps(handle.props)) {
171
+ return null
172
+ }
173
+
174
+ if (handle.props.value !== undefined) {
175
+ return handle.props.value
176
+ }
177
+
178
+ if (!hasInitializedSingle) {
179
+ uncontrolledSingleValue = handle.props.defaultValue ?? null
180
+ hasInitializedSingle = true
181
+ }
182
+
183
+ return uncontrolledSingleValue
184
+ }
185
+
186
+ function getMultipleValue() {
187
+ if (!isMultipleProps(handle.props)) {
188
+ return []
189
+ }
190
+
191
+ if (handle.props.value !== undefined) {
192
+ return handle.props.value
193
+ }
194
+
195
+ if (!hasInitializedMultiple) {
196
+ uncontrolledMultipleValue = [...(handle.props.defaultValue ?? [])]
197
+ hasInitializedMultiple = true
198
+ }
199
+
200
+ return uncontrolledMultipleValue
201
+ }
202
+
203
+ function isOpen(value: string) {
204
+ if (getType() === 'multiple') {
205
+ return getMultipleValue().includes(value)
206
+ }
207
+
208
+ return getSingleValue() === value
209
+ }
210
+
211
+ function dispatchChange(itemValue: string, value: AccordionValue) {
212
+ rootNode?.dispatchEvent(
213
+ new AccordionChangeEvent(value, {
214
+ accordionType: getType(),
215
+ itemValue,
216
+ }),
217
+ )
218
+ }
219
+
220
+ function toggleItem(itemValue: string) {
221
+ if (handle.props.disabled) {
222
+ return
223
+ }
224
+
225
+ if (isMultipleProps(handle.props)) {
226
+ let currentValue = getMultipleValue()
227
+ let nextValue = currentValue.includes(itemValue)
228
+ ? currentValue.filter((value) => value !== itemValue)
229
+ : [...currentValue, itemValue]
230
+
231
+ if (handle.props.value === undefined) {
232
+ uncontrolledMultipleValue = nextValue
233
+ void handle.update()
234
+ }
235
+
236
+ handle.props.onValueChange?.(nextValue)
237
+ dispatchChange(itemValue, nextValue)
238
+ return
239
+ }
240
+
241
+ let isCurrentItemOpen = getSingleValue() === itemValue
242
+ if (isCurrentItemOpen && !(handle.props.collapsible ?? true)) {
243
+ return
244
+ }
245
+
246
+ let nextValue = isCurrentItemOpen ? null : itemValue
247
+
248
+ if (handle.props.value === undefined) {
249
+ uncontrolledSingleValue = nextValue
250
+ void handle.update()
251
+ }
252
+
253
+ handle.props.onValueChange?.(nextValue)
254
+ dispatchChange(itemValue, nextValue)
255
+ }
256
+
257
+ function focusItem(itemValue: string, direction: FocusDirection) {
258
+ let items = registeredItems.filter((item) => !item.disabled && item.getTriggerNode() !== null)
259
+ if (items.length === 0) {
260
+ return
261
+ }
262
+
263
+ let currentIndex = items.findIndex((item) => item.value === itemValue)
264
+ let targetIndex = 0
265
+
266
+ switch (direction) {
267
+ case 'first':
268
+ targetIndex = 0
269
+ break
270
+ case 'last':
271
+ targetIndex = items.length - 1
272
+ break
273
+ case 'previous':
274
+ targetIndex = currentIndex <= 0 ? items.length - 1 : currentIndex - 1
275
+ break
276
+ case 'next':
277
+ targetIndex =
278
+ currentIndex === -1 || currentIndex === items.length - 1 ? 0 : currentIndex + 1
279
+ break
280
+ }
281
+
282
+ items[targetIndex]?.getTriggerNode()?.focus()
283
+ }
284
+
285
+ function registerItem(item: RegisteredItem) {
286
+ registeredItems.push(item)
287
+ }
288
+
289
+ function getTriggerId(value: string) {
290
+ return registeredItems.find((item) => item.value === value)?.getTriggerNode()?.id
291
+ }
292
+
293
+ function getPanelId(value: string) {
294
+ return `${handle.id}-${value}-panel`
295
+ }
296
+
297
+ handle.context.set({
298
+ get collapsible() {
299
+ return getType() === 'multiple'
300
+ ? true
301
+ : ((handle.props as AccordionSingleContextProps).collapsible ?? true)
302
+ },
303
+ get disabled() {
304
+ return handle.props.disabled ?? false
305
+ },
306
+ focusItem,
307
+ getPanelId,
308
+ getTriggerId,
309
+ get headingLevel() {
310
+ return handle.props.headingLevel ?? 3
311
+ },
312
+ isOpen,
313
+ registerItem,
314
+ registerRoot(node) {
315
+ rootNode = node
316
+ },
317
+ toggleItem,
318
+ get type() {
319
+ return getType()
320
+ },
321
+ unregisterRoot(node) {
322
+ if (rootNode === node) {
323
+ rootNode = null
324
+ }
325
+ },
326
+ })
327
+
328
+ return () => {
329
+ registeredItems = []
330
+ return handle.props.children
331
+ }
332
+ }
333
+
334
+ function AccordionItemProvider(
335
+ handle: Handle<AccordionItemOptions & { children?: RemixNode }, AccordionItemContextValue>,
336
+ ): () => RemixNode {
337
+ let triggerNode: HTMLButtonElement | null = null
338
+ let triggerId = `${handle.id}-trigger`
339
+ let panelId = `${handle.id}-panel`
340
+ let disabled = false
341
+ let headingLevel: AccordionHeadingLevel = 3
342
+ let lockedOpen = false
343
+ let open = false
344
+ let value = handle.props.value
345
+
346
+ handle.context.set({
347
+ get disabled() {
348
+ return disabled
349
+ },
350
+ get headingLevel() {
351
+ return headingLevel
352
+ },
353
+ get lockedOpen() {
354
+ return lockedOpen
355
+ },
356
+ get open() {
357
+ return open
358
+ },
359
+ get panelId() {
360
+ return panelId
361
+ },
362
+ setTriggerNode(node) {
363
+ triggerNode = node
364
+ },
365
+ get triggerId() {
366
+ return triggerId
367
+ },
368
+ get value() {
369
+ return value
370
+ },
371
+ })
372
+
373
+ return () => {
374
+ let accordion = getAccordionContext(handle)
375
+ value = handle.props.value
376
+ disabled = accordion.disabled || handle.props.disabled === true
377
+ headingLevel = accordion.headingLevel
378
+ open = accordion.isOpen(handle.props.value)
379
+ lockedOpen = accordion.type === 'single' && !accordion.collapsible && open
380
+
381
+ accordion.registerItem({
382
+ disabled,
383
+ getTriggerNode: () => triggerNode,
384
+ value: handle.props.value,
385
+ })
386
+
387
+ return handle.props.children
388
+ }
389
+ }
390
+
391
+ const rootMixin = createMixin<HTMLElement, [options?: AccordionRootOptions], ElementProps>(
392
+ (handle) => {
393
+ let context = getAccordionContext(handle)
394
+ let rootNode: HTMLElement | null = null
395
+
396
+ handle.queueTask((node, signal) => {
397
+ rootNode = node
398
+ context.registerRoot(node)
399
+ signal.addEventListener('abort', () => {
400
+ if (rootNode === node) {
401
+ rootNode = null
402
+ }
403
+ context.unregisterRoot(node)
404
+ })
405
+ })
406
+
407
+ return () =>
408
+ attrs({
409
+ 'data-disabled': context.disabled ? '' : undefined,
410
+ 'data-type': context.type,
411
+ })
412
+ },
413
+ )
414
+
415
+ const itemMixin = createMixin<HTMLElement, [options?: AccordionItemOptions], ElementProps>(
416
+ (handle) => {
417
+ let item = getAccordionItemContext(handle)
418
+
419
+ return () =>
420
+ attrs({
421
+ 'data-disabled': item.disabled ? '' : undefined,
422
+ 'data-state': item.open ? 'open' : 'closed',
423
+ })
424
+ },
425
+ )
426
+
427
+ const triggerMixin = createMixin<
428
+ HTMLButtonElement,
429
+ [options?: AccordionTriggerOptions],
430
+ ElementProps
431
+ >((handle) => {
432
+ let accordion = getAccordionContext(handle)
433
+ let item = getAccordionItemContext(handle)
434
+
435
+ return (options, props = options as ElementProps) => {
436
+ options = props === options ? undefined : options
437
+ let disabled = item.disabled || options?.disabled === true || props.disabled === true
438
+ let toggleItem = () => {
439
+ if (disabled || item.lockedOpen) {
440
+ return
441
+ }
442
+
443
+ accordion.toggleItem(item.value)
444
+ }
445
+
446
+ return [
447
+ attrs({
448
+ 'aria-controls': item.panelId,
449
+ 'aria-disabled': item.lockedOpen ? true : undefined,
450
+ 'aria-expanded': item.open,
451
+ 'data-state': item.open ? 'open' : 'closed',
452
+ disabled: disabled ? true : undefined,
453
+ id: item.triggerId,
454
+ }),
455
+ ref((node: HTMLButtonElement) => {
456
+ item.setTriggerNode(node)
457
+ }),
458
+ on('click', toggleItem),
459
+ on('keydown', (event) => {
460
+ switch (event.key) {
461
+ case 'ArrowDown':
462
+ event.preventDefault()
463
+ accordion.focusItem(item.value, 'next')
464
+ break
465
+ case 'ArrowUp':
466
+ event.preventDefault()
467
+ accordion.focusItem(item.value, 'previous')
468
+ break
469
+ case 'Home':
470
+ event.preventDefault()
471
+ accordion.focusItem(item.value, 'first')
472
+ break
473
+ case 'End':
474
+ event.preventDefault()
475
+ accordion.focusItem(item.value, 'last')
476
+ break
477
+ }
478
+ }),
479
+ ]
480
+ }
481
+ })
482
+
483
+ const contentMixin = createMixin<HTMLElement, [options?: AccordionContentOptions], ElementProps>(
484
+ (handle) => {
485
+ let item = getAccordionItemContext(handle)
486
+
487
+ return () =>
488
+ attrs({
489
+ 'aria-hidden': item.open ? undefined : true,
490
+ 'aria-labelledby': item.triggerId,
491
+ 'data-state': item.open ? 'open' : 'closed',
492
+ id: item.panelId,
493
+ inert: item.open ? undefined : true,
494
+ })
495
+ },
496
+ )
497
+
498
+ export const Context = AccordionProvider
499
+ export const ItemContext: (
500
+ handle: Handle<AccordionItemOptions & { children?: RemixNode }, AccordionItemContextValue>,
501
+ ) => () => RemixNode = AccordionItemProvider
502
+ export const content = contentMixin
503
+ export const item = itemMixin
504
+ export const root = rootMixin
505
+ export const trigger = triggerMixin
506
+
507
+ export function onAccordionChange<target extends HTMLElement>(
508
+ handler: AccordionChangeHandler<target>,
509
+ captureBoolean?: boolean,
510
+ ): ReturnType<typeof on<target, typeof ACCORDION_CHANGE_EVENT>> {
511
+ return on(ACCORDION_CHANGE_EVENT, handler, captureBoolean)
512
+ }
@@ -2,7 +2,7 @@
2
2
 
3
3
  `anchor` positions a floating element against an anchor element or viewport coordinates and keeps it constrained to the viewport. Use it for custom floating surfaces that need placement, flipping, offsets, and optional relative alignment.
4
4
 
5
- ## Usage
5
+ ## Primitive Usage
6
6
 
7
7
  ```tsx
8
8
  import { anchor } from 'remix/ui/anchor'
@@ -55,7 +55,42 @@ Anchor to coordinates when the surface should open at a pointer location.
55
55
  let cleanup = anchor(popover, { x: event.clientX, y: event.clientY }, { placement: 'bottom-start' })
56
56
  ```
57
57
 
58
- ## `anchor.*`
58
+ Keep presentation app-owned when the anchored element is rendered by your component:
59
+
60
+ ```tsx
61
+ import { anchor } from 'remix/ui/anchor'
62
+ import { on, ref, type Handle } from 'remix/ui'
63
+ import { panelStyle } from './floating.styles'
64
+
65
+ export function AnchoredPanel(handle: Handle) {
66
+ let cleanup = () => {}
67
+ let trigger: HTMLElement | null = null
68
+ let panel: HTMLElement | null = null
69
+
70
+ function position() {
71
+ cleanup()
72
+ if (trigger && panel) {
73
+ cleanup = anchor(panel, trigger, { placement: 'bottom-start', offset: 8 })
74
+ }
75
+ }
76
+
77
+ return () => (
78
+ <>
79
+ <button
80
+ mix={[ref((node) => (trigger = node as HTMLElement)), on('click', position)]}
81
+ type="button"
82
+ >
83
+ Open
84
+ </button>
85
+ <div data-panel mix={[panelStyle, ref((node) => (panel = node as HTMLElement))]}>
86
+ Panel
87
+ </div>
88
+ </>
89
+ )
90
+ }
91
+ ```
92
+
93
+ ## `remix/ui/anchor`
59
94
 
60
95
  - `anchor(floatingElement, anchorTarget, options)`: positions `floatingElement` against an element or coordinate target, starts animation-frame polling for geometry changes, and returns a cleanup function.
61
96
  - `AnchorOptions`: placement, inset, relative alignment, and offset options.
@@ -37,7 +37,7 @@ type AnimationState = {
37
37
  }
38
38
 
39
39
  const animatingNodes = new WeakMap<Element, AnimationState>()
40
- const initialEntranceSeenByParent = new WeakMap<ParentNode, Set<string>>()
40
+ const initialEntranceSeenByParent = new WeakMap<ParentNode, Set<unknown>>()
41
41
 
42
42
  function extractStyleProps(config: AnimateMixinConfig): Keyframe {
43
43
  let result: Keyframe = {}
@@ -152,14 +152,14 @@ function waitForAnimationOrAbort(animation: Animation, signal: AbortSignal): Pro
152
152
  }
153
153
 
154
154
  function shouldSkipInitialEntrance(
155
- event: { key?: string; parent: ParentNode },
155
+ event: { key?: unknown; parent: ParentNode },
156
156
  config: AnimateMixinConfig,
157
157
  ): boolean {
158
158
  if (config.initial !== false) return false
159
159
  if (event.key == null) return false
160
160
  let seenForParent = initialEntranceSeenByParent.get(event.parent)
161
161
  if (!seenForParent) {
162
- seenForParent = new Set<string>()
162
+ seenForParent = new Set<unknown>()
163
163
  initialEntranceSeenByParent.set(event.parent, seenForParent)
164
164
  }
165
165
  if (seenForParent.has(event.key)) return false
@@ -57,7 +57,7 @@ export function ColorInterpolation() {
57
57
 
58
58
  <div mix={[css({ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 16 })]}>
59
59
  <div
60
- className="oklch-box"
60
+ class="oklch-box"
61
61
  mix={[
62
62
  css({
63
63
  width: 100,
@@ -15,16 +15,19 @@ function shuffle<T>(array: T[]): T[] {
15
15
  export function Reordering(handle: Handle) {
16
16
  let order = initialOrder
17
17
 
18
- function scheduleNextShuffle() {
19
- setTimeout(() => {
20
- if (handle.signal.aborted) return
18
+ function scheduleNextShuffle(signal: AbortSignal) {
19
+ let timeoutId = setTimeout(async () => {
20
+ if (signal.aborted) return
21
21
  order = shuffle(order)
22
- handle.update()
23
- scheduleNextShuffle()
22
+ let nextSignal = await handle.update()
23
+ if (nextSignal.aborted) return
24
+ scheduleNextShuffle(nextSignal)
24
25
  }, 1000)
26
+
27
+ signal.addEventListener('abort', () => clearTimeout(timeoutId), { once: true })
25
28
  }
26
29
 
27
- scheduleNextShuffle()
30
+ handle.queueTask(scheduleNextShuffle)
28
31
 
29
32
  return () => (
30
33
  <ul
@@ -2,7 +2,7 @@
2
2
 
3
3
  `Breadcrumbs` renders semantic breadcrumb navigation from a list of items. Use it when the page needs a compact path back through parent sections.
4
4
 
5
- ## Usage
5
+ ## Component Usage
6
6
 
7
7
  ```tsx
8
8
  import { Breadcrumbs } from 'remix/ui/breadcrumbs'
@@ -32,13 +32,13 @@ Mark an earlier item as current when the page belongs to a parent section but th
32
32
  />
33
33
  ```
34
34
 
35
- Pass `separator` to replace the default chevron glyph.
35
+ Pass `separator` to replace the default chevron icon.
36
36
 
37
37
  ```tsx
38
38
  <Breadcrumbs items={[{ href: '/', label: 'Home' }, { label: 'Breadcrumbs' }]} separator="/" />
39
39
  ```
40
40
 
41
- ## `breadcrumbs.*`
41
+ ## `remix/ui/breadcrumbs`
42
42
 
43
43
  - `Breadcrumbs`: component that renders a `<nav>` with an ordered list of breadcrumb items.
44
44
  - `BreadcrumbItem`: item shape with `label`, optional `href`, and optional `current`.
@@ -52,4 +52,4 @@ Pass `separator` to replace the default chevron glyph.
52
52
  - An explicit current item wins over the last-item default.
53
53
  - Current items render as text with `aria-current="page"`, even when they include `href`.
54
54
  - Non-current items with `href` render as links; non-current items without `href` render as text.
55
- - The default separator is the `chevronRight` glyph. Separators render between items and are hidden from assistive technology.
55
+ - The default separator is a chevron icon. Separators render between items and are hidden from assistive technology.