foldkit-primitives 0.15.4 → 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-l7InESYh.d.mts → events/input-modality.d.ts} +9 -10
  136. package/dist/events/input-modality.d.ts.map +1 -0
  137. package/dist/{input-modality-XwQOFLip.mjs → events/input-modality.js} +2 -2
  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-C4gHodLc.mjs → internal.js} +7 -5
  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} +10 -306
  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 -335
  373. package/dist/device/index.d.mts.map +0 -1
  374. package/dist/device/index.mjs +0 -493
  375. package/dist/device/index.mjs.map +0 -1
  376. package/dist/dom/index.d.mts +0 -714
  377. package/dist/dom/index.d.mts.map +0 -1
  378. package/dist/dom/index.mjs +0 -1840
  379. package/dist/dom/index.mjs.map +0 -1
  380. package/dist/editable-text-Bg7vil7h.d.mts +0 -307
  381. package/dist/editable-text-Bg7vil7h.d.mts.map +0 -1
  382. package/dist/events/index.d.mts +0 -168
  383. package/dist/events/index.d.mts.map +0 -1
  384. package/dist/events/index.mjs +0 -307
  385. package/dist/events/index.mjs.map +0 -1
  386. package/dist/follow-tab-stop-DM5EI4Ci.mjs +0 -856
  387. package/dist/follow-tab-stop-DM5EI4Ci.mjs.map +0 -1
  388. package/dist/index-Bomdwb7e.d.mts +0 -142
  389. package/dist/index-Bomdwb7e.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-XwQOFLip.mjs.map +0 -1
  393. package/dist/input-modality-l7InESYh.d.mts.map +0 -1
  394. package/dist/interaction/index.d.mts +0 -1193
  395. package/dist/interaction/index.d.mts.map +0 -1
  396. package/dist/interaction/index.mjs +0 -1992
  397. package/dist/interaction/index.mjs.map +0 -1
  398. package/dist/internal-C4gHodLc.mjs.map +0 -1
  399. package/dist/media/index.d.mts +0 -103
  400. package/dist/media/index.d.mts.map +0 -1
  401. package/dist/media/index.mjs +0 -146
  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-BmlJCjn6.mjs +0 -236
  406. package/dist/motion-BmlJCjn6.mjs.map +0 -1
  407. package/dist/net/index.d.mts +0 -338
  408. package/dist/net/index.d.mts.map +0 -1
  409. package/dist/net/index.mjs +0 -530
  410. package/dist/net/index.mjs.map +0 -1
  411. package/dist/observers/index.d.mts +0 -76
  412. package/dist/observers/index.d.mts.map +0 -1
  413. package/dist/observers/index.mjs +0 -155
  414. package/dist/observers/index.mjs.map +0 -1
  415. package/dist/rolldown-runtime-D8jQpDG7.mjs +0 -12
  416. package/dist/state/index.d.mts +0 -432
  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 -167
  420. package/dist/time/index.d.mts.map +0 -1
  421. package/dist/time/index.mjs +0 -236
  422. package/dist/time/index.mjs.map +0 -1
@@ -0,0 +1,232 @@
1
+ import { Effect, Queue, Schema, Stream } from "effect";
2
+ import * as Mount from "foldkit/mount";
3
+ // src/dom/editable-text.ts
4
+ const TextEdited = Schema.TaggedStruct("TextEdited", {
5
+ /** The field, by its marking attribute's value. */
6
+ field: Schema.String,
7
+ text: Schema.String
8
+ });
9
+ const TextCommitted = Schema.TaggedStruct("TextCommitted", {
10
+ field: Schema.String,
11
+ text: Schema.String
12
+ });
13
+ const TextCancelled = Schema.TaggedStruct("TextCancelled", {
14
+ field: Schema.String,
15
+ /** The text the field had when editing began, which the DOM shows again. */
16
+ initial: Schema.String
17
+ });
18
+ const EditAsked = Schema.TaggedStruct("EditAsked", {
19
+ /** A marked field, not editable yet, that was double-clicked. */
20
+ field: Schema.String });
21
+ /** Whether a field takes more than one line. */
22
+ const multiline = (element) => element.getAttribute("aria-multiline") === "true";
23
+ /**
24
+ * A field's text. A browser ends an edited element with a line break it adds
25
+ * itself, which is not the author's; in one line, the author's breaks are spaces.
26
+ */
27
+ const textOf = (element) => {
28
+ const text = element.innerText.replace(/\r\n?/g, "\n").replace(/\n$/, "");
29
+ return multiline(element) ? text : text.replace(/\n+/g, " ");
30
+ };
31
+ /** Puts the caret at the end of a field, which focuses it too. */
32
+ const caretAtEnd = (field) => {
33
+ field.focus();
34
+ const caret = document.createRange();
35
+ caret.selectNodeContents(field);
36
+ caret.collapse(false);
37
+ const selection = window.getSelection();
38
+ selection?.removeAllRanges();
39
+ selection?.addRange(caret);
40
+ };
41
+ /** Whether a key press belongs to an input method still composing, not to the field. */
42
+ const composing = (event) => event.isComposing || event.keyCode === 229;
43
+ /**
44
+ * Text typed into an editable descendant of an element, as a Mount: one set of
45
+ * listeners on the container, like `Targets`. A field is a descendant marked
46
+ * by an attribute whose value names it, while it is `contenteditable`. The
47
+ * view decides which one is; the Mount focuses it as it becomes so (made
48
+ * editable, or drawn editable), with the caret at its end, and at no other
49
+ * time. When Enter or Escape ends an edit and the view then removes the field
50
+ * or makes it no longer editable, focus, left on nothing, comes back to the
51
+ * container, so the next key reaches it; give the container a `tabindex`. A double-click on a marked field that is not editable yet asks for it
52
+ * to be (`EditAsked`).
53
+ *
54
+ * It reads `innerText`, never `innerHTML`, so what arrives is text. A field is
55
+ * one line unless it carries `aria-multiline="true"`: in one line, a line
56
+ * break becomes a space. Nothing is reported while an input method composes;
57
+ * the composed text arrives once, when it is done.
58
+ *
59
+ * Enter commits (Shift+Enter breaks a line in a multiline field), and so does
60
+ * leaving the field. Escape cancels, and puts the text the field had when
61
+ * editing began back in the DOM, since a view that stopped redrawing the field
62
+ * while it was edited will not. Where the browser lacks `plaintext-only`, a
63
+ * paste is inserted as text. What an edit means is the parent's `update`.
64
+ */
65
+ const EditableText = Mount.defineStream("EditableText", {
66
+ messages: [
67
+ TextEdited,
68
+ TextCommitted,
69
+ TextCancelled,
70
+ EditAsked
71
+ ],
72
+ args: {
73
+ /** The attribute that marks a field, holding its name. */
74
+ attribute: Schema.String },
75
+ execute: ({ element, attribute }) => Stream.callback((queue) => Effect.acquireRelease(Effect.sync(() => {
76
+ /** The field being edited: its name, its text when editing began, and the last reported. */
77
+ let current;
78
+ let composingText = false;
79
+ let ending;
80
+ /** The marked field at or above an event's target, inside the container. */
81
+ const markedOf = (target) => {
82
+ if (!(target instanceof Element)) return void 0;
83
+ const field = target.closest(`[${attribute}]`);
84
+ return field instanceof HTMLElement && element.contains(field) ? field : void 0;
85
+ };
86
+ /** The same, while it is editable. */
87
+ const fieldOf = (target) => {
88
+ const field = markedOf(target);
89
+ return field?.isContentEditable === true ? field : void 0;
90
+ };
91
+ /** Begins an edit of `field`, unless one of it is under way: on focus, or typing. */
92
+ const begin = (field) => {
93
+ if (current?.field === field && !current.ended) return current;
94
+ const text = textOf(field);
95
+ current = {
96
+ field,
97
+ name: field.getAttribute(attribute) ?? "",
98
+ initial: text,
99
+ reported: text,
100
+ ended: false
101
+ };
102
+ return current;
103
+ };
104
+ /**
105
+ * The edit of `field`: the one under way or just ended, else one begun
106
+ * now, for a field focused before these listeners came. An ended edit
107
+ * reports nothing more, so the blur that follows a commit or a cancel
108
+ * does not commit again.
109
+ */
110
+ const editOf = (field) => current?.field === field ? current : begin(field);
111
+ const report = (field) => {
112
+ const edit = editOf(field);
113
+ if (edit.ended) return;
114
+ const text = textOf(field);
115
+ if (text === edit.reported) return;
116
+ edit.reported = text;
117
+ Queue.offerUnsafe(queue, TextEdited.make({
118
+ field: edit.name,
119
+ text
120
+ }));
121
+ };
122
+ const commit = (field) => {
123
+ const edit = editOf(field);
124
+ if (edit.ended) return;
125
+ edit.ended = true;
126
+ Queue.offerUnsafe(queue, TextCommitted.make({
127
+ field: edit.name,
128
+ text: textOf(field)
129
+ }));
130
+ };
131
+ const cancel = (field) => {
132
+ const edit = editOf(field);
133
+ if (edit.ended) return;
134
+ edit.ended = true;
135
+ field.innerText = edit.initial;
136
+ caretAtEnd(field);
137
+ Queue.offerUnsafe(queue, TextCancelled.make({
138
+ field: edit.name,
139
+ initial: edit.initial
140
+ }));
141
+ };
142
+ const listeners = [
143
+ ["dblclick", (event) => {
144
+ const field = markedOf(event.target);
145
+ if (field === void 0 || field.isContentEditable) return;
146
+ Queue.offerUnsafe(queue, EditAsked.make({ field: field.getAttribute(attribute) ?? "" }));
147
+ }],
148
+ ["focusin", (event) => {
149
+ composingText = false;
150
+ const field = fieldOf(event.target);
151
+ if (field !== void 0) begin(field);
152
+ }],
153
+ ["beforeinput", (event) => {
154
+ const field = fieldOf(event.target);
155
+ if (field !== void 0) begin(field);
156
+ }],
157
+ ["compositionstart", () => composingText = true],
158
+ ["compositionend", (event) => {
159
+ composingText = false;
160
+ const field = fieldOf(event.target);
161
+ if (field !== void 0) report(field);
162
+ }],
163
+ ["input", (event) => {
164
+ const field = fieldOf(event.target);
165
+ if (field !== void 0 && !composingText) report(field);
166
+ }],
167
+ ["keydown", (event) => {
168
+ const field = fieldOf(event.target);
169
+ const key = event;
170
+ if (field === void 0 || composing(key)) return;
171
+ if (key.key === "Escape") {
172
+ event.preventDefault();
173
+ ending = field;
174
+ cancel(field);
175
+ } else if (key.key === "Enter" && !(key.shiftKey && multiline(field))) {
176
+ event.preventDefault();
177
+ ending = field;
178
+ commit(field);
179
+ }
180
+ }],
181
+ ["focusout", (event) => {
182
+ const field = fieldOf(event.target);
183
+ if (field === void 0) return;
184
+ queueMicrotask(() => {
185
+ if (field === ending && field.isConnected && field.isContentEditable) ending = void 0;
186
+ });
187
+ commit(field);
188
+ }],
189
+ ["paste", (event) => {
190
+ const field = fieldOf(event.target);
191
+ if (field === void 0 || field.contentEditable === "plaintext-only") return;
192
+ const pasted = event.clipboardData?.getData("text/plain") ?? "";
193
+ event.preventDefault();
194
+ begin(field);
195
+ document.execCommand("insertText", false, pasted);
196
+ }]
197
+ ];
198
+ const editable = `[${attribute}][contenteditable]:not([contenteditable="false"])`;
199
+ const becoming = new MutationObserver((records) => {
200
+ if (ending !== void 0 && !(ending.isConnected && ending.isContentEditable)) {
201
+ ending = void 0;
202
+ const focused = document.activeElement;
203
+ if ((focused === null || focused === document.body) && element instanceof HTMLElement) element.focus({ preventScroll: true });
204
+ }
205
+ for (const record of records) {
206
+ const changed = record.type === "attributes" ? [record.target] : Array.from(record.addedNodes);
207
+ for (const node of changed) {
208
+ if (!(node instanceof HTMLElement)) continue;
209
+ const field = node.matches(editable) ? node : node.querySelector(editable);
210
+ if (field instanceof HTMLElement) return caretAtEnd(field);
211
+ }
212
+ }
213
+ });
214
+ for (const [type, listener] of listeners) element.addEventListener(type, listener);
215
+ becoming.observe(element, {
216
+ subtree: true,
217
+ childList: true,
218
+ attributes: true,
219
+ attributeFilter: ["contenteditable"]
220
+ });
221
+ return {
222
+ listeners,
223
+ becoming
224
+ };
225
+ }), ({ listeners, becoming }) => Effect.sync(() => {
226
+ becoming.disconnect();
227
+ for (const [type, listener] of listeners) element.removeEventListener(type, listener);
228
+ })))
229
+ });
230
+ export { EditAsked, EditableText, TextCancelled, TextCommitted, TextEdited, textOf };
231
+
232
+ //# sourceMappingURL=editable-text.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"editable-text.js","names":[],"sources":["../../src/dom/editable-text.ts"],"sourcesContent":["import { Effect, Queue, Schema, Stream } from 'effect'\nimport * as Mount from 'foldkit/mount'\n\nexport const TextEdited = Schema.TaggedStruct('TextEdited', {\n /** The field, by its marking attribute's value. */\n field: Schema.String,\n text: Schema.String,\n})\nexport type TextEdited = typeof TextEdited.Type\n\nexport const TextCommitted = Schema.TaggedStruct('TextCommitted', {\n field: Schema.String,\n text: Schema.String,\n})\nexport type TextCommitted = typeof TextCommitted.Type\n\nexport const TextCancelled = Schema.TaggedStruct('TextCancelled', {\n field: Schema.String,\n /** The text the field had when editing began, which the DOM shows again. */\n initial: Schema.String,\n})\nexport type TextCancelled = typeof TextCancelled.Type\n\nexport const EditAsked = Schema.TaggedStruct('EditAsked', {\n /** A marked field, not editable yet, that was double-clicked. */\n field: Schema.String,\n})\nexport type EditAsked = typeof EditAsked.Type\n\nexport type TextFact = TextEdited | TextCommitted | TextCancelled | EditAsked\n\n/** Whether a field takes more than one line. */\nconst multiline = (element: HTMLElement) => element.getAttribute('aria-multiline') === 'true'\n\n/**\n * A field's text. A browser ends an edited element with a line break it adds\n * itself, which is not the author's; in one line, the author's breaks are spaces.\n */\nexport const textOf = (element: HTMLElement): string => {\n const text = element.innerText.replace(/\\r\\n?/g, '\\n').replace(/\\n$/, '')\n return multiline(element) ? text : text.replace(/\\n+/g, ' ')\n}\n\n/** Puts the caret at the end of a field, which focuses it too. */\nconst caretAtEnd = (field: HTMLElement) => {\n // Chromium also focuses on the selection below; no standard says a browser must.\n field.focus()\n const caret = document.createRange()\n caret.selectNodeContents(field)\n caret.collapse(false)\n const selection = window.getSelection()\n selection?.removeAllRanges()\n selection?.addRange(caret)\n}\n\n/** Whether a key press belongs to an input method still composing, not to the field. */\nconst composing = (event: KeyboardEvent) => event.isComposing || event.keyCode === 229\n\n/**\n * Text typed into an editable descendant of an element, as a Mount: one set of\n * listeners on the container, like `Targets`. A field is a descendant marked\n * by an attribute whose value names it, while it is `contenteditable`. The\n * view decides which one is; the Mount focuses it as it becomes so (made\n * editable, or drawn editable), with the caret at its end, and at no other\n * time. When Enter or Escape ends an edit and the view then removes the field\n * or makes it no longer editable, focus, left on nothing, comes back to the\n * container, so the next key reaches it; give the container a `tabindex`. A double-click on a marked field that is not editable yet asks for it\n * to be (`EditAsked`).\n *\n * It reads `innerText`, never `innerHTML`, so what arrives is text. A field is\n * one line unless it carries `aria-multiline=\"true\"`: in one line, a line\n * break becomes a space. Nothing is reported while an input method composes;\n * the composed text arrives once, when it is done.\n *\n * Enter commits (Shift+Enter breaks a line in a multiline field), and so does\n * leaving the field. Escape cancels, and puts the text the field had when\n * editing began back in the DOM, since a view that stopped redrawing the field\n * while it was edited will not. Where the browser lacks `plaintext-only`, a\n * paste is inserted as text. What an edit means is the parent's `update`.\n */\nexport const EditableText = Mount.defineStream('EditableText', {\n messages: [TextEdited, TextCommitted, TextCancelled, EditAsked],\n args: {\n /** The attribute that marks a field, holding its name. */\n attribute: Schema.String,\n },\n execute: ({ element, attribute }) =>\n Stream.callback<TextFact>(queue =>\n Effect.acquireRelease(\n Effect.sync(() => {\n /** The field being edited: its name, its text when editing began, and the last reported. */\n let current:\n | {\n readonly field: HTMLElement\n readonly name: string\n readonly initial: string\n reported: string\n ended: boolean\n }\n | undefined\n let composingText = false\n // A field whose edit a key ended: when it leaves with focus on nothing, focus\n // comes back to the container, where the keys that began the edit are.\n let ending: HTMLElement | undefined\n\n /** The marked field at or above an event's target, inside the container. */\n const markedOf = (target: EventTarget | null): HTMLElement | undefined => {\n if (!(target instanceof Element)) return undefined\n const field = target.closest(`[${attribute}]`)\n return field instanceof HTMLElement && element.contains(field) ? field : undefined\n }\n /** The same, while it is editable. */\n const fieldOf = (target: EventTarget | null): HTMLElement | undefined => {\n const field = markedOf(target)\n return field?.isContentEditable === true ? field : undefined\n }\n /** Begins an edit of `field`, unless one of it is under way: on focus, or typing. */\n const begin = (field: HTMLElement) => {\n if (current?.field === field && !current.ended) return current\n const text = textOf(field)\n current = {\n field,\n name: field.getAttribute(attribute) ?? '',\n initial: text,\n reported: text,\n ended: false,\n }\n return current\n }\n /**\n * The edit of `field`: the one under way or just ended, else one begun\n * now, for a field focused before these listeners came. An ended edit\n * reports nothing more, so the blur that follows a commit or a cancel\n * does not commit again.\n */\n const editOf = (field: HTMLElement) => (current?.field === field ? current : begin(field))\n const report = (field: HTMLElement) => {\n const edit = editOf(field)\n if (edit.ended) return\n const text = textOf(field)\n // A browser may follow a composition with an input of the same text.\n if (text === edit.reported) return\n edit.reported = text\n Queue.offerUnsafe(queue, TextEdited.make({ field: edit.name, text }))\n }\n const commit = (field: HTMLElement) => {\n const edit = editOf(field)\n if (edit.ended) return\n edit.ended = true\n Queue.offerUnsafe(queue, TextCommitted.make({ field: edit.name, text: textOf(field) }))\n }\n const cancel = (field: HTMLElement) => {\n const edit = editOf(field)\n if (edit.ended) return\n edit.ended = true\n field.innerText = edit.initial\n // Writing the text moved the caret to its start; typing on goes after it.\n caretAtEnd(field)\n Queue.offerUnsafe(\n queue,\n TextCancelled.make({ field: edit.name, initial: edit.initial }),\n )\n }\n\n const listeners: ReadonlyArray<readonly [string, (event: Event) => void]> = [\n [\n 'dblclick',\n event => {\n const field = markedOf(event.target)\n // In an editable field, a double-click selects a word.\n if (field === undefined || field.isContentEditable) return\n Queue.offerUnsafe(\n queue,\n EditAsked.make({ field: field.getAttribute(attribute) ?? '' }),\n )\n },\n ],\n [\n 'focusin',\n event => {\n // A composition that never ended, in a field left, holds no other field silent.\n composingText = false\n const field = fieldOf(event.target)\n if (field !== undefined) begin(field)\n },\n ],\n // Before the change: a field focused before these listeners came is begun here.\n [\n 'beforeinput',\n event => {\n const field = fieldOf(event.target)\n if (field !== undefined) begin(field)\n },\n ],\n ['compositionstart', () => (composingText = true)],\n [\n 'compositionend',\n event => {\n composingText = false\n const field = fieldOf(event.target)\n if (field !== undefined) report(field)\n },\n ],\n [\n 'input',\n event => {\n const field = fieldOf(event.target)\n if (field !== undefined && !composingText) report(field)\n },\n ],\n [\n 'keydown',\n event => {\n const field = fieldOf(event.target)\n const key = event as KeyboardEvent\n if (field === undefined || composing(key)) return\n if (key.key === 'Escape') {\n event.preventDefault()\n ending = field\n cancel(field)\n } else if (key.key === 'Enter' && !(key.shiftKey && multiline(field))) {\n event.preventDefault()\n ending = field\n commit(field)\n }\n },\n ],\n [\n 'focusout',\n event => {\n const field = fieldOf(event.target)\n if (field === undefined) return\n // Left while still there and editable, asked once the change that may have\n // taken it away is done: the author went elsewhere, and focus is theirs.\n queueMicrotask(() => {\n if (field === ending && field.isConnected && field.isContentEditable)\n ending = undefined\n })\n commit(field)\n },\n ],\n [\n 'paste',\n event => {\n const field = fieldOf(event.target)\n // `plaintext-only` pastes text itself; elsewhere, markup would arrive.\n if (field === undefined || field.contentEditable === 'plaintext-only') return\n const pasted = (event as ClipboardEvent).clipboardData?.getData('text/plain') ?? ''\n event.preventDefault()\n // `insertText` fires no `beforeinput`: begun here, a paste after Enter is an edit.\n begin(field)\n // As typing is, so the browser's undo takes it back; `textOf` makes one line of it.\n document.execCommand('insertText', false, pasted)\n },\n ],\n ]\n // Focuses a field as it becomes editable, and only then: made so, or drawn so.\n // A field editable all along, or another going away, moves no focus.\n const editable = `[${attribute}][contenteditable]:not([contenteditable=\"false\"])`\n const becoming = new MutationObserver(records => {\n if (ending !== undefined && !(ending.isConnected && ending.isContentEditable)) {\n ending = undefined\n const focused = document.activeElement\n if ((focused === null || focused === document.body) && element instanceof HTMLElement)\n element.focus({ preventScroll: true })\n }\n for (const record of records) {\n const changed =\n record.type === 'attributes' ? [record.target] : Array.from(record.addedNodes)\n for (const node of changed) {\n if (!(node instanceof HTMLElement)) continue\n const field = node.matches(editable) ? node : node.querySelector(editable)\n if (field instanceof HTMLElement) return caretAtEnd(field)\n }\n }\n })\n\n for (const [type, listener] of listeners) element.addEventListener(type, listener)\n // A field made editable, drawn editable, or leaving.\n becoming.observe(element, {\n subtree: true,\n childList: true,\n attributes: true,\n attributeFilter: ['contenteditable'],\n })\n return { listeners, becoming }\n }),\n ({ listeners, becoming }) =>\n Effect.sync(() => {\n becoming.disconnect()\n for (const [type, listener] of listeners) element.removeEventListener(type, listener)\n }),\n ),\n ),\n})\n"],"mappings":"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"}
@@ -0,0 +1,93 @@
1
+ import { Schema } from "effect";
2
+ import * as Mount from "foldkit/mount";
3
+ /** The custom properties `FluidHover` writes on its container for a highlight named `name`. */
4
+ export declare const fluidHovered: (name: string) => {
5
+ readonly x: `--fk-${string}-x`;
6
+ readonly y: `--fk-${string}-y`;
7
+ readonly w: `--fk-${string}-w`;
8
+ readonly h: `--fk-${string}-h`;
9
+ /** `1` while an item is highlighted, `0` once the pointer and focus have left. */
10
+ readonly shown: `--fk-${string}-shown`;
11
+ /**
12
+ * `0` for the frame the highlight appears in, then `1`: a highlight's
13
+ * movement scales its duration by it, so it appears on its item rather
14
+ * than sliding in from where it last was.
15
+ */
16
+ readonly moving: `--fk-${string}-moving`;
17
+ };
18
+ /**
19
+ * The attribute `FluidHover` sets on its container, to the highlight's name,
20
+ * while it runs: a stylist draws the highlight, and drops each item's own
21
+ * hover, only under it.
22
+ */
23
+ export declare const FLUID_HOVER_ATTRIBUTE = "data-fluid-hover";
24
+ /** The attribute that names, inside an item, the control a press in a gap reaches. */
25
+ export declare const FLUID_PRESS_ATTRIBUTE = "data-fluid-press";
26
+ /** The attribute on the item the highlight is shown on, for what CSS draws beside it. */
27
+ export declare const FLUID_LIT_ATTRIBUTE = "data-fluid-lit";
28
+ /**
29
+ * The attribute `FluidHover` sets on its container, to the highlight's name,
30
+ * while the item that highlight is on is held. A stylist draws the press on
31
+ * the highlight (`data-fluid-held`) rather than on the item, whose own press
32
+ * is hidden under it; a press in a gap marks it too where `gapClick` sends
33
+ * that press to the lit item.
34
+ */
35
+ export declare const FLUID_HELD_ATTRIBUTE = "data-fluid-held";
36
+ declare const Axis: Schema.Literals<readonly ["x", "y", "xy"]>;
37
+ export type FluidAxis = typeof Axis.Type;
38
+ /**
39
+ * One highlight that follows the pointer across a container's items, as a
40
+ * Mount, with no Message and no Model: which item the pointer is nearest is
41
+ * presentation, known to the DOM and to no transition.
42
+ *
43
+ * The item nearest the pointer is the one highlighted, so the pointer in a gap
44
+ * between two items still points at one, and the highlight moves from item to
45
+ * item instead of blinking off between them. On the `y` axis nearness is read
46
+ * vertically (a list), on `x` horizontally (a strip), on `xy` both (a grid). A
47
+ * disabled item (`aria-disabled="true"`, `data-disabled`, `:disabled`) is never
48
+ * highlighted. An item reached by the keyboard (`:focus-visible`) is
49
+ * highlighted too, and with `focused`, the item that selector finds from a
50
+ * focused element that is no item (a tree's row, from its focused
51
+ * `treeitem`, which also holds the rows beneath it); a touch highlights
52
+ * nothing, since there is no pointer to
53
+ * follow before the press.
54
+ *
55
+ * The container gets `--fk-<name>-x`, `-y`, `-w` and `-h` in pixels, relative
56
+ * to its scroll box like `Measure`'s, and `-shown` and `-moving` (see
57
+ * `fluidHovered`); a view draws the highlight as an absolutely placed child
58
+ * that reads them. With `gapClick`, a click in a gap presses the highlighted
59
+ * item: its descendant marked `data-fluid-press`, or the item itself; with
60
+ * `gapReach` too, only a click within that many pixels of it, as a grid of
61
+ * cards with wide gutters wants (Fluid Functionalism's uses 16). A popup
62
+ * measured before it has a layout box keeps its last complete place, and
63
+ * tries again for three frames, rather than drawing the highlight at zero.
64
+ * The item the highlight is shown on carries `data-fluid-lit`, so a style
65
+ * can change what sits beside it (a table hides the lines around the lit
66
+ * row); its container carries `data-fluid-held` while that item is pressed.
67
+ *
68
+ * `follows` names the item the highlight sits on while the pointer is not
69
+ * moving it: a menu marks the row its keys reach (`[data-active]`), and the
70
+ * highlight goes there whenever that mark moves, so the keys and the pointer
71
+ * light the same one. `from` names the item a fresh highlight grows out of,
72
+ * as a tab's hover leaves the chosen tab. A highlight always fades where it
73
+ * is: once the pointer leaves, nothing should move. It stays only for an item
74
+ * the keyboard reached (`:focus-visible`), not one a click focused.
75
+ */
76
+ export declare const FluidHover: Mount.MountDefinitionWithArgs<"FluidHover", {
77
+ /** The highlight's name, which names the custom properties. */
78
+ name: Schema.String;
79
+ /** The selector of an item within the container. */
80
+ item: Schema.String;
81
+ axis: Schema.Literals<readonly ["x", "y", "xy"]>;
82
+ gapClick: Schema.Boolean;
83
+ /** How far from the highlighted item, in pixels, a click in a gap still presses it. */
84
+ gapReach: Schema.optional<Schema.Number>;
85
+ /** The selector of the item the highlight sits on while the pointer is not moving it. */
86
+ follows: Schema.optional<Schema.String>;
87
+ /** The selector of the item a fresh highlight grows out of. */
88
+ from: Schema.optional<Schema.String>;
89
+ /** The selector, run from a focused element outside any item, of the item it lights. */
90
+ focused: Schema.optional<Schema.String>;
91
+ }, never>;
92
+ export {};
93
+ //# sourceMappingURL=fluid-hover.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fluid-hover.d.ts","names":[],"sources":["../../src/dom/fluid-hover.ts"],"mappings":";;;qBAIa,eAAY;WAErB;WACA;WACA;WACA;;WAEA;;;;;;WAMA;;;;;;;qBAQS;;qBAGA;;qBAGA;;;;;;;;qBASA;cAEP,MAAI,OAAA;YACE,mBAAmB,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBAyDvB,YAAU,MAAA"}
@@ -0,0 +1,294 @@
1
+ import { Effect, Schema, Stream } from "effect";
2
+ import * as Mount from "foldkit/mount";
3
+ // src/dom/fluid-hover.ts
4
+ /** The custom properties `FluidHover` writes on its container for a highlight named `name`. */
5
+ const fluidHovered = (name) => ({
6
+ x: `--fk-${name}-x`,
7
+ y: `--fk-${name}-y`,
8
+ w: `--fk-${name}-w`,
9
+ h: `--fk-${name}-h`,
10
+ /** `1` while an item is highlighted, `0` once the pointer and focus have left. */
11
+ shown: `--fk-${name}-shown`,
12
+ /**
13
+ * `0` for the frame the highlight appears in, then `1`: a highlight's
14
+ * movement scales its duration by it, so it appears on its item rather
15
+ * than sliding in from where it last was.
16
+ */
17
+ moving: `--fk-${name}-moving`
18
+ });
19
+ /**
20
+ * The attribute `FluidHover` sets on its container, to the highlight's name,
21
+ * while it runs: a stylist draws the highlight, and drops each item's own
22
+ * hover, only under it.
23
+ */
24
+ const FLUID_HOVER_ATTRIBUTE = "data-fluid-hover";
25
+ /** The attribute that names, inside an item, the control a press in a gap reaches. */
26
+ const FLUID_PRESS_ATTRIBUTE = "data-fluid-press";
27
+ /** The attribute on the item the highlight is shown on, for what CSS draws beside it. */
28
+ const FLUID_LIT_ATTRIBUTE = "data-fluid-lit";
29
+ /**
30
+ * The attribute `FluidHover` sets on its container, to the highlight's name,
31
+ * while the item that highlight is on is held. A stylist draws the press on
32
+ * the highlight (`data-fluid-held`) rather than on the item, whose own press
33
+ * is hidden under it; a press in a gap marks it too where `gapClick` sends
34
+ * that press to the lit item.
35
+ */
36
+ const FLUID_HELD_ATTRIBUTE = "data-fluid-held";
37
+ const Axis = Schema.Literals([
38
+ "x",
39
+ "y",
40
+ "xy"
41
+ ]);
42
+ /** How far a point is from a rectangle along each axis: zero inside it. */
43
+ const gap = (low, high, at) => Math.max(low - at, 0, at - high);
44
+ const away = {
45
+ x: (dx, dy) => dx * 1e6 + dy,
46
+ y: (dx, dy) => dy * 1e6 + dx,
47
+ xy: Math.hypot
48
+ };
49
+ const distance = (rect, x, y, axis) => away[axis](gap(rect.left, rect.right, x), gap(rect.top, rect.bottom, y));
50
+ const isDisabled = (item) => item.matches("[aria-disabled=\"true\"], [data-disabled]:not([data-disabled=\"false\"]), :disabled");
51
+ /**
52
+ * One highlight that follows the pointer across a container's items, as a
53
+ * Mount, with no Message and no Model: which item the pointer is nearest is
54
+ * presentation, known to the DOM and to no transition.
55
+ *
56
+ * The item nearest the pointer is the one highlighted, so the pointer in a gap
57
+ * between two items still points at one, and the highlight moves from item to
58
+ * item instead of blinking off between them. On the `y` axis nearness is read
59
+ * vertically (a list), on `x` horizontally (a strip), on `xy` both (a grid). A
60
+ * disabled item (`aria-disabled="true"`, `data-disabled`, `:disabled`) is never
61
+ * highlighted. An item reached by the keyboard (`:focus-visible`) is
62
+ * highlighted too, and with `focused`, the item that selector finds from a
63
+ * focused element that is no item (a tree's row, from its focused
64
+ * `treeitem`, which also holds the rows beneath it); a touch highlights
65
+ * nothing, since there is no pointer to
66
+ * follow before the press.
67
+ *
68
+ * The container gets `--fk-<name>-x`, `-y`, `-w` and `-h` in pixels, relative
69
+ * to its scroll box like `Measure`'s, and `-shown` and `-moving` (see
70
+ * `fluidHovered`); a view draws the highlight as an absolutely placed child
71
+ * that reads them. With `gapClick`, a click in a gap presses the highlighted
72
+ * item: its descendant marked `data-fluid-press`, or the item itself; with
73
+ * `gapReach` too, only a click within that many pixels of it, as a grid of
74
+ * cards with wide gutters wants (Fluid Functionalism's uses 16). A popup
75
+ * measured before it has a layout box keeps its last complete place, and
76
+ * tries again for three frames, rather than drawing the highlight at zero.
77
+ * The item the highlight is shown on carries `data-fluid-lit`, so a style
78
+ * can change what sits beside it (a table hides the lines around the lit
79
+ * row); its container carries `data-fluid-held` while that item is pressed.
80
+ *
81
+ * `follows` names the item the highlight sits on while the pointer is not
82
+ * moving it: a menu marks the row its keys reach (`[data-active]`), and the
83
+ * highlight goes there whenever that mark moves, so the keys and the pointer
84
+ * light the same one. `from` names the item a fresh highlight grows out of,
85
+ * as a tab's hover leaves the chosen tab. A highlight always fades where it
86
+ * is: once the pointer leaves, nothing should move. It stays only for an item
87
+ * the keyboard reached (`:focus-visible`), not one a click focused.
88
+ */
89
+ const FluidHover = Mount.defineStream("FluidHover", {
90
+ messages: [Schema.Never],
91
+ args: {
92
+ /** The highlight's name, which names the custom properties. */
93
+ name: Schema.String,
94
+ /** The selector of an item within the container. */
95
+ item: Schema.String,
96
+ axis: Axis,
97
+ gapClick: Schema.Boolean,
98
+ /** How far from the highlighted item, in pixels, a click in a gap still presses it. */
99
+ gapReach: Schema.optional(Schema.Number),
100
+ /** The selector of the item the highlight sits on while the pointer is not moving it. */
101
+ follows: Schema.optional(Schema.String),
102
+ /** The selector of the item a fresh highlight grows out of. */
103
+ from: Schema.optional(Schema.String),
104
+ /** The selector, run from a focused element outside any item, of the item it lights. */
105
+ focused: Schema.optional(Schema.String)
106
+ },
107
+ execute: ({ element, name, item: selector, axis, gapClick, gapReach, follows, from, focused }) => Stream.callback(() => Effect.acquireRelease(Effect.sync(() => {
108
+ const container = element;
109
+ const property = fluidHovered(name);
110
+ let active = null;
111
+ let followed = null;
112
+ let pointer = null;
113
+ let frame;
114
+ const origin = () => from === void 0 ? null : container.querySelector(from);
115
+ let retries = 0;
116
+ const place = (at = active) => {
117
+ if (at === null) return;
118
+ const box = container.getBoundingClientRect();
119
+ const rect = at.getBoundingClientRect();
120
+ if (rect.width === 0 && rect.height === 0) {
121
+ if (retries < 3) {
122
+ retries += 1;
123
+ requestAnimationFrame(() => place(at));
124
+ }
125
+ return;
126
+ }
127
+ retries = 0;
128
+ const x = rect.left - box.left - container.clientLeft + container.scrollLeft;
129
+ const y = rect.top - box.top - container.clientTop + container.scrollTop;
130
+ container.style.setProperty(property.x, `${x}px`);
131
+ container.style.setProperty(property.y, `${y}px`);
132
+ container.style.setProperty(property.w, `${rect.width}px`);
133
+ container.style.setProperty(property.h, `${rect.height}px`);
134
+ };
135
+ /** Marks `item` as the lit one, and nothing else. */
136
+ const light = (item) => {
137
+ container.querySelectorAll(`[${FLUID_LIT_ATTRIBUTE}]`).forEach((each) => each !== item && each.removeAttribute("data-fluid-lit"));
138
+ item?.setAttribute(FLUID_LIT_ATTRIBUTE, "");
139
+ };
140
+ const show = (next) => {
141
+ const appearing = container.style.getPropertyValue(property.shown) !== "1";
142
+ active = next;
143
+ light(next);
144
+ const grows = appearing ? origin() : null;
145
+ if (appearing) container.style.setProperty(property.moving, "0");
146
+ if (grows === null) {
147
+ place();
148
+ container.style.setProperty(property.shown, "1");
149
+ } else {
150
+ place(grows);
151
+ requestAnimationFrame(() => {
152
+ if (active !== next) return;
153
+ place();
154
+ container.style.setProperty(property.shown, "1");
155
+ });
156
+ }
157
+ if (appearing) requestAnimationFrame(() => container.style.setProperty(property.moving, "1"));
158
+ };
159
+ const hide = () => {
160
+ container.style.setProperty(property.shown, "0");
161
+ container.removeAttribute(FLUID_HELD_ATTRIBUTE);
162
+ light(null);
163
+ };
164
+ /** Whether the keyboard has an item focused, which the highlight then stays on. */
165
+ const keyed = () => {
166
+ const focused = document.activeElement;
167
+ return focused !== null && container.contains(focused) && focused.matches(":focus-visible");
168
+ };
169
+ const nearest = (x, y) => {
170
+ let best = null;
171
+ let bestDistance = Infinity;
172
+ for (const each of Array.from(container.querySelectorAll(selector))) {
173
+ if (isDisabled(each)) continue;
174
+ const far = distance(each.getBoundingClientRect(), x, y, axis);
175
+ if (far < bestDistance) {
176
+ best = each;
177
+ bestDistance = far;
178
+ }
179
+ }
180
+ return best;
181
+ };
182
+ const follow = () => {
183
+ frame = void 0;
184
+ if (pointer === null) return;
185
+ const next = nearest(pointer.x, pointer.y);
186
+ if (next === null) hide();
187
+ else if (next !== active || container.style.getPropertyValue(property.shown) !== "1") show(next);
188
+ };
189
+ const move = (event) => {
190
+ if (event.pointerType === "touch") return;
191
+ pointer = {
192
+ x: event.clientX,
193
+ y: event.clientY
194
+ };
195
+ if (frame === void 0) frame = requestAnimationFrame(follow);
196
+ };
197
+ const leave = () => {
198
+ pointer = null;
199
+ release();
200
+ if (!keyed()) hide();
201
+ };
202
+ const focus = (event) => {
203
+ if (!(event.target instanceof Element) || !event.target.matches(":focus-visible")) return;
204
+ const owner = event.target.closest(selector) ?? (focused === void 0 ? null : event.target.querySelector(focused));
205
+ if (owner !== null && container.contains(owner) && !isDisabled(owner)) show(owner);
206
+ };
207
+ const blur = (event) => {
208
+ const to = event.relatedTarget;
209
+ if (pointer === null && !(to instanceof Node && container.contains(to))) hide();
210
+ };
211
+ const reachOf = (item, event) => gapReach === void 0 || distance(item.getBoundingClientRect(), event.clientX, event.clientY, "xy") <= gapReach;
212
+ /** Whether a click in a gap presses the lit item, within `gapReach` of it. */
213
+ const reaches = (item, event) => gapClick && reachOf(item, event);
214
+ const click = (event) => {
215
+ if (active === null) return;
216
+ if (container.style.getPropertyValue(property.shown) !== "1") return;
217
+ const target = event.target;
218
+ if (!(target instanceof Element) || target.closest(selector) !== null) return;
219
+ if (!reaches(active, event)) return;
220
+ const press = active.querySelector(`[data-fluid-press]`) ?? active;
221
+ if (press instanceof HTMLElement) press.click();
222
+ };
223
+ const soon = () => {
224
+ if (active !== null) requestAnimationFrame(() => place());
225
+ };
226
+ /**
227
+ * Marks the container as held where the press is the lit item's: the
228
+ * item itself, or a gap a click there reaches through (`gapClick`). A
229
+ * press on another item is that item's, once the pointer has lit it.
230
+ */
231
+ const press = (event) => {
232
+ if (event.button !== 0 || active === null) return;
233
+ if (container.style.getPropertyValue(property.shown) !== "1") return;
234
+ const target = event.target;
235
+ if (!(target instanceof Element)) return;
236
+ const inItem = target.closest(selector) !== null;
237
+ if (inItem && !active.contains(target)) return;
238
+ if (!inItem && !reaches(active, event)) return;
239
+ container.setAttribute(FLUID_HELD_ATTRIBUTE, name);
240
+ };
241
+ const release = () => container.removeAttribute(FLUID_HELD_ATTRIBUTE);
242
+ /** The marked item moved: the highlight goes with it, or fades if it is gone. */
243
+ const marked = () => {
244
+ if (follows === void 0) return;
245
+ const next = container.querySelector(follows);
246
+ if (next === followed) return;
247
+ followed = next;
248
+ if (next !== null && !isDisabled(next)) show(next);
249
+ else if (pointer === null && !keyed()) hide();
250
+ };
251
+ const sizes = typeof ResizeObserver === "undefined" ? void 0 : new ResizeObserver(soon);
252
+ const marks = follows === void 0 ? void 0 : new MutationObserver(marked);
253
+ sizes?.observe(container);
254
+ marks?.observe(container, {
255
+ subtree: true,
256
+ childList: true,
257
+ attributes: true
258
+ });
259
+ container.addEventListener("pointermove", move, { passive: true });
260
+ container.addEventListener("pointerdown", press);
261
+ container.addEventListener("pointerleave", leave);
262
+ window.addEventListener("pointerup", release);
263
+ window.addEventListener("pointercancel", release);
264
+ container.addEventListener("focusin", focus);
265
+ container.addEventListener("focusout", blur);
266
+ container.addEventListener("click", click);
267
+ container.addEventListener("scroll", soon, { passive: true });
268
+ window.addEventListener("resize", soon);
269
+ container.style.setProperty(property.shown, "0");
270
+ container.setAttribute(FLUID_HOVER_ATTRIBUTE, name);
271
+ marked();
272
+ return () => {
273
+ if (frame !== void 0) cancelAnimationFrame(frame);
274
+ sizes?.disconnect();
275
+ marks?.disconnect();
276
+ container.removeAttribute(FLUID_HOVER_ATTRIBUTE);
277
+ container.removeAttribute(FLUID_HELD_ATTRIBUTE);
278
+ light(null);
279
+ container.removeEventListener("pointermove", move);
280
+ container.removeEventListener("pointerdown", press);
281
+ container.removeEventListener("pointerleave", leave);
282
+ window.removeEventListener("pointerup", release);
283
+ window.removeEventListener("pointercancel", release);
284
+ container.removeEventListener("focusin", focus);
285
+ container.removeEventListener("focusout", blur);
286
+ container.removeEventListener("click", click);
287
+ container.removeEventListener("scroll", soon);
288
+ window.removeEventListener("resize", soon);
289
+ };
290
+ }), (stop) => Effect.sync(stop)))
291
+ });
292
+ export { FLUID_HELD_ATTRIBUTE, FLUID_HOVER_ATTRIBUTE, FLUID_LIT_ATTRIBUTE, FLUID_PRESS_ATTRIBUTE, FluidHover, fluidHovered };
293
+
294
+ //# sourceMappingURL=fluid-hover.js.map