foldkit-primitives 0.15.3 → 0.16.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 (422) hide show
  1. package/dist/device/fullscreen.d.ts +28 -0
  2. package/dist/device/fullscreen.d.ts.map +1 -0
  3. package/dist/device/fullscreen.js +69 -0
  4. package/dist/device/fullscreen.js.map +1 -0
  5. package/dist/device/geolocation.d.ts +56 -0
  6. package/dist/device/geolocation.d.ts.map +1 -0
  7. package/dist/device/geolocation.js +87 -0
  8. package/dist/device/geolocation.js.map +1 -0
  9. package/dist/device/index.d.ts +5 -0
  10. package/dist/device/index.js +6 -0
  11. package/dist/device/media-devices.d.ts +88 -0
  12. package/dist/device/media-devices.d.ts.map +1 -0
  13. package/dist/device/media-devices.js +117 -0
  14. package/dist/device/media-devices.js.map +1 -0
  15. package/dist/device/media-stream.d.ts +93 -0
  16. package/dist/device/media-stream.d.ts.map +1 -0
  17. package/dist/device/media-stream.js +106 -0
  18. package/dist/device/media-stream.js.map +1 -0
  19. package/dist/device/permissions.d.ts +106 -0
  20. package/dist/device/permissions.d.ts.map +1 -0
  21. package/dist/device/permissions.js +143 -0
  22. package/dist/device/permissions.js.map +1 -0
  23. package/dist/dom/autofocus.d.ts +15 -0
  24. package/dist/dom/autofocus.d.ts.map +1 -0
  25. package/dist/dom/autofocus.js +22 -0
  26. package/dist/dom/autofocus.js.map +1 -0
  27. package/dist/dom/clipboard.d.ts +30 -0
  28. package/dist/dom/clipboard.d.ts.map +1 -0
  29. package/dist/dom/clipboard.js +50 -0
  30. package/dist/dom/clipboard.js.map +1 -0
  31. package/dist/dom/editable-text.d.ts +72 -0
  32. package/dist/dom/editable-text.d.ts.map +1 -0
  33. package/dist/dom/editable-text.js +232 -0
  34. package/dist/dom/editable-text.js.map +1 -0
  35. package/dist/dom/fluid-hover.d.ts +93 -0
  36. package/dist/dom/fluid-hover.d.ts.map +1 -0
  37. package/dist/dom/fluid-hover.js +294 -0
  38. package/dist/dom/fluid-hover.js.map +1 -0
  39. package/dist/dom/focus-scope.d.ts +21 -0
  40. package/dist/dom/focus-scope.d.ts.map +1 -0
  41. package/dist/dom/focus-scope.js +93 -0
  42. package/dist/dom/focus-scope.js.map +1 -0
  43. package/dist/dom/follow-tab-stop.d.ts +11 -0
  44. package/dist/dom/follow-tab-stop.d.ts.map +1 -0
  45. package/dist/dom/follow-tab-stop.js +54 -0
  46. package/dist/dom/follow-tab-stop.js.map +1 -0
  47. package/dist/dom/image-decode.d.ts +27 -0
  48. package/dist/dom/image-decode.d.ts.map +1 -0
  49. package/dist/dom/image-decode.js +50 -0
  50. package/dist/dom/image-decode.js.map +1 -0
  51. package/dist/dom/index.d.ts +24 -0
  52. package/dist/dom/index.js +25 -0
  53. package/dist/dom/input-mask.d.ts +35 -0
  54. package/dist/dom/input-mask.d.ts.map +1 -0
  55. package/dist/dom/input-mask.js +90 -0
  56. package/dist/dom/input-mask.js.map +1 -0
  57. package/dist/dom/keep-in-view.d.ts +16 -0
  58. package/dist/dom/keep-in-view.d.ts.map +1 -0
  59. package/dist/dom/keep-in-view.js +38 -0
  60. package/dist/dom/keep-in-view.js.map +1 -0
  61. package/dist/dom/keyboard-inset.d.ts +29 -0
  62. package/dist/dom/keyboard-inset.d.ts.map +1 -0
  63. package/dist/dom/keyboard-inset.js +45 -0
  64. package/dist/dom/keyboard-inset.js.map +1 -0
  65. package/dist/dom/layers.d.ts +6 -0
  66. package/dist/dom/layers.d.ts.map +1 -0
  67. package/dist/dom/layers.js +35 -0
  68. package/dist/dom/layers.js.map +1 -0
  69. package/dist/dom/measure.d.ts +42 -0
  70. package/dist/dom/measure.d.ts.map +1 -0
  71. package/dist/dom/measure.js +123 -0
  72. package/dist/dom/measure.js.map +1 -0
  73. package/dist/dom/move.d.ts +45 -0
  74. package/dist/dom/move.d.ts.map +1 -0
  75. package/dist/dom/move.js +96 -0
  76. package/dist/dom/move.js.map +1 -0
  77. package/dist/dom/pointed-links.d.ts +13 -0
  78. package/dist/dom/pointed-links.d.ts.map +1 -0
  79. package/dist/dom/pointed-links.js +59 -0
  80. package/dist/dom/pointed-links.js.map +1 -0
  81. package/dist/dom/pointer-drag.d.ts +132 -0
  82. package/dist/dom/pointer-drag.d.ts.map +1 -0
  83. package/dist/dom/pointer-drag.js +307 -0
  84. package/dist/dom/pointer-drag.js.map +1 -0
  85. package/dist/dom/pointer-position.d.ts +133 -0
  86. package/dist/dom/pointer-position.d.ts.map +1 -0
  87. package/dist/dom/pointer-position.js +173 -0
  88. package/dist/dom/pointer-position.js.map +1 -0
  89. package/dist/dom/script-loader.d.ts +12 -0
  90. package/dist/dom/script-loader.d.ts.map +1 -0
  91. package/dist/dom/script-loader.js +54 -0
  92. package/dist/dom/script-loader.js.map +1 -0
  93. package/dist/dom/scroll-bars.d.ts +52 -0
  94. package/dist/dom/scroll-bars.d.ts.map +1 -0
  95. package/dist/dom/scroll-bars.js +259 -0
  96. package/dist/dom/scroll-bars.js.map +1 -0
  97. package/dist/dom/scroll-settle.d.ts +33 -0
  98. package/dist/dom/scroll-settle.d.ts.map +1 -0
  99. package/dist/dom/scroll-settle.js +84 -0
  100. package/dist/dom/scroll-settle.js.map +1 -0
  101. package/dist/dom/scroll.d.ts +21 -0
  102. package/dist/dom/scroll.d.ts.map +1 -0
  103. package/dist/dom/scroll.js +141 -0
  104. package/dist/dom/scroll.js.map +1 -0
  105. package/dist/dom/share.d.ts +19 -0
  106. package/dist/dom/share.d.ts.map +1 -0
  107. package/dist/dom/share.js +41 -0
  108. package/dist/dom/share.js.map +1 -0
  109. package/dist/dom/swipe.d.ts +121 -0
  110. package/dist/dom/swipe.d.ts.map +1 -0
  111. package/dist/dom/swipe.js +291 -0
  112. package/dist/dom/swipe.js.map +1 -0
  113. package/dist/dom/targets.d.ts +45 -0
  114. package/dist/dom/targets.d.ts.map +1 -0
  115. package/dist/dom/targets.js +70 -0
  116. package/dist/dom/targets.js.map +1 -0
  117. package/dist/dom/track-box.d.ts +61 -0
  118. package/dist/dom/track-box.d.ts.map +1 -0
  119. package/dist/dom/track-box.js +131 -0
  120. package/dist/dom/track-box.js.map +1 -0
  121. package/dist/events/active-element.d.ts +15 -0
  122. package/dist/events/active-element.d.ts.map +1 -0
  123. package/dist/events/active-element.js +33 -0
  124. package/dist/events/active-element.js.map +1 -0
  125. package/dist/events/hotkeys.d.ts +22 -0
  126. package/dist/events/hotkeys.d.ts.map +1 -0
  127. package/dist/events/hotkeys.js +56 -0
  128. package/dist/events/hotkeys.js.map +1 -0
  129. package/dist/events/idle.d.ts +29 -0
  130. package/dist/events/idle.d.ts.map +1 -0
  131. package/dist/events/idle.js +51 -0
  132. package/dist/events/idle.js.map +1 -0
  133. package/dist/events/index.d.ts +9 -0
  134. package/dist/events/index.js +10 -0
  135. package/dist/{input-modality-BY-bSrEc.d.mts → events/input-modality.d.ts} +9 -12
  136. package/dist/events/input-modality.d.ts.map +1 -0
  137. package/dist/{input-modality-BXD383jg.mjs → events/input-modality.js} +3 -4
  138. package/dist/events/input-modality.js.map +1 -0
  139. package/dist/events/keyboard.d.ts +30 -0
  140. package/dist/events/keyboard.d.ts.map +1 -0
  141. package/dist/events/keyboard.js +55 -0
  142. package/dist/events/keyboard.js.map +1 -0
  143. package/dist/events/pointer.d.ts +15 -0
  144. package/dist/events/pointer.d.ts.map +1 -0
  145. package/dist/events/pointer.js +28 -0
  146. package/dist/events/pointer.js.map +1 -0
  147. package/dist/events/scroll.d.ts +16 -0
  148. package/dist/events/scroll.d.ts.map +1 -0
  149. package/dist/events/scroll.js +29 -0
  150. package/dist/events/scroll.js.map +1 -0
  151. package/dist/events/visibility.d.ts +25 -0
  152. package/dist/events/visibility.d.ts.map +1 -0
  153. package/dist/events/visibility.js +28 -0
  154. package/dist/events/visibility.js.map +1 -0
  155. package/dist/events/window-size.d.ts +30 -0
  156. package/dist/events/window-size.d.ts.map +1 -0
  157. package/dist/events/window-size.js +63 -0
  158. package/dist/events/window-size.js.map +1 -0
  159. package/dist/index.d.ts +9 -0
  160. package/dist/index.js +10 -0
  161. package/dist/interaction/bundle-behavior.d.ts +37 -0
  162. package/dist/interaction/bundle-behavior.d.ts.map +1 -0
  163. package/dist/interaction/bundle-behavior.js +34 -0
  164. package/dist/interaction/bundle-behavior.js.map +1 -0
  165. package/dist/interaction/dismiss-layer.d.ts +100 -0
  166. package/dist/interaction/dismiss-layer.d.ts.map +1 -0
  167. package/dist/interaction/dismiss-layer.js +140 -0
  168. package/dist/interaction/dismiss-layer.js.map +1 -0
  169. package/dist/interaction/editable-text.d.ts +13 -0
  170. package/dist/interaction/editable-text.d.ts.map +1 -0
  171. package/dist/interaction/editable-text.js +17 -0
  172. package/dist/interaction/editable-text.js.map +1 -0
  173. package/dist/interaction/focus-scope.d.ts +21 -0
  174. package/dist/interaction/focus-scope.d.ts.map +1 -0
  175. package/dist/interaction/focus-scope.js +25 -0
  176. package/dist/interaction/focus-scope.js.map +1 -0
  177. package/dist/interaction/focus-visible.d.ts +9 -0
  178. package/dist/interaction/focus-visible.d.ts.map +1 -0
  179. package/dist/interaction/focus-visible.js +10 -0
  180. package/dist/interaction/focus-visible.js.map +1 -0
  181. package/dist/interaction/grid-navigation.d.ts +73 -0
  182. package/dist/interaction/grid-navigation.d.ts.map +1 -0
  183. package/dist/interaction/grid-navigation.js +137 -0
  184. package/dist/interaction/grid-navigation.js.map +1 -0
  185. package/dist/interaction/index.d.ts +21 -0
  186. package/dist/interaction/index.js +21 -0
  187. package/dist/interaction/layers.d.ts +12 -0
  188. package/dist/interaction/layers.d.ts.map +1 -0
  189. package/dist/interaction/layers.js +14 -0
  190. package/dist/interaction/layers.js.map +1 -0
  191. package/dist/interaction/list-navigation.d.ts +105 -0
  192. package/dist/interaction/list-navigation.d.ts.map +1 -0
  193. package/dist/interaction/list-navigation.js +168 -0
  194. package/dist/interaction/list-navigation.js.map +1 -0
  195. package/dist/interaction/live-announce.d.ts +70 -0
  196. package/dist/interaction/live-announce.d.ts.map +1 -0
  197. package/dist/interaction/live-announce.js +115 -0
  198. package/dist/interaction/live-announce.js.map +1 -0
  199. package/dist/interaction/long-press.d.ts +102 -0
  200. package/dist/interaction/long-press.d.ts.map +1 -0
  201. package/dist/interaction/long-press.js +115 -0
  202. package/dist/interaction/long-press.js.map +1 -0
  203. package/dist/interaction/move.d.ts +10 -0
  204. package/dist/interaction/move.d.ts.map +1 -0
  205. package/dist/interaction/move.js +17 -0
  206. package/dist/interaction/move.js.map +1 -0
  207. package/dist/interaction/overlay.d.ts +45 -0
  208. package/dist/interaction/overlay.d.ts.map +1 -0
  209. package/dist/interaction/overlay.js +57 -0
  210. package/dist/interaction/overlay.js.map +1 -0
  211. package/dist/interaction/placing.d.ts +86 -0
  212. package/dist/interaction/placing.d.ts.map +1 -0
  213. package/dist/interaction/placing.js +239 -0
  214. package/dist/interaction/placing.js.map +1 -0
  215. package/dist/interaction/pointer-drag.d.ts +23 -0
  216. package/dist/interaction/pointer-drag.d.ts.map +1 -0
  217. package/dist/interaction/pointer-drag.js +21 -0
  218. package/dist/interaction/pointer-drag.js.map +1 -0
  219. package/dist/interaction/press.d.ts +152 -0
  220. package/dist/interaction/press.d.ts.map +1 -0
  221. package/dist/interaction/press.js +229 -0
  222. package/dist/interaction/press.js.map +1 -0
  223. package/dist/interaction/roving-tabindex.d.ts +85 -0
  224. package/dist/interaction/roving-tabindex.d.ts.map +1 -0
  225. package/dist/interaction/roving-tabindex.js +142 -0
  226. package/dist/interaction/roving-tabindex.js.map +1 -0
  227. package/dist/interaction/selection.d.ts +72 -0
  228. package/dist/interaction/selection.d.ts.map +1 -0
  229. package/dist/interaction/selection.js +129 -0
  230. package/dist/interaction/selection.js.map +1 -0
  231. package/dist/interaction/targets.d.ts +15 -0
  232. package/dist/interaction/targets.d.ts.map +1 -0
  233. package/dist/interaction/targets.js +20 -0
  234. package/dist/interaction/targets.js.map +1 -0
  235. package/dist/interaction/tree-navigation.d.ts +111 -0
  236. package/dist/interaction/tree-navigation.d.ts.map +1 -0
  237. package/dist/interaction/tree-navigation.js +207 -0
  238. package/dist/interaction/tree-navigation.js.map +1 -0
  239. package/dist/interaction/typeahead.d.ts +73 -0
  240. package/dist/interaction/typeahead.d.ts.map +1 -0
  241. package/dist/interaction/typeahead.js +113 -0
  242. package/dist/interaction/typeahead.js.map +1 -0
  243. package/dist/internal.d.ts +16 -0
  244. package/dist/internal.d.ts.map +1 -0
  245. package/dist/{internal-DP-xLKbT.mjs → internal.js} +8 -7
  246. package/dist/internal.js.map +1 -0
  247. package/dist/media/breakpoints.d.ts +37 -0
  248. package/dist/media/breakpoints.d.ts.map +1 -0
  249. package/dist/media/breakpoints.js +64 -0
  250. package/dist/media/breakpoints.js.map +1 -0
  251. package/dist/media/index.d.ts +3 -0
  252. package/dist/media/index.js +4 -0
  253. package/dist/media/mediaquery.d.ts +40 -0
  254. package/dist/media/mediaquery.d.ts.map +1 -0
  255. package/dist/media/mediaquery.js +42 -0
  256. package/dist/media/mediaquery.js.map +1 -0
  257. package/dist/media/platform.d.ts +30 -0
  258. package/dist/media/platform.d.ts.map +1 -0
  259. package/dist/media/platform.js +50 -0
  260. package/dist/media/platform.js.map +1 -0
  261. package/dist/motion/index.d.ts +5 -0
  262. package/dist/motion/index.js +5 -0
  263. package/dist/motion/motion.d.ts +16 -0
  264. package/dist/motion/motion.d.ts.map +1 -0
  265. package/dist/motion/motion.js +25 -0
  266. package/dist/motion/motion.js.map +1 -0
  267. package/dist/motion/presence.d.ts +37 -0
  268. package/dist/motion/presence.d.ts.map +1 -0
  269. package/dist/motion/presence.js +65 -0
  270. package/dist/motion/presence.js.map +1 -0
  271. package/dist/motion/spring.d.ts +50 -0
  272. package/dist/motion/spring.d.ts.map +1 -0
  273. package/dist/motion/spring.js +92 -0
  274. package/dist/motion/spring.js.map +1 -0
  275. package/dist/motion/tween.d.ts +44 -0
  276. package/dist/motion/tween.d.ts.map +1 -0
  277. package/dist/motion/tween.js +65 -0
  278. package/dist/motion/tween.js.map +1 -0
  279. package/dist/net/broadcast.d.ts +39 -0
  280. package/dist/net/broadcast.d.ts.map +1 -0
  281. package/dist/net/broadcast.js +73 -0
  282. package/dist/net/broadcast.js.map +1 -0
  283. package/dist/net/index.d.ts +5 -0
  284. package/dist/net/index.js +6 -0
  285. package/dist/net/online.d.ts +24 -0
  286. package/dist/net/online.d.ts.map +1 -0
  287. package/dist/net/online.js +26 -0
  288. package/dist/net/online.js.map +1 -0
  289. package/dist/net/sharedHost.d.ts +64 -0
  290. package/dist/net/sharedHost.d.ts.map +1 -0
  291. package/dist/net/sharedHost.js +124 -0
  292. package/dist/net/sharedHost.js.map +1 -0
  293. package/dist/net/sse.d.ts +115 -0
  294. package/dist/net/sse.d.ts.map +1 -0
  295. package/dist/net/sse.js +138 -0
  296. package/dist/net/sse.js.map +1 -0
  297. package/dist/net/websocket.d.ts +172 -0
  298. package/dist/net/websocket.d.ts.map +1 -0
  299. package/dist/net/websocket.js +199 -0
  300. package/dist/net/websocket.js.map +1 -0
  301. package/dist/observers/bounds.d.ts +24 -0
  302. package/dist/observers/bounds.d.ts.map +1 -0
  303. package/dist/observers/bounds.js +51 -0
  304. package/dist/observers/bounds.js.map +1 -0
  305. package/dist/observers/index.d.ts +4 -0
  306. package/dist/observers/index.js +5 -0
  307. package/dist/observers/intersection.d.ts +18 -0
  308. package/dist/observers/intersection.d.ts.map +1 -0
  309. package/dist/observers/intersection.js +33 -0
  310. package/dist/observers/intersection.js.map +1 -0
  311. package/dist/observers/mutation.d.ts +25 -0
  312. package/dist/observers/mutation.d.ts.map +1 -0
  313. package/dist/observers/mutation.js +53 -0
  314. package/dist/observers/mutation.js.map +1 -0
  315. package/dist/observers/resize.d.ts +18 -0
  316. package/dist/observers/resize.d.ts.map +1 -0
  317. package/dist/observers/resize.js +33 -0
  318. package/dist/observers/resize.js.map +1 -0
  319. package/dist/state/history.d.ts +115 -0
  320. package/dist/state/history.d.ts.map +1 -0
  321. package/dist/state/history.js +167 -0
  322. package/dist/state/history.js.map +1 -0
  323. package/dist/state/index.d.ts +6 -0
  324. package/dist/state/index.js +7 -0
  325. package/dist/state/locale.d.ts +27 -0
  326. package/dist/state/locale.d.ts.map +1 -0
  327. package/dist/state/locale.js +25 -0
  328. package/dist/state/locale.js.map +1 -0
  329. package/dist/state/pagination.d.ts +53 -0
  330. package/dist/state/pagination.d.ts.map +1 -0
  331. package/dist/state/pagination.js +72 -0
  332. package/dist/state/pagination.js.map +1 -0
  333. package/dist/state/range.d.ts +9 -0
  334. package/dist/state/range.d.ts.map +1 -0
  335. package/dist/state/range.js +18 -0
  336. package/dist/state/range.js.map +1 -0
  337. package/dist/state/selection.d.ts +47 -0
  338. package/dist/state/selection.d.ts.map +1 -0
  339. package/dist/state/selection.js +39 -0
  340. package/dist/state/selection.js.map +1 -0
  341. package/dist/state/virtual.d.ts +201 -0
  342. package/dist/state/virtual.d.ts.map +1 -0
  343. package/dist/state/{index.mjs → virtual.js} +11 -313
  344. package/dist/state/virtual.js.map +1 -0
  345. package/dist/time/debounce.d.ts +43 -0
  346. package/dist/time/debounce.d.ts.map +1 -0
  347. package/dist/time/debounce.js +65 -0
  348. package/dist/time/debounce.js.map +1 -0
  349. package/dist/time/index.d.ts +6 -0
  350. package/dist/time/index.js +7 -0
  351. package/dist/time/interval.d.ts +37 -0
  352. package/dist/time/interval.d.ts.map +1 -0
  353. package/dist/time/interval.js +52 -0
  354. package/dist/time/interval.js.map +1 -0
  355. package/dist/time/relative.d.ts +8 -0
  356. package/dist/time/relative.d.ts.map +1 -0
  357. package/dist/time/relative.js +27 -0
  358. package/dist/time/relative.js.map +1 -0
  359. package/dist/time/throttle.d.ts +38 -0
  360. package/dist/time/throttle.d.ts.map +1 -0
  361. package/dist/time/throttle.js +39 -0
  362. package/dist/time/throttle.js.map +1 -0
  363. package/dist/time/ticks.d.ts +21 -0
  364. package/dist/time/ticks.d.ts.map +1 -0
  365. package/dist/time/ticks.js +30 -0
  366. package/dist/time/ticks.js.map +1 -0
  367. package/dist/time/timer.d.ts +32 -0
  368. package/dist/time/timer.d.ts.map +1 -0
  369. package/dist/time/timer.js +50 -0
  370. package/dist/time/timer.js.map +1 -0
  371. package/package.json +31 -31
  372. package/dist/device/index.d.mts +0 -345
  373. package/dist/device/index.d.mts.map +0 -1
  374. package/dist/device/index.mjs +0 -498
  375. package/dist/device/index.mjs.map +0 -1
  376. package/dist/dom/index.d.mts +0 -750
  377. package/dist/dom/index.d.mts.map +0 -1
  378. package/dist/dom/index.mjs +0 -1857
  379. package/dist/dom/index.mjs.map +0 -1
  380. package/dist/editable-text-1D31qthY.d.mts +0 -319
  381. package/dist/editable-text-1D31qthY.d.mts.map +0 -1
  382. package/dist/events/index.d.mts +0 -184
  383. package/dist/events/index.d.mts.map +0 -1
  384. package/dist/events/index.mjs +0 -315
  385. package/dist/events/index.mjs.map +0 -1
  386. package/dist/follow-tab-stop-Caog2qg1.mjs +0 -863
  387. package/dist/follow-tab-stop-Caog2qg1.mjs.map +0 -1
  388. package/dist/index-CmmxqSEi.d.mts +0 -149
  389. package/dist/index-CmmxqSEi.d.mts.map +0 -1
  390. package/dist/index.d.mts +0 -12
  391. package/dist/index.mjs +0 -12
  392. package/dist/input-modality-BXD383jg.mjs.map +0 -1
  393. package/dist/input-modality-BY-bSrEc.d.mts.map +0 -1
  394. package/dist/interaction/index.d.mts +0 -1194
  395. package/dist/interaction/index.d.mts.map +0 -1
  396. package/dist/interaction/index.mjs +0 -2012
  397. package/dist/interaction/index.mjs.map +0 -1
  398. package/dist/internal-DP-xLKbT.mjs.map +0 -1
  399. package/dist/media/index.d.mts +0 -109
  400. package/dist/media/index.d.mts.map +0 -1
  401. package/dist/media/index.mjs +0 -149
  402. package/dist/media/index.mjs.map +0 -1
  403. package/dist/motion/index.d.mts +0 -2
  404. package/dist/motion/index.mjs +0 -1
  405. package/dist/motion-DmFDppRn.mjs +0 -240
  406. package/dist/motion-DmFDppRn.mjs.map +0 -1
  407. package/dist/net/index.d.mts +0 -348
  408. package/dist/net/index.d.mts.map +0 -1
  409. package/dist/net/index.mjs +0 -535
  410. package/dist/net/index.mjs.map +0 -1
  411. package/dist/observers/index.d.mts +0 -84
  412. package/dist/observers/index.d.mts.map +0 -1
  413. package/dist/observers/index.mjs +0 -159
  414. package/dist/observers/index.mjs.map +0 -1
  415. package/dist/rolldown-runtime-D7D4PA-g.mjs +0 -13
  416. package/dist/state/index.d.mts +0 -444
  417. package/dist/state/index.d.mts.map +0 -1
  418. package/dist/state/index.mjs.map +0 -1
  419. package/dist/time/index.d.mts +0 -179
  420. package/dist/time/index.d.mts.map +0 -1
  421. package/dist/time/index.mjs +0 -242
  422. package/dist/time/index.mjs.map +0 -1
@@ -0,0 +1,173 @@
1
+ import { Effect, Option, Queue, Schema, Stream } from "effect";
2
+ import * as Mount from "foldkit/mount";
3
+ // src/dom/pointer-position.ts
4
+ /**
5
+ * A place in an element's padding box, in CSS pixels from its top left
6
+ * corner, and the pointer's pressure there (0 to 1; a mouse reads 0.5 while
7
+ * a button is down). A captured pointer can be outside the box, so `x` and
8
+ * `y` can be negative or past its size.
9
+ */
10
+ const PointerPoint = Schema.Struct({
11
+ x: Schema.Number,
12
+ y: Schema.Number,
13
+ pressure: Schema.Number
14
+ });
15
+ /** The padding box's size at the event, in CSS pixels. */
16
+ const Size = {
17
+ width: Schema.Number,
18
+ height: Schema.Number
19
+ };
20
+ const PointerPressed = Schema.TaggedStruct("PointerPressed", {
21
+ ...Size,
22
+ point: PointerPoint,
23
+ /** `mouse`, `pen` or `touch`, as the browser names it. */
24
+ pointerType: Schema.String
25
+ });
26
+ const PointerMoved = Schema.TaggedStruct("PointerMoved", {
27
+ ...Size,
28
+ /** Where the pointer is now. */
29
+ point: PointerPoint,
30
+ /**
31
+ * Every place it passed since the last move, ending with `point`: the
32
+ * browser's coalesced events, so a fast stroke keeps its curve. Just
33
+ * `point` where the browser coalesces none.
34
+ */
35
+ points: Schema.Array(PointerPoint)
36
+ });
37
+ const PointerReleased = Schema.TaggedStruct("PointerReleased", {
38
+ /** `false` when the pointer was cancelled, lost its capture, or pressed again unreleased. */
39
+ completed: Schema.Boolean });
40
+ /**
41
+ * The padding box of an element whose border box is `rect`: inside its
42
+ * border, padding included. An absolutely positioned child (a thumb, a
43
+ * stroke) is laid out against it, so a place read here is where that child
44
+ * sits, whatever padding a stylist adds.
45
+ */
46
+ const paddingBoxOf = (layout) => {
47
+ const { rect, border } = layout;
48
+ return {
49
+ left: rect.left + border.left,
50
+ top: rect.top + border.top,
51
+ width: Math.max(0, rect.width - border.left - border.right),
52
+ height: Math.max(0, rect.height - border.top - border.bottom)
53
+ };
54
+ };
55
+ const borderOf = (style) => ({
56
+ top: parseFloat(style.borderTopWidth),
57
+ right: parseFloat(style.borderRightWidth),
58
+ bottom: parseFloat(style.borderBottomWidth),
59
+ left: parseFloat(style.borderLeftWidth)
60
+ });
61
+ /**
62
+ * An element's padding box now, in the viewport, as `PointerPosition`
63
+ * measures it: for a size kept beside its places, which a `ResizeObserver`'s
64
+ * content box does not match once the element has padding. Read from the
65
+ * bounding rectangle and the computed border, since `clientWidth` and
66
+ * `clientLeft` round to whole pixels.
67
+ */
68
+ const measurePaddingBox = (element) => paddingBoxOf({
69
+ rect: element.getBoundingClientRect(),
70
+ border: borderOf(getComputedStyle(element))
71
+ });
72
+ const pointIn = (box, event) => ({
73
+ x: event.clientX - box.left,
74
+ y: event.clientY - box.top,
75
+ pressure: event.pressure
76
+ });
77
+ /**
78
+ * Where one pointer is inside an element, as a Mount, for a surface the
79
+ * pointer draws on or points into (a color area, a dial, a signature pad): a
80
+ * primary press, each move until the release, and the release, each with
81
+ * the place in the element's padding box and the box's size. The box is
82
+ * measured at each event, so an element that moved or resized is followed.
83
+ * Coordinates are raw, left to right and top down whatever the direction:
84
+ * what a place means (a share, an angle, a reading direction) is the parent's.
85
+ *
86
+ * The pointer is captured from press to release, so a drag that leaves the
87
+ * element is still heard, and the moves and the release are listened to only
88
+ * meanwhile. A press keeps the browser's own focus and text selection away,
89
+ * and a second pointer while one is down is ignored.
90
+ */
91
+ const PointerPosition = Mount.defineStream("PointerPosition", {
92
+ messages: [
93
+ PointerPressed,
94
+ PointerMoved,
95
+ PointerReleased
96
+ ],
97
+ args: {
98
+ /**
99
+ * A descendant to focus on a press, found by this selector (a thumb), so
100
+ * the keys go on from where the pointer left it.
101
+ */
102
+ focus: Schema.optionalKey(Schema.String) },
103
+ execute: ({ element, focus }) => Stream.callback((queue) => Effect.acquireRelease(Effect.sync(() => {
104
+ const offer = (fact) => Queue.offerUnsafe(queue, fact);
105
+ let held = Option.none();
106
+ const ours = (event) => event instanceof PointerEvent && Option.contains(held, event.pointerId);
107
+ const release = () => {
108
+ if (Option.isNone(held)) return;
109
+ const pointerId = held.value;
110
+ held = Option.none();
111
+ for (const [type, listener] of during) element.removeEventListener(type, listener);
112
+ try {
113
+ element.releasePointerCapture(pointerId);
114
+ } catch {}
115
+ };
116
+ const end = (completed) => (event) => {
117
+ if (!ours(event)) return;
118
+ release();
119
+ offer(PointerReleased.make({ completed }));
120
+ };
121
+ const move = (event) => {
122
+ if (!ours(event)) return;
123
+ const box = measurePaddingBox(element);
124
+ const point = pointIn(box, event);
125
+ const coalesced = event.getCoalescedEvents?.() ?? [];
126
+ offer(PointerMoved.make({
127
+ width: box.width,
128
+ height: box.height,
129
+ point,
130
+ points: coalesced.length > 0 ? coalesced.map((one) => pointIn(box, one)) : [point]
131
+ }));
132
+ };
133
+ const during = [
134
+ ["pointermove", move],
135
+ ["pointerup", end(true)],
136
+ ["pointercancel", end(false)],
137
+ ["lostpointercapture", end(false)]
138
+ ];
139
+ const down = (event) => {
140
+ if (!(event instanceof PointerEvent) || event.button !== 0) return;
141
+ if (Option.isSome(held)) {
142
+ if (!ours(event)) return;
143
+ release();
144
+ offer(PointerReleased.make({ completed: false }));
145
+ }
146
+ held = Option.some(event.pointerId);
147
+ for (const [type, listener] of during) element.addEventListener(type, listener);
148
+ try {
149
+ element.setPointerCapture(event.pointerId);
150
+ } catch {}
151
+ event.preventDefault();
152
+ if (focus !== void 0) {
153
+ const into = element.querySelector(focus);
154
+ if (into instanceof HTMLElement) into.focus();
155
+ }
156
+ const box = measurePaddingBox(element);
157
+ offer(PointerPressed.make({
158
+ width: box.width,
159
+ height: box.height,
160
+ point: pointIn(box, event),
161
+ pointerType: event.pointerType
162
+ }));
163
+ };
164
+ element.addEventListener("pointerdown", down);
165
+ return () => {
166
+ element.removeEventListener("pointerdown", down);
167
+ release();
168
+ };
169
+ }), (stop) => Effect.sync(stop)))
170
+ });
171
+ export { PointerMoved, PointerPoint, PointerPosition, PointerPressed, PointerReleased, measurePaddingBox, paddingBoxOf };
172
+
173
+ //# sourceMappingURL=pointer-position.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pointer-position.js","names":[],"sources":["../../src/dom/pointer-position.ts"],"sourcesContent":["import { Effect, Option, Queue, Schema, Stream } from 'effect'\nimport * as Mount from 'foldkit/mount'\n\n/**\n * A place in an element's padding box, in CSS pixels from its top left\n * corner, and the pointer's pressure there (0 to 1; a mouse reads 0.5 while\n * a button is down). A captured pointer can be outside the box, so `x` and\n * `y` can be negative or past its size.\n */\nexport const PointerPoint = Schema.Struct({\n x: Schema.Number,\n y: Schema.Number,\n pressure: Schema.Number,\n})\nexport type PointerPoint = typeof PointerPoint.Type\n\n/** The padding box's size at the event, in CSS pixels. */\nconst Size = { width: Schema.Number, height: Schema.Number }\n\nexport const PointerPressed = Schema.TaggedStruct('PointerPressed', {\n ...Size,\n point: PointerPoint,\n /** `mouse`, `pen` or `touch`, as the browser names it. */\n pointerType: Schema.String,\n})\nexport type PointerPressed = typeof PointerPressed.Type\n\nexport const PointerMoved = Schema.TaggedStruct('PointerMoved', {\n ...Size,\n /** Where the pointer is now. */\n point: PointerPoint,\n /**\n * Every place it passed since the last move, ending with `point`: the\n * browser's coalesced events, so a fast stroke keeps its curve. Just\n * `point` where the browser coalesces none.\n */\n points: Schema.Array(PointerPoint),\n})\nexport type PointerMoved = typeof PointerMoved.Type\n\nexport const PointerReleased = Schema.TaggedStruct('PointerReleased', {\n /** `false` when the pointer was cancelled, lost its capture, or pressed again unreleased. */\n completed: Schema.Boolean,\n})\nexport type PointerReleased = typeof PointerReleased.Type\n\nexport type PointerFact = PointerPressed | PointerMoved | PointerReleased\n\ninterface Sides {\n readonly top: number\n readonly right: number\n readonly bottom: number\n readonly left: number\n}\n\nexport interface Rect {\n readonly left: number\n readonly top: number\n readonly width: number\n readonly height: number\n}\n\n/**\n * The padding box of an element whose border box is `rect`: inside its\n * border, padding included. An absolutely positioned child (a thumb, a\n * stroke) is laid out against it, so a place read here is where that child\n * sits, whatever padding a stylist adds.\n */\nexport const paddingBoxOf = (layout: { readonly rect: Rect; readonly border: Sides }): Rect => {\n const { rect, border } = layout\n return {\n left: rect.left + border.left,\n top: rect.top + border.top,\n width: Math.max(0, rect.width - border.left - border.right),\n height: Math.max(0, rect.height - border.top - border.bottom),\n }\n}\n\nconst borderOf = (style: CSSStyleDeclaration): Sides => ({\n top: parseFloat(style.borderTopWidth),\n right: parseFloat(style.borderRightWidth),\n bottom: parseFloat(style.borderBottomWidth),\n left: parseFloat(style.borderLeftWidth),\n})\n\n/**\n * An element's padding box now, in the viewport, as `PointerPosition`\n * measures it: for a size kept beside its places, which a `ResizeObserver`'s\n * content box does not match once the element has padding. Read from the\n * bounding rectangle and the computed border, since `clientWidth` and\n * `clientLeft` round to whole pixels.\n */\nexport const measurePaddingBox = (element: Element): Rect =>\n paddingBoxOf({\n rect: element.getBoundingClientRect(),\n border: borderOf(getComputedStyle(element)),\n })\n\nconst pointIn = (box: Rect, event: PointerEvent): PointerPoint => ({\n x: event.clientX - box.left,\n y: event.clientY - box.top,\n pressure: event.pressure,\n})\n\n/**\n * Where one pointer is inside an element, as a Mount, for a surface the\n * pointer draws on or points into (a color area, a dial, a signature pad): a\n * primary press, each move until the release, and the release, each with\n * the place in the element's padding box and the box's size. The box is\n * measured at each event, so an element that moved or resized is followed.\n * Coordinates are raw, left to right and top down whatever the direction:\n * what a place means (a share, an angle, a reading direction) is the parent's.\n *\n * The pointer is captured from press to release, so a drag that leaves the\n * element is still heard, and the moves and the release are listened to only\n * meanwhile. A press keeps the browser's own focus and text selection away,\n * and a second pointer while one is down is ignored.\n */\nexport const PointerPosition = Mount.defineStream('PointerPosition', {\n messages: [PointerPressed, PointerMoved, PointerReleased],\n args: {\n /**\n * A descendant to focus on a press, found by this selector (a thumb), so\n * the keys go on from where the pointer left it.\n */\n focus: Schema.optionalKey(Schema.String),\n },\n execute: ({ element, focus }) =>\n Stream.callback<PointerFact>(queue =>\n Effect.acquireRelease(\n Effect.sync(() => {\n const offer = (fact: PointerFact) => Queue.offerUnsafe(queue, fact)\n let held: Option.Option<number> = Option.none()\n const ours = (event: Event): event is PointerEvent =>\n event instanceof PointerEvent && Option.contains(held, event.pointerId)\n\n const release = () => {\n if (Option.isNone(held)) return\n const pointerId = held.value\n held = Option.none()\n for (const [type, listener] of during) element.removeEventListener(type, listener)\n try {\n element.releasePointerCapture(pointerId)\n } catch {\n // Capture may already be gone with the pointer.\n }\n }\n const end = (completed: boolean) => (event: Event) => {\n if (!ours(event)) return\n release()\n offer(PointerReleased.make({ completed }))\n }\n const move = (event: Event) => {\n if (!ours(event)) return\n const box = measurePaddingBox(element)\n const point = pointIn(box, event)\n // Safari coalesces none and has no method for it.\n const coalesced = event.getCoalescedEvents?.() ?? []\n offer(\n PointerMoved.make({\n width: box.width,\n height: box.height,\n point,\n points: coalesced.length > 0 ? coalesced.map(one => pointIn(box, one)) : [point],\n }),\n )\n }\n const during: ReadonlyArray<readonly [string, (event: Event) => void]> = [\n ['pointermove', move],\n ['pointerup', end(true)],\n ['pointercancel', end(false)],\n ['lostpointercapture', end(false)],\n ]\n\n const down = (event: Event) => {\n if (!(event instanceof PointerEvent) || event.button !== 0) return\n if (Option.isSome(held)) {\n if (!ours(event)) return\n // The same pointer down again: its release went where nothing heard it.\n release()\n offer(PointerReleased.make({ completed: false }))\n }\n held = Option.some(event.pointerId)\n for (const [type, listener] of during) element.addEventListener(type, listener)\n try {\n element.setPointerCapture(event.pointerId)\n } catch {\n // A pointer the browser no longer tracks cannot be captured; its moves over the element still come.\n }\n // Kept from the browser's own focus and text selection, and from the mouse events a touch also sends.\n event.preventDefault()\n if (focus !== undefined) {\n const into = element.querySelector(focus)\n if (into instanceof HTMLElement) into.focus()\n }\n const box = measurePaddingBox(element)\n offer(\n PointerPressed.make({\n width: box.width,\n height: box.height,\n point: pointIn(box, event),\n pointerType: event.pointerType,\n }),\n )\n }\n element.addEventListener('pointerdown', down)\n return () => {\n element.removeEventListener('pointerdown', down)\n release()\n }\n }),\n stop => Effect.sync(stop),\n ),\n ),\n})\n"],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import { Schema } from "effect";
2
+ import { Command } from "foldkit/command";
3
+ export declare const ScriptMessage: import("foldkit/message").MessageUnion<{
4
+ readonly Loaded: {};
5
+ readonly LoadFailed: {
6
+ message: Schema.String;
7
+ };
8
+ }>;
9
+ export type ScriptMessage = typeof ScriptMessage.Type;
10
+ /** Loads a script by URL, once per URL. */
11
+ export declare const loadScript: (src: string) => Command<ScriptMessage, never, never>;
12
+ //# sourceMappingURL=script-loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"script-loader.d.ts","names":[],"sources":["../../src/dom/script-loader.ts"],"mappings":";;qBAWa,yCAAa;;;IAEV,SAAO,OAAA;;;YAEX,uBAAuB,cAAc;;qBASpC,aAAU,gBAAkB,QAAQ"}
@@ -0,0 +1,54 @@
1
+ import { Effect, Schema } from "effect";
2
+ import { defineMessageUnion } from "foldkit/message";
3
+ // src/dom/script-loader.ts
4
+ /**
5
+ * Script loading as a Command: appends a `src` script to the head unless one
6
+ * is already there. Idempotent by URL — concurrent placements collapse onto
7
+ * the first tag instead of fetching twice. Yields `Loaded` on success and
8
+ * `LoadFailed` otherwise (network error, no document), so `update` handles
9
+ * both outcomes as Messages.
10
+ */
11
+ const ScriptMessage = defineMessageUnion({
12
+ Loaded: {},
13
+ LoadFailed: { message: Schema.String }
14
+ });
15
+ const failMessage = (error) => error instanceof Error ? error.message : String(error);
16
+ const inflight = /* @__PURE__ */ new Map();
17
+ /** Loads a script by URL, once per URL. */
18
+ const loadScript = (src) => ({
19
+ name: "Script.load",
20
+ args: { src },
21
+ effect: Effect.matchEffect(Effect.tryPromise({
22
+ try: () => {
23
+ if (typeof document === "undefined") return Promise.reject(/* @__PURE__ */ new Error("script loading is unavailable"));
24
+ const running = inflight.get(src);
25
+ if (running !== void 0) return running;
26
+ if (Array.from(document.getElementsByTagName("script")).some((element) => element.getAttribute("src") === src)) return Promise.resolve();
27
+ const tracked = new Promise((resolve, reject) => {
28
+ const element = document.createElement("script");
29
+ element.src = src;
30
+ element.async = true;
31
+ element.onload = () => resolve();
32
+ element.onerror = () => {
33
+ element.remove();
34
+ reject(/* @__PURE__ */ new Error(`failed to load script: ${src}`));
35
+ };
36
+ document.head.appendChild(element);
37
+ }).then(() => {
38
+ inflight.delete(src);
39
+ }, (error) => {
40
+ inflight.delete(src);
41
+ throw error;
42
+ });
43
+ inflight.set(src, tracked);
44
+ return tracked;
45
+ },
46
+ catch: (error) => error
47
+ }), {
48
+ onFailure: (error) => Effect.succeed(ScriptMessage.LoadFailed({ message: failMessage(error) })),
49
+ onSuccess: () => Effect.succeed(ScriptMessage.Loaded())
50
+ })
51
+ });
52
+ export { ScriptMessage, loadScript };
53
+
54
+ //# sourceMappingURL=script-loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"script-loader.js","names":[],"sources":["../../src/dom/script-loader.ts"],"sourcesContent":["/**\n * Script loading as a Command: appends a `src` script to the head unless one\n * is already there. Idempotent by URL — concurrent placements collapse onto\n * the first tag instead of fetching twice. Yields `Loaded` on success and\n * `LoadFailed` otherwise (network error, no document), so `update` handles\n * both outcomes as Messages.\n */\nimport { Effect, Schema } from 'effect'\nimport type { Command } from 'foldkit/command'\nimport { defineMessageUnion } from 'foldkit/message'\n\nexport const ScriptMessage = defineMessageUnion({\n Loaded: {},\n LoadFailed: { message: Schema.String },\n})\nexport type ScriptMessage = typeof ScriptMessage.Type\n\nconst failMessage = (error: unknown): string =>\n error instanceof Error ? error.message : String(error)\n\n// Tags still fetching, by URL: concurrent loads share one tag and its fate.\nconst inflight = new Map<string, Promise<void>>()\n\n/** Loads a script by URL, once per URL. */\nexport const loadScript = (src: string): Command<ScriptMessage, never, never> => ({\n name: 'Script.load',\n args: { src },\n effect: Effect.matchEffect(\n Effect.tryPromise({\n try: () => {\n if (typeof document === 'undefined') {\n return Promise.reject(new Error('script loading is unavailable'))\n }\n // Concurrent loads share one tag and its fate, instead of racing\n // past the presence check and fetching twice: the in-flight entry\n // is checked before presence, in the same synchronous block that\n // appends, so a second load cannot slip between them.\n const running = inflight.get(src)\n if (running !== undefined) return running\n // getAttribute, not .src: the property resolves to an absolute URL\n // and would never equal the given string.\n const present = Array.from(document.getElementsByTagName('script')).some(\n element => element.getAttribute('src') === src,\n )\n if (present) return Promise.resolve()\n const completion = new Promise<void>((resolve, reject) => {\n const element = document.createElement('script')\n element.src = src\n element.async = true\n element.onload = () => resolve()\n element.onerror = () => {\n // A dead tag must not satisfy later presence checks.\n element.remove()\n reject(new Error(`failed to load script: ${src}`))\n }\n document.head.appendChild(element)\n })\n const tracked = completion.then(\n () => {\n inflight.delete(src)\n },\n (error: unknown) => {\n inflight.delete(src)\n throw error\n },\n )\n inflight.set(src, tracked)\n return tracked\n },\n catch: (error: unknown) => error,\n }),\n {\n onFailure: error => Effect.succeed(ScriptMessage.LoadFailed({ message: failMessage(error) })),\n onSuccess: () => Effect.succeed(ScriptMessage.Loaded()),\n },\n ),\n})\n"],"mappings":";;;;;;;;;;AAWA,MAAa,gBAAgB,mBAAmB;CAC9C,QAAQ,CAAC;CACT,YAAY,EAAE,SAAS,OAAO,OAAO;AACvC,CAAC;AAGD,MAAM,eAAe,UACnB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAGvD,MAAM,2BAAW,IAAI,IAA2B;;AAGhD,MAAa,cAAc,SAAuD;CAChF,MAAM;CACN,MAAM,EAAE,IAAI;CACZ,QAAQ,OAAO,YACb,OAAO,WAAW;EAChB,WAAW;GACT,IAAI,OAAO,aAAa,aACtB,OAAO,QAAQ,uBAAO,IAAI,MAAM,+BAA+B,CAAC;GAMlE,MAAM,UAAU,SAAS,IAAI,GAAG;GAChC,IAAI,YAAY,KAAA,GAAW,OAAO;GAMlC,IAHgB,MAAM,KAAK,SAAS,qBAAqB,QAAQ,CAAC,CAAC,CAAC,MAClE,YAAW,QAAQ,aAAa,KAAK,MAAM,GAEnC,GAAG,OAAO,QAAQ,QAAQ;GAapC,MAAM,UAAU,IAZO,SAAe,SAAS,WAAW;IACxD,MAAM,UAAU,SAAS,cAAc,QAAQ;IAC/C,QAAQ,MAAM;IACd,QAAQ,QAAQ;IAChB,QAAQ,eAAe,QAAQ;IAC/B,QAAQ,gBAAgB;KAEtB,QAAQ,OAAO;KACf,uBAAO,IAAI,MAAM,0BAA0B,KAAK,CAAC;IACnD;IACA,SAAS,KAAK,YAAY,OAAO;GACnC,CACyB,CAAC,CAAC,WACnB;IACJ,SAAS,OAAO,GAAG;GACrB,IACC,UAAmB;IAClB,SAAS,OAAO,GAAG;IACnB,MAAM;GACR,CACF;GACA,SAAS,IAAI,KAAK,OAAO;GACzB,OAAO;EACT;EACA,QAAQ,UAAmB;CAC7B,CAAC,GACD;EACE,YAAW,UAAS,OAAO,QAAQ,cAAc,WAAW,EAAE,SAAS,YAAY,KAAK,EAAE,CAAC,CAAC;EAC5F,iBAAiB,OAAO,QAAQ,cAAc,OAAO,CAAC;CACxD,CACF;AACF"}
@@ -0,0 +1,52 @@
1
+ import { Schema } from "effect";
2
+ import * as Mount from "foldkit/mount";
3
+ /**
4
+ * The attribute that marks a bar beside a scroller `ScrollBars` runs on, set
5
+ * to the axis it shows: `block` (the up-and-down bar) or `inline`.
6
+ */
7
+ export declare const SCROLL_BAR_ATTRIBUTE = "data-scroll-bar";
8
+ /**
9
+ * The attribute `ScrollBars` sets on its scroller while it draws the bars, so a
10
+ * style hides the native bar only then: with no Mount running (a coarse
11
+ * pointer, a page not yet hydrated) the browser's bar stays.
12
+ */
13
+ export declare const SCROLL_OVERLAID_ATTRIBUTE = "data-scroll-overlaid";
14
+ /**
15
+ * The custom properties `ScrollBars` writes on each bar, in pixels, for its
16
+ * thumb to read: how far along the bar the thumb starts, and how long it is.
17
+ * Physical: an inline bar's offset is from its left edge in either direction.
18
+ */
19
+ export declare const scrollThumb: {
20
+ readonly offset: '--fk-scroll-thumb-offset';
21
+ readonly size: '--fk-scroll-thumb-size';
22
+ };
23
+ /**
24
+ * An overlay scrollbar as a Mount, with no Message and no Model: where a
25
+ * scroller is scrolled is the browser's, and the bar only shows it.
26
+ *
27
+ * It runs on the scroller (or on an element holding it, named by `scroller`,
28
+ * when the scroller carries another Mount) and drives the bars drawn beside
29
+ * it: the scroller's parent's children marked `data-scroll-bar` (`block` or
30
+ * `inline`), which a style lays over the scroller's edge. Each bar gets `data-scrollable` while its axis has
31
+ * more to scroll, `data-shown` while the scroller scrolls or the pointer moves
32
+ * over it, until `idle` milliseconds pass with neither (or longer, while the
33
+ * pointer rests on a bar), and `data-dragging` while its thumb is dragged; and
34
+ * `--fk-scroll-thumb-offset` and `-size` (see `scrollThumb`). Pressing a bar
35
+ * off its thumb moves the thumb there, then drags it.
36
+ *
37
+ * It does nothing where the primary pointer is coarse or cannot hover, decided
38
+ * when it mounts: touch keeps the browser's bar and its physics. Otherwise the
39
+ * scroller gets `data-scroll-overlaid`, for a style to hide the native bar.
40
+ * How the bar looks, rests, widens and fades is the style's.
41
+ */
42
+ export declare const ScrollBars: Mount.MountDefinitionWithArgs<"ScrollBars", {
43
+ /** How long, in milliseconds, the bars stay after the last scroll or move. Default 600. */
44
+ idle: Schema.optional<Schema.Number>;
45
+ /**
46
+ * The scroller, as a selector within the element, when it cannot hold this
47
+ * Mount itself (another component's, with a Mount of its own); looked for
48
+ * once, when it mounts. Default: the element is the scroller.
49
+ */
50
+ scroller: Schema.optional<Schema.String>;
51
+ }, never>;
52
+ //# sourceMappingURL=scroll-bars.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scroll-bars.d.ts","names":[],"sources":["../../src/dom/scroll-bars.ts"],"mappings":";;;;;;qBAOa;;;;;;qBAOA;;;;;;qBAOA;WACX;WACA;;;;;;;;;;;;;;;;;;;;;qBA6BW,YAAU,MAAA"}
@@ -0,0 +1,259 @@
1
+ import { Effect, Schema, Stream } from "effect";
2
+ import * as Mount from "foldkit/mount";
3
+ // src/dom/scroll-bars.ts
4
+ /**
5
+ * The attribute that marks a bar beside a scroller `ScrollBars` runs on, set
6
+ * to the axis it shows: `block` (the up-and-down bar) or `inline`.
7
+ */
8
+ const SCROLL_BAR_ATTRIBUTE = "data-scroll-bar";
9
+ /**
10
+ * The attribute `ScrollBars` sets on its scroller while it draws the bars, so a
11
+ * style hides the native bar only then: with no Mount running (a coarse
12
+ * pointer, a page not yet hydrated) the browser's bar stays.
13
+ */
14
+ const SCROLL_OVERLAID_ATTRIBUTE = "data-scroll-overlaid";
15
+ /**
16
+ * The custom properties `ScrollBars` writes on each bar, in pixels, for its
17
+ * thumb to read: how far along the bar the thumb starts, and how long it is.
18
+ * Physical: an inline bar's offset is from its left edge in either direction.
19
+ */
20
+ const scrollThumb = {
21
+ offset: "--fk-scroll-thumb-offset",
22
+ size: "--fk-scroll-thumb-size"
23
+ };
24
+ /** The shortest a thumb is drawn, however long the content, so it stays a target. */
25
+ const SHORTEST = 20;
26
+ const FINE_POINTER = "(hover: hover) and (pointer: fine)";
27
+ /**
28
+ * An overlay scrollbar as a Mount, with no Message and no Model: where a
29
+ * scroller is scrolled is the browser's, and the bar only shows it.
30
+ *
31
+ * It runs on the scroller (or on an element holding it, named by `scroller`,
32
+ * when the scroller carries another Mount) and drives the bars drawn beside
33
+ * it: the scroller's parent's children marked `data-scroll-bar` (`block` or
34
+ * `inline`), which a style lays over the scroller's edge. Each bar gets `data-scrollable` while its axis has
35
+ * more to scroll, `data-shown` while the scroller scrolls or the pointer moves
36
+ * over it, until `idle` milliseconds pass with neither (or longer, while the
37
+ * pointer rests on a bar), and `data-dragging` while its thumb is dragged; and
38
+ * `--fk-scroll-thumb-offset` and `-size` (see `scrollThumb`). Pressing a bar
39
+ * off its thumb moves the thumb there, then drags it.
40
+ *
41
+ * It does nothing where the primary pointer is coarse or cannot hover, decided
42
+ * when it mounts: touch keeps the browser's bar and its physics. Otherwise the
43
+ * scroller gets `data-scroll-overlaid`, for a style to hide the native bar.
44
+ * How the bar looks, rests, widens and fades is the style's.
45
+ */
46
+ const ScrollBars = Mount.defineStream("ScrollBars", {
47
+ messages: [Schema.Never],
48
+ args: {
49
+ /** How long, in milliseconds, the bars stay after the last scroll or move. Default 600. */
50
+ idle: Schema.optional(Schema.Number),
51
+ /**
52
+ * The scroller, as a selector within the element, when it cannot hold this
53
+ * Mount itself (another component's, with a Mount of its own); looked for
54
+ * once, when it mounts. Default: the element is the scroller.
55
+ */
56
+ scroller: Schema.optional(Schema.String)
57
+ },
58
+ execute: ({ element, idle = 600, scroller: within }) => Stream.callback(() => Effect.acquireRelease(Effect.sync(() => {
59
+ if (typeof matchMedia !== "function" || !matchMedia(FINE_POINTER).matches) return () => {};
60
+ const found = within === void 0 ? element : element.querySelector(within);
61
+ if (!(found instanceof HTMLElement)) return () => {};
62
+ const scroller = found;
63
+ const area = scroller.parentElement;
64
+ if (area === null) return () => {};
65
+ const isBar = (child) => child instanceof HTMLElement && child.hasAttribute("data-scroll-bar");
66
+ /** Looked for at each use, so a redraw that replaced a bar is followed. */
67
+ const bars = () => Array.from(area.children).filter(isBar);
68
+ const axisOf = (bar) => bar.getAttribute("data-scroll-bar") === "inline" ? "inline" : "block";
69
+ /** The scroller along one axis, with the start measured from the top or the left. */
70
+ const extent = (axis) => {
71
+ if (axis === "block") return {
72
+ view: scroller.clientHeight,
73
+ content: scroller.scrollHeight,
74
+ start: scroller.scrollTop
75
+ };
76
+ const room = scroller.scrollWidth - scroller.clientWidth;
77
+ const rtl = getComputedStyle(scroller).direction === "rtl";
78
+ return {
79
+ view: scroller.clientWidth,
80
+ content: scroller.scrollWidth,
81
+ start: rtl ? room + scroller.scrollLeft : scroller.scrollLeft
82
+ };
83
+ };
84
+ const scrollTo = (axis, start) => {
85
+ if (axis === "block") {
86
+ scroller.scrollTop = start;
87
+ return;
88
+ }
89
+ const room = scroller.scrollWidth - scroller.clientWidth;
90
+ const rtl = getComputedStyle(scroller).direction === "rtl";
91
+ scroller.scrollLeft = rtl ? start - room : start;
92
+ };
93
+ const trackOf = (bar, axis) => axis === "block" ? bar.clientHeight : bar.clientWidth;
94
+ /** Where the thumb is along its bar, or nothing while the axis has nothing to scroll. */
95
+ const thumbOf = (bar, axis) => {
96
+ const { view, content, start } = extent(axis);
97
+ const track = trackOf(bar, axis);
98
+ if (content - view < 1 || track <= 0) return null;
99
+ const size = Math.min(track, Math.max(SHORTEST, track * view / content));
100
+ return {
101
+ track,
102
+ size,
103
+ offset: (track - size) * start / (content - view),
104
+ room: content - view
105
+ };
106
+ };
107
+ const set = (bar, name, value) => {
108
+ if (bar.style.getPropertyValue(name) !== value) bar.style.setProperty(name, value);
109
+ };
110
+ const mark = (bar, name, on) => {
111
+ if (bar.hasAttribute(name) !== on) bar.toggleAttribute(name, on);
112
+ };
113
+ let frame;
114
+ const update = () => {
115
+ if (frame !== void 0) cancelAnimationFrame(frame);
116
+ frame = void 0;
117
+ for (const bar of bars()) {
118
+ const axis = axisOf(bar);
119
+ const { view, content } = extent(axis);
120
+ mark(bar, "data-scrollable", content - view >= 1);
121
+ const thumb = thumbOf(bar, axis);
122
+ if (thumb === null) continue;
123
+ set(bar, scrollThumb.offset, `${thumb.offset}px`);
124
+ set(bar, scrollThumb.size, `${thumb.size}px`);
125
+ }
126
+ };
127
+ const soon = () => {
128
+ if (frame === void 0) frame = requestAnimationFrame(update);
129
+ };
130
+ let hiding;
131
+ let resting = null;
132
+ /** Ends the drag under way, if one is. */
133
+ let dragging = null;
134
+ const hide = () => {
135
+ hiding = void 0;
136
+ if (resting !== null || dragging !== null) return;
137
+ for (const bar of bars()) mark(bar, "data-shown", false);
138
+ };
139
+ const show = () => {
140
+ for (const bar of bars()) mark(bar, "data-shown", true);
141
+ if (hiding !== void 0) clearTimeout(hiding);
142
+ hiding = setTimeout(hide, idle);
143
+ };
144
+ const scrolled = () => {
145
+ update();
146
+ show();
147
+ };
148
+ const moved = (event) => {
149
+ if (event.pointerType !== "touch") show();
150
+ };
151
+ const entered = (event) => {
152
+ if (event.pointerType === "touch") return;
153
+ area.addEventListener("pointermove", moved, { passive: true });
154
+ show();
155
+ };
156
+ const left = () => {
157
+ area.removeEventListener("pointermove", moved);
158
+ resting = null;
159
+ if (hiding === void 0) hiding = setTimeout(hide, idle);
160
+ };
161
+ const over = (event) => {
162
+ const target = event.target;
163
+ resting = target instanceof Element ? bars().find((bar) => bar.contains(target)) ?? null : null;
164
+ };
165
+ const pressed = (event) => {
166
+ if (event.button !== 0 || event.pointerType === "touch" || dragging !== null) return;
167
+ const target = event.target;
168
+ if (!(target instanceof Element)) return;
169
+ const bar = bars().find((each) => each.contains(target));
170
+ if (bar === void 0) return;
171
+ const axis = axisOf(bar);
172
+ const thumb = thumbOf(bar, axis);
173
+ if (thumb === null) return;
174
+ event.preventDefault();
175
+ const along = (at) => {
176
+ const box = bar.getBoundingClientRect();
177
+ return axis === "block" ? at.clientY - box.top - bar.clientTop : at.clientX - box.left - bar.clientLeft;
178
+ };
179
+ const at = along(event);
180
+ const onThumb = at >= thumb.offset && at <= thumb.offset + thumb.size;
181
+ const grab = onThumb ? at - thumb.offset : thumb.size / 2;
182
+ const follow = (to) => {
183
+ const current = thumbOf(bar, axis);
184
+ if (current === null) return;
185
+ const offset = Math.min(Math.max(along(to) - grab, 0), current.track - current.size);
186
+ scrollTo(axis, offset / (current.track - current.size) * current.room);
187
+ };
188
+ const id = event.pointerId;
189
+ const move = (to) => {
190
+ if (to.pointerId === id) follow(to);
191
+ };
192
+ const end = (to) => {
193
+ if (to.pointerId === id) stop();
194
+ };
195
+ const owner = bar.ownerDocument;
196
+ const stop = () => {
197
+ owner.removeEventListener("pointermove", move);
198
+ owner.removeEventListener("pointerup", end);
199
+ owner.removeEventListener("pointercancel", end);
200
+ mark(bar, "data-dragging", false);
201
+ dragging = null;
202
+ show();
203
+ };
204
+ owner.addEventListener("pointermove", move);
205
+ owner.addEventListener("pointerup", end);
206
+ owner.addEventListener("pointercancel", end);
207
+ mark(bar, "data-dragging", true);
208
+ dragging = stop;
209
+ show();
210
+ if (!onThumb) follow(event);
211
+ };
212
+ const sizes = new ResizeObserver(soon);
213
+ const changes = new MutationObserver((records) => {
214
+ for (const record of records) {
215
+ for (const node of Array.from(record.removedNodes)) if (node instanceof Element) sizes.unobserve(node);
216
+ for (const node of Array.from(record.addedNodes)) if (node instanceof Element && (record.target === scroller || isBar(node))) sizes.observe(node);
217
+ }
218
+ soon();
219
+ });
220
+ sizes.observe(scroller);
221
+ for (const child of Array.from(scroller.children)) sizes.observe(child);
222
+ for (const bar of bars()) sizes.observe(bar);
223
+ changes.observe(scroller, { childList: true });
224
+ changes.observe(area, { childList: true });
225
+ scroller.addEventListener("scroll", scrolled, { passive: true });
226
+ area.addEventListener("pointerenter", entered);
227
+ area.addEventListener("pointerleave", left);
228
+ area.addEventListener("pointerover", over);
229
+ area.addEventListener("pointerdown", pressed);
230
+ scroller.setAttribute(SCROLL_OVERLAID_ATTRIBUTE, "");
231
+ update();
232
+ return () => {
233
+ dragging?.();
234
+ if (frame !== void 0) cancelAnimationFrame(frame);
235
+ if (hiding !== void 0) clearTimeout(hiding);
236
+ sizes.disconnect();
237
+ changes.disconnect();
238
+ scroller.removeEventListener("scroll", scrolled);
239
+ area.removeEventListener("pointerenter", entered);
240
+ area.removeEventListener("pointerleave", left);
241
+ area.removeEventListener("pointerover", over);
242
+ area.removeEventListener("pointerdown", pressed);
243
+ area.removeEventListener("pointermove", moved);
244
+ scroller.removeAttribute(SCROLL_OVERLAID_ATTRIBUTE);
245
+ for (const bar of bars()) {
246
+ for (const name of [
247
+ "data-scrollable",
248
+ "data-shown",
249
+ "data-dragging"
250
+ ]) bar.removeAttribute(name);
251
+ bar.style.removeProperty(scrollThumb.offset);
252
+ bar.style.removeProperty(scrollThumb.size);
253
+ }
254
+ };
255
+ }), (stop) => Effect.sync(stop)))
256
+ });
257
+ export { SCROLL_BAR_ATTRIBUTE, SCROLL_OVERLAID_ATTRIBUTE, ScrollBars, scrollThumb };
258
+
259
+ //# sourceMappingURL=scroll-bars.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scroll-bars.js","names":[],"sources":["../../src/dom/scroll-bars.ts"],"sourcesContent":["import { Effect, Schema, Stream } from 'effect'\nimport * as Mount from 'foldkit/mount'\n\n/**\n * The attribute that marks a bar beside a scroller `ScrollBars` runs on, set\n * to the axis it shows: `block` (the up-and-down bar) or `inline`.\n */\nexport const SCROLL_BAR_ATTRIBUTE = 'data-scroll-bar'\n\n/**\n * The attribute `ScrollBars` sets on its scroller while it draws the bars, so a\n * style hides the native bar only then: with no Mount running (a coarse\n * pointer, a page not yet hydrated) the browser's bar stays.\n */\nexport const SCROLL_OVERLAID_ATTRIBUTE = 'data-scroll-overlaid'\n\n/**\n * The custom properties `ScrollBars` writes on each bar, in pixels, for its\n * thumb to read: how far along the bar the thumb starts, and how long it is.\n * Physical: an inline bar's offset is from its left edge in either direction.\n */\nexport const scrollThumb = {\n offset: '--fk-scroll-thumb-offset',\n size: '--fk-scroll-thumb-size',\n} as const\n\n/** The shortest a thumb is drawn, however long the content, so it stays a target. */\nconst SHORTEST = 20\n\nconst FINE_POINTER = '(hover: hover) and (pointer: fine)'\n\ntype Axis = 'block' | 'inline'\n\n/**\n * An overlay scrollbar as a Mount, with no Message and no Model: where a\n * scroller is scrolled is the browser's, and the bar only shows it.\n *\n * It runs on the scroller (or on an element holding it, named by `scroller`,\n * when the scroller carries another Mount) and drives the bars drawn beside\n * it: the scroller's parent's children marked `data-scroll-bar` (`block` or\n * `inline`), which a style lays over the scroller's edge. Each bar gets `data-scrollable` while its axis has\n * more to scroll, `data-shown` while the scroller scrolls or the pointer moves\n * over it, until `idle` milliseconds pass with neither (or longer, while the\n * pointer rests on a bar), and `data-dragging` while its thumb is dragged; and\n * `--fk-scroll-thumb-offset` and `-size` (see `scrollThumb`). Pressing a bar\n * off its thumb moves the thumb there, then drags it.\n *\n * It does nothing where the primary pointer is coarse or cannot hover, decided\n * when it mounts: touch keeps the browser's bar and its physics. Otherwise the\n * scroller gets `data-scroll-overlaid`, for a style to hide the native bar.\n * How the bar looks, rests, widens and fades is the style's.\n */\nexport const ScrollBars = Mount.defineStream('ScrollBars', {\n messages: [Schema.Never],\n args: {\n /** How long, in milliseconds, the bars stay after the last scroll or move. Default 600. */\n idle: Schema.optional(Schema.Number),\n /**\n * The scroller, as a selector within the element, when it cannot hold this\n * Mount itself (another component's, with a Mount of its own); looked for\n * once, when it mounts. Default: the element is the scroller.\n */\n scroller: Schema.optional(Schema.String),\n },\n execute: ({ element, idle = 600, scroller: within }) =>\n Stream.callback<never>(() =>\n Effect.acquireRelease(\n Effect.sync(() => {\n if (typeof matchMedia !== 'function' || !matchMedia(FINE_POINTER).matches) {\n return () => {}\n }\n const found = within === undefined ? element : element.querySelector(within)\n if (!(found instanceof HTMLElement)) return () => {}\n const scroller = found\n const area = scroller.parentElement\n if (area === null) return () => {}\n\n const isBar = (child: Element): child is HTMLElement =>\n child instanceof HTMLElement && child.hasAttribute(SCROLL_BAR_ATTRIBUTE)\n /** Looked for at each use, so a redraw that replaced a bar is followed. */\n const bars = () => Array.from(area.children).filter(isBar)\n const axisOf = (bar: HTMLElement): Axis =>\n bar.getAttribute(SCROLL_BAR_ATTRIBUTE) === 'inline' ? 'inline' : 'block'\n\n /** The scroller along one axis, with the start measured from the top or the left. */\n const extent = (axis: Axis) => {\n if (axis === 'block') {\n return {\n view: scroller.clientHeight,\n content: scroller.scrollHeight,\n start: scroller.scrollTop,\n }\n }\n const room = scroller.scrollWidth - scroller.clientWidth\n // A right-to-left scroller counts from 0 at the right down to minus its room.\n const rtl = getComputedStyle(scroller).direction === 'rtl'\n return {\n view: scroller.clientWidth,\n content: scroller.scrollWidth,\n start: rtl ? room + scroller.scrollLeft : scroller.scrollLeft,\n }\n }\n const scrollTo = (axis: Axis, start: number) => {\n if (axis === 'block') {\n scroller.scrollTop = start\n return\n }\n const room = scroller.scrollWidth - scroller.clientWidth\n const rtl = getComputedStyle(scroller).direction === 'rtl'\n scroller.scrollLeft = rtl ? start - room : start\n }\n const trackOf = (bar: HTMLElement, axis: Axis) =>\n axis === 'block' ? bar.clientHeight : bar.clientWidth\n /** Where the thumb is along its bar, or nothing while the axis has nothing to scroll. */\n const thumbOf = (bar: HTMLElement, axis: Axis) => {\n const { view, content, start } = extent(axis)\n const track = trackOf(bar, axis)\n if (content - view < 1 || track <= 0) return null\n const size = Math.min(track, Math.max(SHORTEST, (track * view) / content))\n const offset = ((track - size) * start) / (content - view)\n return { track, size, offset, room: content - view }\n }\n const set = (bar: HTMLElement, name: string, value: string) => {\n if (bar.style.getPropertyValue(name) !== value) bar.style.setProperty(name, value)\n }\n const mark = (bar: HTMLElement, name: string, on: boolean) => {\n if (bar.hasAttribute(name) !== on) bar.toggleAttribute(name, on)\n }\n\n let frame: number | undefined\n const update = () => {\n if (frame !== undefined) cancelAnimationFrame(frame)\n frame = undefined\n for (const bar of bars()) {\n const axis = axisOf(bar)\n const { view, content } = extent(axis)\n // Marked first: a style draws no bar until it is, so it has no length before.\n mark(bar, 'data-scrollable', content - view >= 1)\n const thumb = thumbOf(bar, axis)\n if (thumb === null) continue\n set(bar, scrollThumb.offset, `${thumb.offset}px`)\n set(bar, scrollThumb.size, `${thumb.size}px`)\n }\n }\n const soon = () => {\n if (frame === undefined) frame = requestAnimationFrame(update)\n }\n\n let hiding: ReturnType<typeof setTimeout> | undefined\n let resting: HTMLElement | null = null\n /** Ends the drag under way, if one is. */\n let dragging: (() => void) | null = null\n const hide = () => {\n hiding = undefined\n // A bar the pointer rests on, or one being dragged, stays until it is left.\n if (resting !== null || dragging !== null) return\n for (const bar of bars()) mark(bar, 'data-shown', false)\n }\n const show = () => {\n for (const bar of bars()) mark(bar, 'data-shown', true)\n if (hiding !== undefined) clearTimeout(hiding)\n hiding = setTimeout(hide, idle)\n }\n\n const scrolled = () => {\n update()\n show()\n }\n // Listened to only while the pointer is over the area.\n const moved = (event: PointerEvent) => {\n if (event.pointerType !== 'touch') show()\n }\n const entered = (event: PointerEvent) => {\n if (event.pointerType === 'touch') return\n area.addEventListener('pointermove', moved, { passive: true })\n show()\n }\n const left = () => {\n area.removeEventListener('pointermove', moved)\n resting = null\n // A hide that came while the pointer rested on a bar waited for this.\n if (hiding === undefined) hiding = setTimeout(hide, idle)\n }\n const over = (event: PointerEvent) => {\n const target = event.target\n resting =\n target instanceof Element ? (bars().find(bar => bar.contains(target)) ?? null) : null\n }\n\n const pressed = (event: PointerEvent) => {\n if (event.button !== 0 || event.pointerType === 'touch' || dragging !== null) return\n const target = event.target\n if (!(target instanceof Element)) return\n const bar = bars().find(each => each.contains(target))\n if (bar === undefined) return\n const axis = axisOf(bar)\n const thumb = thumbOf(bar, axis)\n if (thumb === null) return\n // The bar takes the press: no text selected, no focus moved off the scroller.\n event.preventDefault()\n const along = (at: PointerEvent) => {\n const box = bar.getBoundingClientRect()\n return axis === 'block'\n ? at.clientY - box.top - bar.clientTop\n : at.clientX - box.left - bar.clientLeft\n }\n const at = along(event)\n const onThumb = at >= thumb.offset && at <= thumb.offset + thumb.size\n // Held where it was taken, or by its middle when the press jumped it there.\n const grab = onThumb ? at - thumb.offset : thumb.size / 2\n const follow = (to: PointerEvent) => {\n const current = thumbOf(bar, axis)\n if (current === null) return\n const offset = Math.min(Math.max(along(to) - grab, 0), current.track - current.size)\n scrollTo(axis, (offset / (current.track - current.size)) * current.room)\n }\n const id = event.pointerId\n const move = (to: PointerEvent) => {\n if (to.pointerId === id) follow(to)\n }\n const end = (to: PointerEvent) => {\n if (to.pointerId === id) stop()\n }\n // On the document, for the drag alone: the pointer leaves the bar as it drags.\n const owner = bar.ownerDocument\n const stop = () => {\n owner.removeEventListener('pointermove', move)\n owner.removeEventListener('pointerup', end)\n owner.removeEventListener('pointercancel', end)\n mark(bar, 'data-dragging', false)\n dragging = null\n show()\n }\n owner.addEventListener('pointermove', move)\n owner.addEventListener('pointerup', end)\n owner.addEventListener('pointercancel', end)\n mark(bar, 'data-dragging', true)\n dragging = stop\n show()\n if (!onThumb) follow(event)\n }\n\n // Both made before anything observes: where one is missing, the Mount\n // fails with nothing attached.\n const sizes = new ResizeObserver(soon)\n // The content's size moves the thumb as much as the scroller's, so each\n // child of the scroller is watched, and each bar for its track. Only what\n // a change added or removed is watched or let go: a virtual list swaps\n // a row or two each frame it scrolls, out of many.\n const changes = new MutationObserver(records => {\n for (const record of records) {\n for (const node of Array.from(record.removedNodes)) {\n if (node instanceof Element) sizes.unobserve(node)\n }\n for (const node of Array.from(record.addedNodes)) {\n if (node instanceof Element && (record.target === scroller || isBar(node))) {\n sizes.observe(node)\n }\n }\n }\n soon()\n })\n sizes.observe(scroller)\n for (const child of Array.from(scroller.children)) sizes.observe(child)\n for (const bar of bars()) sizes.observe(bar)\n changes.observe(scroller, { childList: true })\n changes.observe(area, { childList: true })\n scroller.addEventListener('scroll', scrolled, { passive: true })\n area.addEventListener('pointerenter', entered)\n area.addEventListener('pointerleave', left)\n area.addEventListener('pointerover', over)\n area.addEventListener('pointerdown', pressed)\n scroller.setAttribute(SCROLL_OVERLAID_ATTRIBUTE, '')\n update()\n return () => {\n // Ended first: ending a drag shows the bars, which sets a hide to clear.\n dragging?.()\n if (frame !== undefined) cancelAnimationFrame(frame)\n if (hiding !== undefined) clearTimeout(hiding)\n sizes.disconnect()\n changes.disconnect()\n scroller.removeEventListener('scroll', scrolled)\n area.removeEventListener('pointerenter', entered)\n area.removeEventListener('pointerleave', left)\n area.removeEventListener('pointerover', over)\n area.removeEventListener('pointerdown', pressed)\n area.removeEventListener('pointermove', moved)\n scroller.removeAttribute(SCROLL_OVERLAID_ATTRIBUTE)\n for (const bar of bars()) {\n for (const name of ['data-scrollable', 'data-shown', 'data-dragging'])\n bar.removeAttribute(name)\n bar.style.removeProperty(scrollThumb.offset)\n bar.style.removeProperty(scrollThumb.size)\n }\n }\n }),\n stop => Effect.sync(stop),\n ),\n ),\n})\n"],"mappings":"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"}