@remix-run/ui 0.2.0 → 0.4.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 (395) hide show
  1. package/README.md +50 -164
  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.d.ts → anchor/index.d.ts} +8 -1
  9. package/dist/{components/anchor/anchor.js → anchor/index.js} +31 -12
  10. package/dist/anchor/index.js.map +1 -0
  11. package/dist/animation/demos/aspect-ratio.d.ts +2 -0
  12. package/dist/animation/demos/aspect-ratio.js +69 -0
  13. package/dist/animation/demos/aspect-ratio.js.map +1 -0
  14. package/dist/animation/demos/bouncy-switch.d.ts +2 -0
  15. package/dist/animation/demos/bouncy-switch.js +36 -0
  16. package/dist/animation/demos/bouncy-switch.js.map +1 -0
  17. package/dist/animation/demos/color-interpolation.d.ts +1 -0
  18. package/dist/animation/demos/color-interpolation.js +53 -0
  19. package/dist/animation/demos/color-interpolation.js.map +1 -0
  20. package/dist/animation/demos/cube.d.ts +2 -0
  21. package/dist/animation/demos/cube.js +86 -0
  22. package/dist/animation/demos/cube.js.map +1 -0
  23. package/dist/animation/demos/default-animate.d.ts +2 -0
  24. package/dist/animation/demos/default-animate.js +89 -0
  25. package/dist/animation/demos/default-animate.js.map +1 -0
  26. package/dist/animation/demos/drag-release.d.ts +24 -0
  27. package/dist/animation/demos/drag-release.js +96 -0
  28. package/dist/animation/demos/drag-release.js.map +1 -0
  29. package/dist/animation/demos/enter.d.ts +1 -0
  30. package/dist/animation/demos/enter.js +19 -0
  31. package/dist/animation/demos/enter.js.map +1 -0
  32. package/dist/animation/demos/exit.d.ts +2 -0
  33. package/dist/animation/demos/exit.js +58 -0
  34. package/dist/animation/demos/exit.js.map +1 -0
  35. package/dist/animation/demos/flip-toggle.d.ts +2 -0
  36. package/dist/animation/demos/flip-toggle.js +37 -0
  37. package/dist/animation/demos/flip-toggle.js.map +1 -0
  38. package/dist/animation/demos/hold-to-confirm.d.ts +13 -0
  39. package/dist/animation/demos/hold-to-confirm.js +211 -0
  40. package/dist/animation/demos/hold-to-confirm.js.map +1 -0
  41. package/dist/animation/demos/html-content.d.ts +2 -0
  42. package/dist/animation/demos/html-content.js +30 -0
  43. package/dist/animation/demos/html-content.js.map +1 -0
  44. package/dist/animation/demos/interruptible-keyframes.d.ts +1 -0
  45. package/dist/animation/demos/interruptible-keyframes.js +48 -0
  46. package/dist/animation/demos/interruptible-keyframes.js.map +1 -0
  47. package/dist/animation/demos/keyframes.d.ts +1 -0
  48. package/dist/animation/demos/keyframes.js +24 -0
  49. package/dist/animation/demos/keyframes.js.map +1 -0
  50. package/dist/animation/demos/material-ripple.d.ts +2 -0
  51. package/dist/animation/demos/material-ripple.js +127 -0
  52. package/dist/animation/demos/material-ripple.js.map +1 -0
  53. package/dist/animation/demos/mixin-presence-list.d.ts +2 -0
  54. package/dist/animation/demos/mixin-presence-list.js +88 -0
  55. package/dist/animation/demos/mixin-presence-list.js.map +1 -0
  56. package/dist/animation/demos/mixin-reclaim.d.ts +2 -0
  57. package/dist/animation/demos/mixin-reclaim.js +90 -0
  58. package/dist/animation/demos/mixin-reclaim.js.map +1 -0
  59. package/dist/animation/demos/multi-state-badge.d.ts +2 -0
  60. package/dist/animation/demos/multi-state-badge.js +231 -0
  61. package/dist/animation/demos/multi-state-badge.js.map +1 -0
  62. package/dist/animation/demos/press.d.ts +2 -0
  63. package/dist/animation/demos/press.js +63 -0
  64. package/dist/animation/demos/press.js.map +1 -0
  65. package/dist/animation/demos/reordering.d.ts +2 -0
  66. package/dist/animation/demos/reordering.js +53 -0
  67. package/dist/animation/demos/reordering.js.map +1 -0
  68. package/dist/animation/demos/rolling-square.d.ts +2 -0
  69. package/dist/animation/demos/rolling-square.js +42 -0
  70. package/dist/animation/demos/rolling-square.js.map +1 -0
  71. package/dist/animation/demos/rotate.d.ts +1 -0
  72. package/dist/animation/demos/rotate.js +18 -0
  73. package/dist/animation/demos/rotate.js.map +1 -0
  74. package/dist/animation/demos/shared-layout.d.ts +2 -0
  75. package/dist/animation/demos/shared-layout.js +114 -0
  76. package/dist/animation/demos/shared-layout.js.map +1 -0
  77. package/dist/animation/demos/transition-options.d.ts +1 -0
  78. package/dist/animation/demos/transition-options.js +21 -0
  79. package/dist/animation/demos/transition-options.js.map +1 -0
  80. package/dist/animation/spring.d.ts +22 -0
  81. package/dist/animation/spring.js +22 -0
  82. package/dist/animation/spring.js.map +1 -1
  83. package/dist/{components/breadcrumbs/breadcrumbs.js → breadcrumbs/index.js} +19 -19
  84. package/dist/breadcrumbs/index.js.map +1 -0
  85. package/dist/button/index.d.ts +15 -0
  86. package/dist/button/index.js +128 -0
  87. package/dist/button/index.js.map +1 -0
  88. package/dist/checkbox/index.d.ts +14 -0
  89. package/dist/checkbox/index.js +125 -0
  90. package/dist/checkbox/index.js.map +1 -0
  91. package/dist/combobox/index.d.ts +21 -0
  92. package/dist/combobox/index.js +58 -0
  93. package/dist/combobox/index.js.map +1 -0
  94. package/dist/{components/combobox/combobox.d.ts → combobox/primitives.d.ts} +3 -7
  95. package/dist/{components/combobox/combobox.js → combobox/primitives.js} +8 -61
  96. package/dist/combobox/primitives.js.map +1 -0
  97. package/dist/input/index.d.ts +13 -0
  98. package/dist/input/index.js +121 -0
  99. package/dist/input/index.js.map +1 -0
  100. package/dist/listbox/flash-attribute.js.map +1 -0
  101. package/dist/{components/listbox/listbox.d.ts → listbox/index.d.ts} +2 -6
  102. package/dist/{components/listbox/listbox.js → listbox/index.js} +4 -82
  103. package/dist/listbox/index.js.map +1 -0
  104. package/dist/menu/hover-aim.js.map +1 -0
  105. package/dist/menu/index.d.ts +42 -0
  106. package/dist/menu/index.js +250 -0
  107. package/dist/menu/index.js.map +1 -0
  108. package/dist/{components/menu/menu.d.ts → menu/primitives.d.ts} +6 -32
  109. package/dist/{components/menu/menu.js → menu/primitives.js} +117 -279
  110. package/dist/menu/primitives.js.map +1 -0
  111. package/dist/{components/popover/popover.d.ts → popover/index.d.ts} +3 -5
  112. package/dist/{components/popover/popover.js → popover/index.js} +15 -51
  113. package/dist/popover/index.js.map +1 -0
  114. package/dist/{interactions/outside-click/outside-click-mixin.js → popover/outside-click.js} +1 -1
  115. package/dist/popover/outside-click.js.map +1 -0
  116. package/dist/popover/scroll-lock.d.ts +1 -0
  117. package/dist/{utils → popover}/scroll-lock.js +0 -18
  118. package/dist/popover/scroll-lock.js.map +1 -0
  119. package/dist/radio/index.d.ts +12 -0
  120. package/dist/radio/index.js +77 -0
  121. package/dist/radio/index.js.map +1 -0
  122. package/dist/runtime/client-entries.d.ts +1 -2
  123. package/dist/runtime/client-entries.js.map +1 -1
  124. package/dist/runtime/component.d.ts +2 -2
  125. package/dist/runtime/component.js +1 -1
  126. package/dist/runtime/component.js.map +1 -1
  127. package/dist/runtime/diff-dom.js +194 -21
  128. package/dist/runtime/diff-dom.js.map +1 -1
  129. package/dist/runtime/frame.d.ts +7 -0
  130. package/dist/runtime/frame.js +176 -41
  131. package/dist/runtime/frame.js.map +1 -1
  132. package/dist/runtime/jsx.d.ts +2 -3
  133. package/dist/runtime/jsx.js.map +1 -1
  134. package/dist/runtime/reconcile.js +11 -5
  135. package/dist/runtime/reconcile.js.map +1 -1
  136. package/dist/runtime/vdom.js +3 -0
  137. package/dist/runtime/vdom.js.map +1 -1
  138. package/dist/select/index.d.ts +19 -0
  139. package/dist/select/index.js +95 -0
  140. package/dist/select/index.js.map +1 -0
  141. package/dist/select/keydown.js.map +1 -0
  142. package/dist/{components/select/select.d.ts → select/primitives.d.ts} +4 -6
  143. package/dist/{components/select/select.js → select/primitives.js} +12 -64
  144. package/dist/select/primitives.js.map +1 -0
  145. package/dist/server/stream.js +5 -4
  146. package/dist/server/stream.js.map +1 -1
  147. package/dist/shared/focus-styles.d.ts +1 -0
  148. package/dist/shared/focus-styles.js +2 -0
  149. package/dist/shared/focus-styles.js.map +1 -0
  150. package/dist/shared/icons.d.ts +9 -0
  151. package/dist/shared/icons.js +42 -0
  152. package/dist/shared/icons.js.map +1 -0
  153. package/dist/shared/listbox-popover-styles.d.ts +6 -0
  154. package/dist/shared/listbox-popover-styles.js +137 -0
  155. package/dist/shared/listbox-popover-styles.js.map +1 -0
  156. package/dist/shared/style-values.d.ts +78 -0
  157. package/dist/{theme/presets/rmx-01/index.js → shared/style-values.js} +3 -34
  158. package/dist/shared/style-values.js.map +1 -0
  159. package/dist/{interactions/typeahead/typeahead-mixin.js → shared/typeahead.js} +1 -1
  160. package/dist/shared/typeahead.js.map +1 -0
  161. package/dist/shared/wait-for-css-transition.js.map +1 -0
  162. package/dist/shared/wait.js.map +1 -0
  163. package/dist/style/style.js +27 -10
  164. package/dist/style/style.js.map +1 -1
  165. package/dist/tabs/index.d.ts +32 -0
  166. package/dist/tabs/index.js +157 -0
  167. package/dist/tabs/index.js.map +1 -0
  168. package/dist/tabs/primitives.d.ts +57 -0
  169. package/dist/tabs/primitives.js +238 -0
  170. package/dist/tabs/primitives.js.map +1 -0
  171. package/dist/toggle/index.d.ts +9 -0
  172. package/dist/toggle/index.js +108 -0
  173. package/dist/toggle/index.js.map +1 -0
  174. package/dist/toggle/primitives.d.ts +29 -0
  175. package/dist/toggle/primitives.js +127 -0
  176. package/dist/toggle/primitives.js.map +1 -0
  177. package/package.json +74 -45
  178. package/src/{components/accordion → accordion}/README.md +50 -14
  179. package/src/accordion/index.tsx +285 -0
  180. package/src/accordion/primitives.tsx +512 -0
  181. package/src/{components/anchor → anchor}/README.md +48 -5
  182. package/src/{components/anchor/anchor.ts → anchor/index.ts} +53 -12
  183. package/src/animation/demos/aspect-ratio.tsx +120 -0
  184. package/src/animation/demos/bouncy-switch.tsx +47 -0
  185. package/src/animation/demos/color-interpolation.tsx +73 -0
  186. package/src/animation/demos/cube.tsx +116 -0
  187. package/src/animation/demos/default-animate.tsx +129 -0
  188. package/src/animation/demos/drag-release.ts +118 -0
  189. package/src/animation/demos/enter.tsx +22 -0
  190. package/src/animation/demos/exit.tsx +79 -0
  191. package/src/animation/demos/flip-toggle.tsx +46 -0
  192. package/src/animation/demos/hold-to-confirm.tsx +317 -0
  193. package/src/animation/demos/html-content.tsx +41 -0
  194. package/src/animation/demos/interruptible-keyframes.tsx +62 -0
  195. package/src/animation/demos/keyframes.tsx +29 -0
  196. package/src/animation/demos/material-ripple.tsx +158 -0
  197. package/src/animation/demos/mixin-presence-list.tsx +121 -0
  198. package/src/animation/demos/mixin-reclaim.tsx +125 -0
  199. package/src/animation/demos/multi-state-badge.tsx +426 -0
  200. package/src/animation/demos/press.tsx +67 -0
  201. package/src/animation/demos/reordering.tsx +68 -0
  202. package/src/animation/demos/rolling-square.tsx +57 -0
  203. package/src/animation/demos/rotate.tsx +21 -0
  204. package/src/animation/demos/shared-layout.tsx +211 -0
  205. package/src/animation/demos/transition-options.tsx +24 -0
  206. package/src/animation/spring.ts +22 -0
  207. package/src/{components/breadcrumbs → breadcrumbs}/README.md +4 -4
  208. package/src/{components/breadcrumbs/breadcrumbs.tsx → breadcrumbs/index.tsx} +18 -18
  209. package/src/button/README.md +44 -0
  210. package/src/button/index.ts +168 -0
  211. package/src/checkbox/README.md +59 -0
  212. package/src/checkbox/index.ts +162 -0
  213. package/src/{components/combobox → combobox}/README.md +58 -9
  214. package/src/combobox/index.tsx +112 -0
  215. package/src/{components/combobox/combobox.tsx → combobox/primitives.tsx} +5 -91
  216. package/src/input/README.md +52 -0
  217. package/src/input/index.ts +147 -0
  218. package/src/{components/listbox → listbox}/README.md +9 -41
  219. package/src/{components/listbox/listbox.ts → listbox/index.ts} +2 -87
  220. package/src/menu/README.md +161 -0
  221. package/src/menu/index.tsx +354 -0
  222. package/src/{components/menu/menu.tsx → menu/primitives.tsx} +117 -359
  223. package/src/{components/popover → popover}/README.md +20 -39
  224. package/src/{components/popover/popover.ts → popover/index.ts} +16 -61
  225. package/src/{utils → popover}/scroll-lock.ts +0 -28
  226. package/src/radio/README.md +53 -0
  227. package/src/radio/index.ts +100 -0
  228. package/src/runtime/client-entries.ts +1 -5
  229. package/src/runtime/component.ts +3 -3
  230. package/src/runtime/demos/readme.demo.tsx +704 -0
  231. package/src/runtime/diff-dom.ts +270 -20
  232. package/src/runtime/frame.ts +218 -41
  233. package/src/runtime/jsx.ts +6 -10
  234. package/src/runtime/reconcile.ts +11 -5
  235. package/src/runtime/vdom.ts +3 -0
  236. package/src/{components/select → select}/README.md +29 -19
  237. package/src/select/index.tsx +159 -0
  238. package/src/{components/select/select.tsx → select/primitives.tsx} +11 -99
  239. package/src/server/stream.ts +10 -5
  240. package/src/shared/focus-styles.ts +2 -0
  241. package/src/shared/icons.tsx +62 -0
  242. package/src/shared/listbox-popover-styles.ts +146 -0
  243. package/src/shared/style-values.ts +165 -0
  244. package/src/style/style.ts +29 -10
  245. package/src/tabs/README.md +141 -0
  246. package/src/tabs/index.tsx +244 -0
  247. package/src/tabs/primitives.ts +365 -0
  248. package/src/toggle/README.md +56 -0
  249. package/src/toggle/index.tsx +134 -0
  250. package/src/toggle/primitives.ts +192 -0
  251. package/dist/components/accordion/accordion.d.ts +0 -92
  252. package/dist/components/accordion/accordion.js +0 -335
  253. package/dist/components/accordion/accordion.js.map +0 -1
  254. package/dist/components/accordion/demos/card.demo.d.ts +0 -6
  255. package/dist/components/accordion/demos/card.demo.js +0 -58
  256. package/dist/components/accordion/demos/card.demo.js.map +0 -1
  257. package/dist/components/accordion/demos/multiple.demo.d.ts +0 -6
  258. package/dist/components/accordion/demos/multiple.demo.js +0 -19
  259. package/dist/components/accordion/demos/multiple.demo.js.map +0 -1
  260. package/dist/components/accordion/demos/overview.demo.d.ts +0 -6
  261. package/dist/components/accordion/demos/overview.demo.js +0 -19
  262. package/dist/components/accordion/demos/overview.demo.js.map +0 -1
  263. package/dist/components/anchor/anchor.js.map +0 -1
  264. package/dist/components/breadcrumbs/breadcrumbs.js.map +0 -1
  265. package/dist/components/breadcrumbs/demos/basic.demo.d.ts +0 -5
  266. package/dist/components/breadcrumbs/demos/basic.demo.js +0 -14
  267. package/dist/components/breadcrumbs/demos/basic.demo.js.map +0 -1
  268. package/dist/components/breadcrumbs/demos/separator.demo.d.ts +0 -5
  269. package/dist/components/breadcrumbs/demos/separator.demo.js +0 -14
  270. package/dist/components/breadcrumbs/demos/separator.demo.js.map +0 -1
  271. package/dist/components/button/button.d.ts +0 -105
  272. package/dist/components/button/button.js +0 -207
  273. package/dist/components/button/button.js.map +0 -1
  274. package/dist/components/button/demos/aliases.demo.d.ts +0 -6
  275. package/dist/components/button/demos/aliases.demo.js +0 -18
  276. package/dist/components/button/demos/aliases.demo.js.map +0 -1
  277. package/dist/components/button/demos/basic.demo.d.ts +0 -6
  278. package/dist/components/button/demos/basic.demo.js +0 -19
  279. package/dist/components/button/demos/basic.demo.js.map +0 -1
  280. package/dist/components/button/demos/states.demo.d.ts +0 -6
  281. package/dist/components/button/demos/states.demo.js +0 -29
  282. package/dist/components/button/demos/states.demo.js.map +0 -1
  283. package/dist/components/combobox/combobox.js.map +0 -1
  284. package/dist/components/combobox/demos/overview.demo.d.ts +0 -6
  285. package/dist/components/combobox/demos/overview.demo.js +0 -153
  286. package/dist/components/combobox/demos/overview.demo.js.map +0 -1
  287. package/dist/components/glyph/glyph.d.ts +0 -14
  288. package/dist/components/glyph/glyph.js +0 -65
  289. package/dist/components/glyph/glyph.js.map +0 -1
  290. package/dist/components/listbox/demos/overview.demo.d.ts +0 -6
  291. package/dist/components/listbox/demos/overview.demo.js +0 -64
  292. package/dist/components/listbox/demos/overview.demo.js.map +0 -1
  293. package/dist/components/listbox/listbox.js.map +0 -1
  294. package/dist/components/menu/demos/bubbling.demo.d.ts +0 -5
  295. package/dist/components/menu/demos/bubbling.demo.js +0 -15
  296. package/dist/components/menu/demos/bubbling.demo.js.map +0 -1
  297. package/dist/components/menu/demos/overview.demo.d.ts +0 -6
  298. package/dist/components/menu/demos/overview.demo.js +0 -32
  299. package/dist/components/menu/demos/overview.demo.js.map +0 -1
  300. package/dist/components/menu/hover-aim.js.map +0 -1
  301. package/dist/components/menu/menu.js.map +0 -1
  302. package/dist/components/popover/demos/overview.demo.d.ts +0 -6
  303. package/dist/components/popover/demos/overview.demo.js +0 -64
  304. package/dist/components/popover/demos/overview.demo.js.map +0 -1
  305. package/dist/components/popover/popover.js.map +0 -1
  306. package/dist/components/select/demos/deconstructed.demo.d.ts +0 -6
  307. package/dist/components/select/demos/deconstructed.demo.js +0 -53
  308. package/dist/components/select/demos/deconstructed.demo.js.map +0 -1
  309. package/dist/components/select/demos/overview.demo.d.ts +0 -5
  310. package/dist/components/select/demos/overview.demo.js +0 -27
  311. package/dist/components/select/demos/overview.demo.js.map +0 -1
  312. package/dist/components/select/select.js.map +0 -1
  313. package/dist/components/separator/separator.d.ts +0 -2
  314. package/dist/components/separator/separator.js +0 -15
  315. package/dist/components/separator/separator.js.map +0 -1
  316. package/dist/components/tabs/tabs.d.ts +0 -78
  317. package/dist/components/tabs/tabs.js +0 -339
  318. package/dist/components/tabs/tabs.js.map +0 -1
  319. package/dist/interactions/keydown/keydown.js.map +0 -1
  320. package/dist/interactions/outside-click/outside-click-mixin.js.map +0 -1
  321. package/dist/interactions/typeahead/typeahead-mixin.js.map +0 -1
  322. package/dist/theme/contract.d.ts +0 -61
  323. package/dist/theme/contract.js +0 -131
  324. package/dist/theme/contract.js.map +0 -1
  325. package/dist/theme/glyph-contract.d.ts +0 -11
  326. package/dist/theme/glyph-contract.js +0 -34
  327. package/dist/theme/glyph-contract.js.map +0 -1
  328. package/dist/theme/presets/rmx-01/glyphs.d.ts +0 -2
  329. package/dist/theme/presets/rmx-01/glyphs.js +0 -252
  330. package/dist/theme/presets/rmx-01/glyphs.js.map +0 -1
  331. package/dist/theme/presets/rmx-01/index.d.ts +0 -4
  332. package/dist/theme/presets/rmx-01/index.js.map +0 -1
  333. package/dist/theme/runtime.d.ts +0 -2
  334. package/dist/theme/runtime.js +0 -84
  335. package/dist/theme/runtime.js.map +0 -1
  336. package/dist/theme/theme.d.ts +0 -6
  337. package/dist/theme/theme.js +0 -5
  338. package/dist/theme/theme.js.map +0 -1
  339. package/dist/utils/flash-attribute.js.map +0 -1
  340. package/dist/utils/scroll-lock.d.ts +0 -3
  341. package/dist/utils/scroll-lock.js.map +0 -1
  342. package/dist/utils/wait-for-css-transition.js.map +0 -1
  343. package/dist/utils/wait.js.map +0 -1
  344. package/src/components/accordion/accordion.tsx +0 -565
  345. package/src/components/accordion/demos/card.demo.tsx +0 -113
  346. package/src/components/accordion/demos/multiple.demo.tsx +0 -56
  347. package/src/components/accordion/demos/overview.demo.tsx +0 -56
  348. package/src/components/breadcrumbs/demos/basic.demo.tsx +0 -17
  349. package/src/components/breadcrumbs/demos/separator.demo.tsx +0 -18
  350. package/src/components/button/README.md +0 -44
  351. package/src/components/button/button.tsx +0 -286
  352. package/src/components/button/demos/aliases.demo.tsx +0 -27
  353. package/src/components/button/demos/basic.demo.tsx +0 -30
  354. package/src/components/button/demos/states.demo.tsx +0 -52
  355. package/src/components/combobox/demos/overview.demo.tsx +0 -199
  356. package/src/components/glyph/README.md +0 -72
  357. package/src/components/glyph/glyph.tsx +0 -110
  358. package/src/components/listbox/demos/overview.demo.tsx +0 -101
  359. package/src/components/menu/README.md +0 -96
  360. package/src/components/menu/demos/bubbling.demo.tsx +0 -34
  361. package/src/components/menu/demos/overview.demo.tsx +0 -76
  362. package/src/components/popover/demos/overview.demo.tsx +0 -143
  363. package/src/components/select/demos/deconstructed.demo.tsx +0 -95
  364. package/src/components/select/demos/overview.demo.tsx +0 -51
  365. package/src/components/separator/separator.ts +0 -19
  366. package/src/components/tabs/README.md +0 -105
  367. package/src/components/tabs/tabs.tsx +0 -504
  368. package/src/theme/README.md +0 -103
  369. package/src/theme/contract.ts +0 -215
  370. package/src/theme/glyph-contract.ts +0 -59
  371. package/src/theme/presets/rmx-01/glyphs.tsx +0 -308
  372. package/src/theme/presets/rmx-01/index.ts +0 -123
  373. package/src/theme/runtime.ts +0 -119
  374. package/src/theme/theme.ts +0 -15
  375. package/src/utils/scroll-lock/README.md +0 -33
  376. /package/dist/{components/breadcrumbs/breadcrumbs.d.ts → breadcrumbs/index.d.ts} +0 -0
  377. /package/dist/{utils → listbox}/flash-attribute.d.ts +0 -0
  378. /package/dist/{utils → listbox}/flash-attribute.js +0 -0
  379. /package/dist/{components/menu → menu}/hover-aim.d.ts +0 -0
  380. /package/dist/{components/menu → menu}/hover-aim.js +0 -0
  381. /package/dist/{interactions/outside-click/outside-click-mixin.d.ts → popover/outside-click.d.ts} +0 -0
  382. /package/dist/{interactions/keydown → select}/keydown.d.ts +0 -0
  383. /package/dist/{interactions/keydown → select}/keydown.js +0 -0
  384. /package/dist/{interactions/typeahead/typeahead-mixin.d.ts → shared/typeahead.d.ts} +0 -0
  385. /package/dist/{utils → shared}/wait-for-css-transition.d.ts +0 -0
  386. /package/dist/{utils → shared}/wait-for-css-transition.js +0 -0
  387. /package/dist/{utils → shared}/wait.d.ts +0 -0
  388. /package/dist/{utils → shared}/wait.js +0 -0
  389. /package/src/{utils → listbox}/flash-attribute.ts +0 -0
  390. /package/src/{components/menu → menu}/hover-aim.ts +0 -0
  391. /package/src/{interactions/outside-click/outside-click-mixin.ts → popover/outside-click.ts} +0 -0
  392. /package/src/{interactions/keydown → select}/keydown.ts +0 -0
  393. /package/src/{interactions/typeahead/typeahead-mixin.ts → shared/typeahead.ts} +0 -0
  394. /package/src/{utils → shared}/wait-for-css-transition.ts +0 -0
  395. /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
+ }
@@ -1,8 +1,8 @@
1
1
  # anchor
2
2
 
3
- `anchor` positions a floating element against an anchor element and keeps it constrained to the viewport. Use it for custom floating surfaces that need placement, flipping, offsets, and optional relative alignment.
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'
@@ -49,11 +49,54 @@ popover.addEventListener('beforetoggle', (event) => {
49
49
  })
50
50
  ```
51
51
 
52
- ## `anchor.*`
52
+ Anchor to coordinates when the surface should open at a pointer location.
53
53
 
54
- - `anchor(floatingElement, anchorElement, options)`: positions `floatingElement` against `anchorElement`, starts animation-frame polling for geometry changes, and returns a cleanup function.
54
+ ```tsx
55
+ let cleanup = anchor(popover, { x: event.clientX, y: event.clientY }, { placement: 'bottom-start' })
56
+ ```
57
+
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`
94
+
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.
55
96
  - `AnchorOptions`: placement, inset, relative alignment, and offset options.
97
+ - `AnchorPoint`: viewport coordinate target with `x`, `y`, and optional `width`/`height`.
56
98
  - `AnchorPlacement`: exported placement names for the main sides and top/bottom start/end alignment.
99
+ - `AnchorTarget`: an `HTMLElement` or `AnchorPoint`.
57
100
 
58
101
  ## Placements
59
102
 
@@ -149,5 +192,5 @@ anchor(listbox, trigger, {
149
192
  - Oversized inset surfaces with `relativeTo` preserve alignment by scrolling the nearest scrollable descendant when possible.
150
193
  - `offset`, `offsetX`, and `offsetY` may be numbers or functions that receive the floating element.
151
194
  - `relativeTo` lets a surface align to an inner element, which is useful for selected options inside popovers.
152
- - `anchor` polls on animation frames for anchor or floating geometry changes and repositions when either changes.
195
+ - `anchor` polls on animation frames for anchor target or floating geometry changes and repositions when either changes.
153
196
  - The returned cleanup function cancels animation-frame polling.
@@ -24,6 +24,15 @@ export type AnchorPlacement =
24
24
 
25
25
  type AnchorOffsetValue = number | ((floating: HTMLElement) => number)
26
26
 
27
+ export interface AnchorPoint {
28
+ height?: number
29
+ width?: number
30
+ x: number
31
+ y: number
32
+ }
33
+
34
+ export type AnchorTarget = HTMLElement | AnchorPoint
35
+
27
36
  export type AnchorOptions = {
28
37
  placement?: ExtendedAnchorPlacement
29
38
  inset?: boolean
@@ -125,6 +134,39 @@ function resolveOffsetValue(offset: AnchorOffsetValue | undefined, floating: HTM
125
134
  return offset ?? 0
126
135
  }
127
136
 
137
+ function isAnchorPoint(value: unknown): value is AnchorPoint {
138
+ if (typeof value !== 'object' || value === null) {
139
+ return false
140
+ }
141
+
142
+ if (!('x' in value) || !('y' in value)) {
143
+ return false
144
+ }
145
+
146
+ let width = 'width' in value ? value.width : undefined
147
+ let height = 'height' in value ? value.height : undefined
148
+
149
+ return (
150
+ typeof value.x === 'number' &&
151
+ typeof value.y === 'number' &&
152
+ (width === undefined || typeof width === 'number') &&
153
+ (height === undefined || typeof height === 'number')
154
+ )
155
+ }
156
+
157
+ function readAnchorRect(anchorTarget: AnchorTarget) {
158
+ if (anchorTarget instanceof HTMLElement) {
159
+ return anchorTarget.getBoundingClientRect()
160
+ }
161
+
162
+ return new DOMRect(
163
+ anchorTarget.x,
164
+ anchorTarget.y,
165
+ anchorTarget.width ?? 0,
166
+ anchorTarget.height ?? 0,
167
+ )
168
+ }
169
+
128
170
  function calculatePosition(
129
171
  placement: ExtendedAnchorPlacement,
130
172
  anchorRect: DOMRect,
@@ -468,7 +510,7 @@ function getFlippedPlacement(
468
510
  placementHeight: number,
469
511
  collisionWidth: number,
470
512
  collisionHeight: number,
471
- anchor: HTMLElement,
513
+ anchorIsAbsolutePositioned: boolean,
472
514
  inset: boolean,
473
515
  offset: number,
474
516
  offsetX: number,
@@ -476,11 +518,9 @@ function getFlippedPlacement(
476
518
  relativeOffsetX?: number | null,
477
519
  relativeOffsetY?: number | null,
478
520
  ) {
479
- let computedStyle = getComputedStyle(anchor)
480
- let isAbsolutePositioned = computedStyle.position !== 'fixed'
481
521
  let hasScroll = window.scrollY > 0
482
522
 
483
- if (placement.startsWith('top') && isAbsolutePositioned && hasScroll) {
523
+ if (placement.startsWith('top') && anchorIsAbsolutePositioned && hasScroll) {
484
524
  if (anchorRect.top - placementHeight < 0) {
485
525
  return placement
486
526
  }
@@ -641,7 +681,7 @@ function solveRelativeAlignmentAxis(options: {
641
681
 
642
682
  export function anchor(
643
683
  floating: HTMLElement,
644
- anchorElement: HTMLElement,
684
+ anchorTarget: AnchorTarget,
645
685
  options: AnchorOptions = {},
646
686
  ): () => void {
647
687
  let lastAnchorRect: DOMRect
@@ -651,8 +691,8 @@ export function anchor(
651
691
  throw new TypeError('anchor() expected a floating HTMLElement')
652
692
  }
653
693
 
654
- if (!(anchorElement instanceof HTMLElement)) {
655
- throw new TypeError('anchor() expected an anchor HTMLElement')
694
+ if (!(anchorTarget instanceof HTMLElement) && !isAnchorPoint(anchorTarget)) {
695
+ throw new TypeError('anchor() expected an anchor HTMLElement or coordinates')
656
696
  }
657
697
 
658
698
  let {
@@ -664,12 +704,13 @@ export function anchor(
664
704
  offsetY: rawOffsetY = 0,
665
705
  } = options
666
706
 
667
- let isFixed =
668
- floating.hasAttribute('popover') || getComputedStyle(anchorElement).position === 'fixed'
707
+ let anchorIsAbsolutePositioned =
708
+ anchorTarget instanceof HTMLElement && getComputedStyle(anchorTarget).position !== 'fixed'
709
+ let isFixed = floating.hasAttribute('popover') || !anchorIsAbsolutePositioned
669
710
  let animationFrameId = 0
670
711
 
671
712
  function updatePosition(
672
- anchorRect = anchorElement.getBoundingClientRect(),
713
+ anchorRect = readAnchorRect(anchorTarget),
673
714
  naturalDimensions = getFloatingDimensions(floating, relativeTo, {
674
715
  ignoreInlineMaxSize: true,
675
716
  }),
@@ -695,7 +736,7 @@ export function anchor(
695
736
  placementHeight,
696
737
  naturalDimensions.width,
697
738
  naturalDimensions.height,
698
- anchorElement,
739
+ anchorIsAbsolutePositioned,
699
740
  inset,
700
741
  offset,
701
742
  offsetX,
@@ -872,7 +913,7 @@ export function anchor(
872
913
  updatePosition()
873
914
 
874
915
  function pollForPositionChanges() {
875
- let currentRect = anchorElement.getBoundingClientRect()
916
+ let currentRect = readAnchorRect(anchorTarget)
876
917
  let currentDimensions = getFloatingDimensions(floating, relativeTo)
877
918
  if (
878
919
  hasRectChanged(currentRect, lastAnchorRect) ||