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,53 @@
1
+ import { Effect, Queue, Schema, Stream } from "effect";
2
+ import * as Mount from "foldkit/mount";
3
+ // src/observers/mutation.ts
4
+ const Mutated = Schema.TaggedStruct("Mutated", {
5
+ type: Schema.Literals([
6
+ "childList",
7
+ "attributes",
8
+ "characterData"
9
+ ]),
10
+ added: Schema.Array(Schema.String),
11
+ removed: Schema.Array(Schema.String),
12
+ attribute: Schema.NullOr(Schema.String)
13
+ });
14
+ const recordType = (type) => type === "childList" || type === "attributes" || type === "characterData" ? type : null;
15
+ /**
16
+ * DOM mutations as a Mount: MutationObserver reports child, attribute, and
17
+ * text changes as Messages for the element carrying this Mount. Nodes cross
18
+ * as their names (serializable); the live nodes stay in the DOM, never in
19
+ * the Model. No observer (SSR, old browser) emits nothing instead of
20
+ * throwing. Observes the whole subtree — narrow by placing on a smaller
21
+ * element, not by options.
22
+ */
23
+ const Mutation = Mount.defineStream("Mutation", {
24
+ messages: [Mutated],
25
+ execute: ({ element }) => Stream.callback((queue) => Effect.gen(function* () {
26
+ const Observed = globalThis.MutationObserver;
27
+ if (Observed === void 0) return;
28
+ yield* Effect.acquireRelease(Effect.sync(() => {
29
+ const observer = new Observed((records) => {
30
+ for (const record of records) {
31
+ const type = recordType(record.type);
32
+ if (type === null) continue;
33
+ Queue.offerUnsafe(queue, Mutated.make({
34
+ type,
35
+ added: type === "childList" ? Array.from(record.addedNodes, (node) => node.nodeName) : [],
36
+ removed: type === "childList" ? Array.from(record.removedNodes, (node) => node.nodeName) : [],
37
+ attribute: type === "attributes" ? record.attributeName ?? null : null
38
+ }));
39
+ }
40
+ });
41
+ observer.observe(element, {
42
+ childList: true,
43
+ attributes: true,
44
+ characterData: true,
45
+ subtree: true
46
+ });
47
+ return observer;
48
+ }), (observer) => Effect.sync(() => observer.disconnect()));
49
+ }))
50
+ });
51
+ export { Mutated, Mutation };
52
+
53
+ //# sourceMappingURL=mutation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mutation.js","names":[],"sources":["../../src/observers/mutation.ts"],"sourcesContent":["import { Effect, Queue, Schema, Stream } from 'effect'\nimport * as Mount from 'foldkit/mount'\n\nexport const Mutated = Schema.TaggedStruct('Mutated', {\n type: Schema.Literals(['childList', 'attributes', 'characterData']),\n added: Schema.Array(Schema.String),\n removed: Schema.Array(Schema.String),\n attribute: Schema.NullOr(Schema.String),\n})\nexport type Mutated = typeof Mutated.Type\n\ntype ObserverCtor = new (callback: MutationCallback) => MutationObserver\n\nconst recordType = (type: string): Mutated['type'] | null =>\n type === 'childList' || type === 'attributes' || type === 'characterData' ? type : null\n\n/**\n * DOM mutations as a Mount: MutationObserver reports child, attribute, and\n * text changes as Messages for the element carrying this Mount. Nodes cross\n * as their names (serializable); the live nodes stay in the DOM, never in\n * the Model. No observer (SSR, old browser) emits nothing instead of\n * throwing. Observes the whole subtree — narrow by placing on a smaller\n * element, not by options.\n */\nexport const Mutation = Mount.defineStream('Mutation', {\n messages: [Mutated],\n execute: ({ element }) =>\n Stream.callback<typeof Mutated.Type>(queue =>\n Effect.gen(function* () {\n const Observed = (globalThis as { MutationObserver?: ObserverCtor }).MutationObserver\n if (Observed === undefined) return\n yield* Effect.acquireRelease(\n Effect.sync(() => {\n const observer = new Observed(records => {\n for (const record of records) {\n const type = recordType(record.type)\n if (type === null) continue\n Queue.offerUnsafe(\n queue,\n Mutated.make({\n type,\n added:\n type === 'childList'\n ? Array.from(record.addedNodes, node => node.nodeName)\n : [],\n removed:\n type === 'childList'\n ? Array.from(record.removedNodes, node => node.nodeName)\n : [],\n attribute: type === 'attributes' ? (record.attributeName ?? null) : null,\n }),\n )\n }\n })\n observer.observe(element, {\n childList: true,\n attributes: true,\n characterData: true,\n subtree: true,\n })\n return observer\n }),\n observer => Effect.sync(() => observer.disconnect()),\n )\n }),\n ),\n})\n"],"mappings":";;;AAGA,MAAa,UAAU,OAAO,aAAa,WAAW;CACpD,MAAM,OAAO,SAAS;EAAC;EAAa;EAAc;CAAe,CAAC;CAClE,OAAO,OAAO,MAAM,OAAO,MAAM;CACjC,SAAS,OAAO,MAAM,OAAO,MAAM;CACnC,WAAW,OAAO,OAAO,OAAO,MAAM;AACxC,CAAC;AAKD,MAAM,cAAc,SAClB,SAAS,eAAe,SAAS,gBAAgB,SAAS,kBAAkB,OAAO;;;;;;;;;AAUrF,MAAa,WAAW,MAAM,aAAa,YAAY;CACrD,UAAU,CAAC,OAAO;CAClB,UAAU,EAAE,cACV,OAAO,UAA8B,UACnC,OAAO,IAAI,aAAa;EACtB,MAAM,WAAY,WAAmD;EACrE,IAAI,aAAa,KAAA,GAAW;EAC5B,OAAO,OAAO,eACZ,OAAO,WAAW;GAChB,MAAM,WAAW,IAAI,UAAS,YAAW;IACvC,KAAK,MAAM,UAAU,SAAS;KAC5B,MAAM,OAAO,WAAW,OAAO,IAAI;KACnC,IAAI,SAAS,MAAM;KACnB,MAAM,YACJ,OACA,QAAQ,KAAK;MACX;MACA,OACE,SAAS,cACL,MAAM,KAAK,OAAO,aAAY,SAAQ,KAAK,QAAQ,IACnD,CAAC;MACP,SACE,SAAS,cACL,MAAM,KAAK,OAAO,eAAc,SAAQ,KAAK,QAAQ,IACrD,CAAC;MACP,WAAW,SAAS,eAAgB,OAAO,iBAAiB,OAAQ;KACtE,CAAC,CACH;IACF;GACF,CAAC;GACD,SAAS,QAAQ,SAAS;IACxB,WAAW;IACX,YAAY;IACZ,eAAe;IACf,SAAS;GACX,CAAC;GACD,OAAO;EACT,CAAC,IACD,aAAY,OAAO,WAAW,SAAS,WAAW,CAAC,CACrD;CACF,CAAC,CACH;AACJ,CAAC"}
@@ -0,0 +1,18 @@
1
+ import { Schema } from "effect";
2
+ import * as Mount from "foldkit/mount";
3
+ export declare const Resized: Schema.TaggedStruct<"Resized", {
4
+ readonly width: Schema.Number;
5
+ readonly height: Schema.Number;
6
+ }>;
7
+ export type Resized = typeof Resized.Type;
8
+ /**
9
+ * Element size as a Mount: ResizeObserver reports content-box changes as
10
+ * Messages for the element carrying this Mount. No observer (SSR, old
11
+ * browser) emits nothing instead of throwing.
12
+ */
13
+ export declare const Resize: Mount.MountDefinitionNoArgs<"Resize", {
14
+ readonly _tag: "Resized";
15
+ readonly width: number;
16
+ readonly height: number;
17
+ }>;
18
+ //# sourceMappingURL=resize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resize.d.ts","names":[],"sources":["../../src/observers/resize.ts"],"mappings":";;qBAGa,SAAO,OAAA;;;;YAIR,iBAAiB,QAAQ;;;;;;qBASxB,QAAM,MAAA"}
@@ -0,0 +1,33 @@
1
+ import { Effect, Queue, Schema, Stream } from "effect";
2
+ import * as Mount from "foldkit/mount";
3
+ // src/observers/resize.ts
4
+ const Resized = Schema.TaggedStruct("Resized", {
5
+ width: Schema.Number,
6
+ height: Schema.Number
7
+ });
8
+ /**
9
+ * Element size as a Mount: ResizeObserver reports content-box changes as
10
+ * Messages for the element carrying this Mount. No observer (SSR, old
11
+ * browser) emits nothing instead of throwing.
12
+ */
13
+ const Resize = Mount.defineStream("Resize", {
14
+ messages: [Resized],
15
+ execute: ({ element }) => Stream.callback((queue) => Effect.gen(function* () {
16
+ const Observed = globalThis.ResizeObserver;
17
+ if (Observed === void 0) return;
18
+ yield* Effect.acquireRelease(Effect.sync(() => {
19
+ const observer = new Observed((entries) => {
20
+ const rect = entries[0]?.contentRect;
21
+ if (rect !== void 0) Queue.offerUnsafe(queue, Resized.make({
22
+ width: rect.width,
23
+ height: rect.height
24
+ }));
25
+ });
26
+ observer.observe(element);
27
+ return observer;
28
+ }), (observer) => Effect.sync(() => observer.disconnect()));
29
+ }))
30
+ });
31
+ export { Resize, Resized };
32
+
33
+ //# sourceMappingURL=resize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resize.js","names":[],"sources":["../../src/observers/resize.ts"],"sourcesContent":["import { Effect, Queue, Schema, Stream } from 'effect'\nimport * as Mount from 'foldkit/mount'\n\nexport const Resized = Schema.TaggedStruct('Resized', {\n width: Schema.Number,\n height: Schema.Number,\n})\nexport type Resized = typeof Resized.Type\n\ntype ObserverCtor = new (callback: ResizeObserverCallback) => ResizeObserver\n\n/**\n * Element size as a Mount: ResizeObserver reports content-box changes as\n * Messages for the element carrying this Mount. No observer (SSR, old\n * browser) emits nothing instead of throwing.\n */\nexport const Resize = Mount.defineStream('Resize', {\n messages: [Resized],\n execute: ({ element }) =>\n Stream.callback<typeof Resized.Type>(queue =>\n Effect.gen(function* () {\n const Observed = (globalThis as { ResizeObserver?: ObserverCtor }).ResizeObserver\n if (Observed === undefined) return\n yield* Effect.acquireRelease(\n Effect.sync(() => {\n const observer = new Observed(entries => {\n const rect = entries[0]?.contentRect\n if (rect !== undefined) {\n Queue.offerUnsafe(queue, Resized.make({ width: rect.width, height: rect.height }))\n }\n })\n observer.observe(element)\n return observer\n }),\n observer => Effect.sync(() => observer.disconnect()),\n )\n }),\n ),\n})\n"],"mappings":";;;AAGA,MAAa,UAAU,OAAO,aAAa,WAAW;CACpD,OAAO,OAAO;CACd,QAAQ,OAAO;AACjB,CAAC;;;;;;AAUD,MAAa,SAAS,MAAM,aAAa,UAAU;CACjD,UAAU,CAAC,OAAO;CAClB,UAAU,EAAE,cACV,OAAO,UAA8B,UACnC,OAAO,IAAI,aAAa;EACtB,MAAM,WAAY,WAAiD;EACnE,IAAI,aAAa,KAAA,GAAW;EAC5B,OAAO,OAAO,eACZ,OAAO,WAAW;GAChB,MAAM,WAAW,IAAI,UAAS,YAAW;IACvC,MAAM,OAAO,QAAQ,EAAE,EAAE;IACzB,IAAI,SAAS,KAAA,GACX,MAAM,YAAY,OAAO,QAAQ,KAAK;KAAE,OAAO,KAAK;KAAO,QAAQ,KAAK;IAAO,CAAC,CAAC;GAErF,CAAC;GACD,SAAS,QAAQ,OAAO;GACxB,OAAO;EACT,CAAC,IACD,aAAY,OAAO,WAAW,SAAS,WAAW,CAAC,CACrD;CACF,CAAC,CACH;AACJ,CAAC"}
@@ -0,0 +1,115 @@
1
+ import { Schema } from "effect";
2
+ import { Bundle } from "foldkit-bundle";
3
+ export declare const HistoryModel: <Value>(value: Schema.Codec<Value, unknown>) => Schema.Struct<{
4
+ readonly past: Schema.$Array<Schema.Codec<Value, unknown, never, never>>;
5
+ readonly present: Schema.Codec<Value, unknown, never, never>;
6
+ readonly future: Schema.$Array<Schema.Codec<Value, unknown, never, never>>;
7
+ /** The group of the last push, so the next push of the same group joins it; `null` for none. */
8
+ readonly group: Schema.NullOr<Schema.String>;
9
+ }>;
10
+ export type HistoryModel<Value> = {
11
+ readonly past: ReadonlyArray<Value>;
12
+ readonly present: Value;
13
+ readonly future: ReadonlyArray<Value>;
14
+ readonly group: string | null;
15
+ };
16
+ declare const start: <Value>(present: Value) => HistoryModel<Value>;
17
+ declare const push: <Value>(model: HistoryModel<Value>, value: Value, options: {
18
+ readonly capacity: number;
19
+ readonly group?: string | null | undefined;
20
+ }) => HistoryModel<Value>;
21
+ declare const undo: <Value>(model: HistoryModel<Value>) => HistoryModel<Value>;
22
+ declare const redo: <Value>(model: HistoryModel<Value>) => HistoryModel<Value>;
23
+ declare const goTo: <Value>(model: HistoryModel<Value>, step: number) => HistoryModel<Value>;
24
+ declare const clear: <Value>(model: HistoryModel<Value>) => HistoryModel<Value>;
25
+ declare const close: <Value>(model: HistoryModel<Value>) => HistoryModel<Value>;
26
+ declare const revert: <Value>(model: HistoryModel<Value>, group: string) => HistoryModel<Value>;
27
+ /** Whether Undo would move: the past is non-empty. */
28
+ export declare const canUndo: <Value>(model: HistoryModel<Value>) => boolean;
29
+ /** Whether Redo would move: the future is non-empty. */
30
+ export declare const canRedo: <Value>(model: HistoryModel<Value>) => boolean;
31
+ /** The steps of a history as pure functions of its Model. */
32
+ export declare const History: {
33
+ /** A history whose present is `value`, with nothing to undo. */
34
+ start: typeof start;
35
+ /** Records `value` as the present; the same `group` as the last push joins its step. */
36
+ push: typeof push;
37
+ /** One step back, or the Model as it was when there is none. */
38
+ undo: typeof undo;
39
+ /** One step forward, or the Model as it was when there is none. */
40
+ redo: typeof redo;
41
+ /**
42
+ * The value at `step` made the present, counting every kept value from the
43
+ * oldest (0), so the present is at `past.length`: what a click on a step's
44
+ * thumbnail does. The Model as it was for the present or a step not kept.
45
+ */
46
+ goTo: typeof goTo;
47
+ /** Nothing to undo or redo, the present kept. */
48
+ clear: typeof clear;
49
+ /** The next push starts a step of its own, whatever its group: a group ends here. */
50
+ close: typeof close;
51
+ /**
52
+ * The step `group` is making taken back, and not redoable: what a cancelled
53
+ * edit, or one that ended where it began, leaves. The Model as it was when
54
+ * the last push was not of `group`. What the group's first push dropped
55
+ * stays dropped: the redo future it cleared, and an entry capacity evicted;
56
+ * with a capacity of 0 nothing was kept, so the present stays and only the
57
+ * group ends.
58
+ */
59
+ revert: typeof revert;
60
+ canUndo: typeof canUndo;
61
+ canRedo: typeof canRedo;
62
+ };
63
+ /**
64
+ * Undo/redo as a bundle factory: the past, present, and future of one value
65
+ * live in the Model, so every step replays. Pushing records, even an unchanged
66
+ * value; skipping duplicates is the application's policy, not the stack's.
67
+ *
68
+ * A push may name a `group`. Consecutive pushes of the same group are one step:
69
+ * the present moves and nothing new is recorded, so typing a word undoes as a
70
+ * whole. Grouping needs no clock; the application names what belongs together.
71
+ *
72
+ * The steps are also pure functions (`History.push`, `undo`, `redo`, `goTo`, `clear`),
73
+ * for a parent that records an edit in the same transition that makes it
74
+ * rather than dispatching a Message to a placed bundle.
75
+ */
76
+ export declare const history: <const Name extends string, Value>(config: {
77
+ readonly name: Name;
78
+ readonly value: Schema.Codec<Value, unknown>;
79
+ readonly capacity?: number | undefined;
80
+ }) => Bundle.Bundle<Name, {
81
+ readonly initial: Value;
82
+ }, {
83
+ readonly past: readonly Value[];
84
+ readonly present: Value;
85
+ readonly future: readonly Value[];
86
+ readonly group: string | null;
87
+ }, {
88
+ readonly _tag: "Clear";
89
+ } | {
90
+ readonly _tag: "GoTo";
91
+ readonly step: number;
92
+ } | {
93
+ readonly _tag: "Push";
94
+ readonly value: Value;
95
+ readonly group?: string | undefined;
96
+ } | {
97
+ readonly _tag: "Redo";
98
+ } | {
99
+ readonly _tag: "Undo";
100
+ }, never, never, never, void, {}, {}> & {
101
+ Message: import("foldkit/message").MessageUnion<{
102
+ readonly Push: {
103
+ value: Schema.Codec<Value, unknown, never, never>;
104
+ group: Schema.optional<Schema.String>;
105
+ };
106
+ readonly Undo: {};
107
+ readonly Redo: {};
108
+ readonly GoTo: {
109
+ step: Schema.Number;
110
+ };
111
+ readonly Clear: {};
112
+ }>;
113
+ };
114
+ export {};
115
+ //# sourceMappingURL=history.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"history.d.ts","names":[],"sources":["../../src/state/history.ts"],"mappings":";;qBAIa,eAAgB,OAAK,OAAS,OAAO,MAAM,oBAAe,OAAA;;;;;;;YAQ3D,aAAa;WACd,MAAM,cAAc;WACpB,SAAS;WACT,QAAQ,cAAc;WACtB;;cAGL,QAAS,OAAK,SAAW,UAAQ,aAAa;cAe9C,OAAQ,OAAK,OACV,aAAa,QAAM,OACnB,OAAK;WACQ;WAA2B;MAC9C,aAAa;cAcV,OAAQ,OAAK,OAAS,aAAa,WAAS,aAAa;cAWzD,OAAQ,OAAK,OAAS,aAAa,WAAS,aAAa;cAWzD,OAAQ,OAAK,OAAS,aAAa,QAAM,iBAAiB,aAAa;cAYvE,QAAS,OAAK,OAAS,aAAa,WAAS,aAAa;cAK1D,QAAS,OAAK,OAAS,aAAa,WAAS,aAAa;cAG1D,SAAU,OAAK,OAAS,aAAa,QAAM,kBAAkB,aAAa;;qBAanE,UAAW,OAAK,OAAS,aAAa;;qBAGtC,UAAW,OAAK,OAAS,aAAa;;qBAGtC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBA6CA,gBAAiB,qBAAqB,OAAK;WAC7C,MAAM;WACN,OAAO,OAAO,MAAM;WACpB;MACV,OAAA,OAAA;;;;;;;;;;;;;;;;;;;;;;;MAIW,OAAK,OAAA,MAAA;MAAgB,OAAK,OAAA,SAAA,OAAA;;;;;MAG1B,MAAI,OAAA"}
@@ -0,0 +1,167 @@
1
+ import { Schema } from "effect";
2
+ import { defineMessageUnion } from "foldkit/message";
3
+ import { Bundle } from "foldkit-bundle";
4
+ // src/state/history.ts
5
+ const HistoryModel = (value) => Schema.Struct({
6
+ past: Schema.Array(value),
7
+ present: value,
8
+ future: Schema.Array(value),
9
+ /** The group of the last push, so the next push of the same group joins it; `null` for none. */
10
+ group: Schema.NullOr(Schema.String)
11
+ });
12
+ const start = (present) => ({
13
+ past: [],
14
+ present,
15
+ future: [],
16
+ group: null
17
+ });
18
+ /**
19
+ * No redo steps, keeping an already empty future: a view that reads the
20
+ * future compares it by identity, so a push per keystroke or stroke cell
21
+ * must not hand it a new empty array each time.
22
+ */
23
+ const noFuture = (model) => model.future.length === 0 ? model.future : [];
24
+ const push = (model, value, options) => {
25
+ const group = options.group ?? null;
26
+ if (group !== null && group === model.group && model.past.length > 0) return {
27
+ ...model,
28
+ present: value,
29
+ future: noFuture(model)
30
+ };
31
+ return {
32
+ past: options.capacity === 0 ? [] : [...model.past, model.present].slice(-options.capacity),
33
+ present: value,
34
+ future: noFuture(model),
35
+ group
36
+ };
37
+ };
38
+ const undo = (model) => {
39
+ const previous = model.past[model.past.length - 1];
40
+ if (previous === void 0) return model;
41
+ return {
42
+ past: model.past.slice(0, -1),
43
+ present: previous,
44
+ future: [model.present, ...model.future],
45
+ group: null
46
+ };
47
+ };
48
+ const redo = (model) => {
49
+ const next = model.future[0];
50
+ if (next === void 0) return model;
51
+ return {
52
+ past: [...model.past, model.present],
53
+ present: next,
54
+ future: model.future.slice(1),
55
+ group: null
56
+ };
57
+ };
58
+ const goTo = (model, step) => {
59
+ const steps = [
60
+ ...model.past,
61
+ model.present,
62
+ ...model.future
63
+ ];
64
+ if (!Number.isInteger(step) || step < 0 || step >= steps.length || step === model.past.length) return model;
65
+ return {
66
+ past: steps.slice(0, step),
67
+ present: steps[step],
68
+ future: steps.slice(step + 1),
69
+ group: null
70
+ };
71
+ };
72
+ const clear = (model) => model.past.length === 0 && model.future.length === 0 && model.group === null ? model : start(model.present);
73
+ const close = (model) => model.group === null ? model : {
74
+ ...model,
75
+ group: null
76
+ };
77
+ const revert = (model, group) => model.group === group ? {
78
+ ...undo(model),
79
+ future: [],
80
+ group: null
81
+ } : model;
82
+ const checkCapacity = (name, capacity) => {
83
+ if (!Number.isInteger(capacity) || capacity < 0) throw new Error(`History "${name}": capacity must be a non-negative integer`);
84
+ return capacity;
85
+ };
86
+ /** Whether Undo would move: the past is non-empty. */
87
+ const canUndo = (model) => model.past.length > 0;
88
+ /** Whether Redo would move: the future is non-empty. */
89
+ const canRedo = (model) => model.future.length > 0;
90
+ /** The steps of a history as pure functions of its Model. */
91
+ const History = {
92
+ /** A history whose present is `value`, with nothing to undo. */
93
+ start,
94
+ /** Records `value` as the present; the same `group` as the last push joins its step. */
95
+ push,
96
+ /** One step back, or the Model as it was when there is none. */
97
+ undo,
98
+ /** One step forward, or the Model as it was when there is none. */
99
+ redo,
100
+ /**
101
+ * The value at `step` made the present, counting every kept value from the
102
+ * oldest (0), so the present is at `past.length`: what a click on a step's
103
+ * thumbnail does. The Model as it was for the present or a step not kept.
104
+ */
105
+ goTo,
106
+ /** Nothing to undo or redo, the present kept. */
107
+ clear,
108
+ /** The next push starts a step of its own, whatever its group: a group ends here. */
109
+ close,
110
+ /**
111
+ * The step `group` is making taken back, and not redoable: what a cancelled
112
+ * edit, or one that ended where it began, leaves. The Model as it was when
113
+ * the last push was not of `group`. What the group's first push dropped
114
+ * stays dropped: the redo future it cleared, and an entry capacity evicted;
115
+ * with a capacity of 0 nothing was kept, so the present stays and only the
116
+ * group ends.
117
+ */
118
+ revert,
119
+ canUndo,
120
+ canRedo
121
+ };
122
+ /**
123
+ * Undo/redo as a bundle factory: the past, present, and future of one value
124
+ * live in the Model, so every step replays. Pushing records, even an unchanged
125
+ * value; skipping duplicates is the application's policy, not the stack's.
126
+ *
127
+ * A push may name a `group`. Consecutive pushes of the same group are one step:
128
+ * the present moves and nothing new is recorded, so typing a word undoes as a
129
+ * whole. Grouping needs no clock; the application names what belongs together.
130
+ *
131
+ * The steps are also pure functions (`History.push`, `undo`, `redo`, `goTo`, `clear`),
132
+ * for a parent that records an edit in the same transition that makes it
133
+ * rather than dispatching a Message to a placed bundle.
134
+ */
135
+ const history = (config) => {
136
+ const capacity = checkCapacity(config.name, config.capacity ?? 100);
137
+ const Model = HistoryModel(config.value);
138
+ const Message = defineMessageUnion({
139
+ Push: {
140
+ value: config.value,
141
+ group: Schema.optional(Schema.String)
142
+ },
143
+ Undo: {},
144
+ Redo: {},
145
+ GoTo: { step: Schema.Number },
146
+ Clear: {}
147
+ });
148
+ return Object.assign(Bundle.make(config.name, {
149
+ Model,
150
+ Message,
151
+ args: Schema.Struct({ initial: config.value }),
152
+ init: (args) => ({ model: start(args.initial) }),
153
+ update: (model, message) => Message.match(message, {
154
+ Push: ({ value, group }) => ({ model: push(model, value, {
155
+ capacity,
156
+ group
157
+ }) }),
158
+ Undo: () => ({ model: undo(model) }),
159
+ Redo: () => ({ model: redo(model) }),
160
+ GoTo: ({ step }) => ({ model: goTo(model, step) }),
161
+ Clear: () => ({ model: clear(model) })
162
+ })
163
+ }), { Message });
164
+ };
165
+ export { History, HistoryModel, canRedo, canUndo, history };
166
+
167
+ //# sourceMappingURL=history.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"history.js","names":[],"sources":["../../src/state/history.ts"],"sourcesContent":["import { Schema } from 'effect'\nimport { defineMessageUnion } from 'foldkit/message'\nimport { Bundle } from 'foldkit-bundle'\n\nexport const HistoryModel = <Value>(value: Schema.Codec<Value, unknown>) =>\n Schema.Struct({\n past: Schema.Array(value),\n present: value,\n future: Schema.Array(value),\n /** The group of the last push, so the next push of the same group joins it; `null` for none. */\n group: Schema.NullOr(Schema.String),\n })\nexport type HistoryModel<Value> = {\n readonly past: ReadonlyArray<Value>\n readonly present: Value\n readonly future: ReadonlyArray<Value>\n readonly group: string | null\n}\n\nconst start = <Value>(present: Value): HistoryModel<Value> => ({\n past: [],\n present,\n future: [],\n group: null,\n})\n\n/**\n * No redo steps, keeping an already empty future: a view that reads the\n * future compares it by identity, so a push per keystroke or stroke cell\n * must not hand it a new empty array each time.\n */\nconst noFuture = <Value>(model: HistoryModel<Value>): ReadonlyArray<Value> =>\n model.future.length === 0 ? model.future : []\n\nconst push = <Value>(\n model: HistoryModel<Value>,\n value: Value,\n options: { readonly capacity: number; readonly group?: string | null | undefined },\n): HistoryModel<Value> => {\n const group = options.group ?? null\n // The same group again joins the last step: the present moves, the past stays.\n if (group !== null && group === model.group && model.past.length > 0)\n return { ...model, present: value, future: noFuture(model) }\n return {\n // slice(-0) is slice(0): a zero capacity keeps nothing, explicitly.\n past: options.capacity === 0 ? [] : [...model.past, model.present].slice(-options.capacity),\n present: value,\n future: noFuture(model),\n group,\n }\n}\n\nconst undo = <Value>(model: HistoryModel<Value>): HistoryModel<Value> => {\n const previous = model.past[model.past.length - 1]\n if (previous === undefined) return model\n return {\n past: model.past.slice(0, -1),\n present: previous,\n future: [model.present, ...model.future],\n group: null,\n }\n}\n\nconst redo = <Value>(model: HistoryModel<Value>): HistoryModel<Value> => {\n const next = model.future[0]\n if (next === undefined) return model\n return {\n past: [...model.past, model.present],\n present: next,\n future: model.future.slice(1),\n group: null,\n }\n}\n\nconst goTo = <Value>(model: HistoryModel<Value>, step: number): HistoryModel<Value> => {\n const steps = [...model.past, model.present, ...model.future]\n if (!Number.isInteger(step) || step < 0 || step >= steps.length || step === model.past.length)\n return model\n return {\n past: steps.slice(0, step),\n present: steps[step]!,\n future: steps.slice(step + 1),\n group: null,\n }\n}\n\nconst clear = <Value>(model: HistoryModel<Value>): HistoryModel<Value> =>\n model.past.length === 0 && model.future.length === 0 && model.group === null\n ? model\n : start(model.present)\n\nconst close = <Value>(model: HistoryModel<Value>): HistoryModel<Value> =>\n model.group === null ? model : { ...model, group: null }\n\nconst revert = <Value>(model: HistoryModel<Value>, group: string): HistoryModel<Value> =>\n // The group is ended even where there is nothing to take back (capacity 0).\n model.group === group ? { ...undo(model), future: [], group: null } : model\n\nconst checkCapacity = (name: string, capacity: number): number => {\n // A negative or fractional capacity would silently keep a wrong-sized past;\n // fail where it is given, naming the caller, instead.\n if (!Number.isInteger(capacity) || capacity < 0)\n throw new Error(`History \"${name}\": capacity must be a non-negative integer`)\n return capacity\n}\n\n/** Whether Undo would move: the past is non-empty. */\nexport const canUndo = <Value>(model: HistoryModel<Value>): boolean => model.past.length > 0\n\n/** Whether Redo would move: the future is non-empty. */\nexport const canRedo = <Value>(model: HistoryModel<Value>): boolean => model.future.length > 0\n\n/** The steps of a history as pure functions of its Model. */\nexport const History = {\n /** A history whose present is `value`, with nothing to undo. */\n start,\n /** Records `value` as the present; the same `group` as the last push joins its step. */\n push,\n /** One step back, or the Model as it was when there is none. */\n undo,\n /** One step forward, or the Model as it was when there is none. */\n redo,\n /**\n * The value at `step` made the present, counting every kept value from the\n * oldest (0), so the present is at `past.length`: what a click on a step's\n * thumbnail does. The Model as it was for the present or a step not kept.\n */\n goTo,\n /** Nothing to undo or redo, the present kept. */\n clear,\n /** The next push starts a step of its own, whatever its group: a group ends here. */\n close,\n /**\n * The step `group` is making taken back, and not redoable: what a cancelled\n * edit, or one that ended where it began, leaves. The Model as it was when\n * the last push was not of `group`. What the group's first push dropped\n * stays dropped: the redo future it cleared, and an entry capacity evicted;\n * with a capacity of 0 nothing was kept, so the present stays and only the\n * group ends.\n */\n revert,\n canUndo,\n canRedo,\n}\n\n/**\n * Undo/redo as a bundle factory: the past, present, and future of one value\n * live in the Model, so every step replays. Pushing records, even an unchanged\n * value; skipping duplicates is the application's policy, not the stack's.\n *\n * A push may name a `group`. Consecutive pushes of the same group are one step:\n * the present moves and nothing new is recorded, so typing a word undoes as a\n * whole. Grouping needs no clock; the application names what belongs together.\n *\n * The steps are also pure functions (`History.push`, `undo`, `redo`, `goTo`, `clear`),\n * for a parent that records an edit in the same transition that makes it\n * rather than dispatching a Message to a placed bundle.\n */\nexport const history = <const Name extends string, Value>(config: {\n readonly name: Name\n readonly value: Schema.Codec<Value, unknown>\n readonly capacity?: number | undefined\n}) => {\n const capacity = checkCapacity(config.name, config.capacity ?? 100)\n const Model = HistoryModel(config.value)\n const Message = defineMessageUnion({\n Push: { value: config.value, group: Schema.optional(Schema.String) },\n Undo: {},\n Redo: {},\n GoTo: { step: Schema.Number },\n Clear: {},\n })\n return Object.assign(\n Bundle.make(config.name, {\n Model,\n Message,\n args: Schema.Struct({ initial: config.value }),\n init: args => ({ model: start(args.initial) }),\n update: (model, message) =>\n Message.match(message, {\n Push: ({ value, group }) => ({ model: push(model, value, { capacity, group }) }),\n Undo: () => ({ model: undo(model) }),\n Redo: () => ({ model: redo(model) }),\n GoTo: ({ step }) => ({ model: goTo(model, step) }),\n Clear: () => ({ model: clear(model) }),\n }),\n }),\n // The union object is both the Message codec and its constructors, so a\n // placement dispatches `EditHistory.Message.Push(...)` like any bundle's\n // exported Message.\n { Message },\n )\n}\n"],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export * from "./history.js";
2
+ export * from "./locale.js";
3
+ export * from "./pagination.js";
4
+ export * from "./range.js";
5
+ export * from "./selection.js";
6
+ export * from "./virtual.js";
@@ -0,0 +1,7 @@
1
+ export * from "./history.js";
2
+ export * from "./locale.js";
3
+ export * from "./pagination.js";
4
+ export * from "./range.js";
5
+ export * from "./selection.js";
6
+ export * from "./virtual.js";
7
+ export {};
@@ -0,0 +1,27 @@
1
+ import { Schema } from "effect";
2
+ import { Bundle } from "foldkit-bundle";
3
+ export declare const LocaleModel: Schema.Struct<{
4
+ readonly locale: Schema.String;
5
+ }>;
6
+ export type LocaleModel = typeof LocaleModel.Type;
7
+ export declare const LocaleMessage: import("foldkit/message").MessageUnion<{
8
+ readonly SetLocale: {
9
+ locale: Schema.String;
10
+ };
11
+ }>;
12
+ export type LocaleMessage = typeof LocaleMessage.Type;
13
+ /**
14
+ * Locale as a bundle: the current locale string in the Model. Starts from
15
+ * `navigator.language` where available, falling back to the configured
16
+ * default; changes arrive as Messages. No subscriptions: language changes
17
+ * take effect on reload.
18
+ */
19
+ export declare const Locale: Bundle.Bundle<"Locale", {
20
+ readonly default: string;
21
+ }, {
22
+ readonly locale: string;
23
+ }, {
24
+ readonly _tag: "SetLocale";
25
+ readonly locale: string;
26
+ }, never, never, never, void, {}, {}>;
27
+ //# sourceMappingURL=locale.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"locale.d.ts","names":[],"sources":["../../src/state/locale.ts"],"mappings":";;qBAIa,aAAW,OAAA;;;YACZ,qBAAqB,YAAY;qBAEhC,yCAAa;;IAAqC,QAAM,OAAA;;;YACzD,uBAAuB,cAAc;;;;;;;qBAQpC,QAAM,OAAA"}
@@ -0,0 +1,25 @@
1
+ import { Schema } from "effect";
2
+ import { defineMessageUnion } from "foldkit/message";
3
+ import { Bundle } from "foldkit-bundle";
4
+ // src/state/locale.ts
5
+ const LocaleModel = Schema.Struct({ locale: Schema.String });
6
+ const LocaleMessage = defineMessageUnion({ SetLocale: { locale: Schema.String } });
7
+ /**
8
+ * Locale as a bundle: the current locale string in the Model. Starts from
9
+ * `navigator.language` where available, falling back to the configured
10
+ * default; changes arrive as Messages. No subscriptions: language changes
11
+ * take effect on reload.
12
+ */
13
+ const Locale = Bundle.make("Locale", {
14
+ Model: LocaleModel,
15
+ Message: LocaleMessage,
16
+ args: Schema.Struct({ default: Schema.String }),
17
+ init: (args) => ({ model: { locale: typeof navigator !== "undefined" && typeof navigator.language === "string" ? navigator.language : args.default } }),
18
+ update: (model, message) => LocaleMessage.match(message, { SetLocale: ({ locale }) => locale === model.locale ? { model } : { model: {
19
+ ...model,
20
+ locale
21
+ } } })
22
+ });
23
+ export { Locale, LocaleMessage, LocaleModel };
24
+
25
+ //# sourceMappingURL=locale.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"locale.js","names":[],"sources":["../../src/state/locale.ts"],"sourcesContent":["import { Schema } from 'effect'\nimport { defineMessageUnion } from 'foldkit/message'\nimport { Bundle } from 'foldkit-bundle'\n\nexport const LocaleModel = Schema.Struct({ locale: Schema.String })\nexport type LocaleModel = typeof LocaleModel.Type\n\nexport const LocaleMessage = defineMessageUnion({ SetLocale: { locale: Schema.String } })\nexport type LocaleMessage = typeof LocaleMessage.Type\n\n/**\n * Locale as a bundle: the current locale string in the Model. Starts from\n * `navigator.language` where available, falling back to the configured\n * default; changes arrive as Messages. No subscriptions: language changes\n * take effect on reload.\n */\nexport const Locale = Bundle.make('Locale', {\n Model: LocaleModel,\n Message: LocaleMessage,\n args: Schema.Struct({ default: Schema.String }),\n init: args => ({\n model: {\n locale:\n typeof navigator !== 'undefined' && typeof navigator.language === 'string'\n ? navigator.language\n : args.default,\n },\n }),\n update: (model, message) =>\n LocaleMessage.match(message, {\n SetLocale: ({ locale }) =>\n locale === model.locale ? { model } : { model: { ...model, locale } },\n }),\n})\n"],"mappings":";;;;AAIA,MAAa,cAAc,OAAO,OAAO,EAAE,QAAQ,OAAO,OAAO,CAAC;AAGlE,MAAa,gBAAgB,mBAAmB,EAAE,WAAW,EAAE,QAAQ,OAAO,OAAO,EAAE,CAAC;;;;;;;AASxF,MAAa,SAAS,OAAO,KAAK,UAAU;CAC1C,OAAO;CACP,SAAS;CACT,MAAM,OAAO,OAAO,EAAE,SAAS,OAAO,OAAO,CAAC;CAC9C,OAAM,UAAS,EACb,OAAO,EACL,QACE,OAAO,cAAc,eAAe,OAAO,UAAU,aAAa,WAC9D,UAAU,WACV,KAAK,QACb,EACF;CACA,SAAS,OAAO,YACd,cAAc,MAAM,SAAS,EAC3B,YAAY,EAAE,aACZ,WAAW,MAAM,SAAS,EAAE,MAAM,IAAI,EAAE,OAAO;EAAE,GAAG;EAAO;CAAO,EAAE,EACxE,CAAC;AACL,CAAC"}
@@ -0,0 +1,53 @@
1
+ import { Schema } from "effect";
2
+ import { Bundle } from "foldkit-bundle";
3
+ export declare const PaginationModel: Schema.Struct<{
4
+ readonly page: Schema.Number;
5
+ readonly perPage: Schema.Number;
6
+ readonly total: Schema.NullOr<Schema.Number>;
7
+ }>;
8
+ export type PaginationModel = typeof PaginationModel.Type;
9
+ export declare const PaginationMessage: import("foldkit/message").MessageUnion<{
10
+ readonly GoToPage: {
11
+ page: Schema.Number;
12
+ };
13
+ readonly NextPage: {};
14
+ readonly PrevPage: {};
15
+ readonly SetPerPage: {
16
+ perPage: Schema.Number;
17
+ };
18
+ readonly SetTotal: {
19
+ total: Schema.NullOr<Schema.Number>;
20
+ };
21
+ }>;
22
+ export type PaginationMessage = typeof PaginationMessage.Type;
23
+ /** The number of pages, or null while the total is unknown. */
24
+ export declare const pageCount: (model: PaginationModel) => number | null;
25
+ /** The offset of the first item on the page, for a slice or a query. */
26
+ export declare const offset: (model: PaginationModel) => number;
27
+ /**
28
+ * Pagination as a bundle: the page, page size, and total live in the Model,
29
+ * so page changes replay and every transition clamps into range. Pure logic,
30
+ * no streams: data loading stays the application's job.
31
+ */
32
+ export declare const Pagination: Bundle.Bundle<"Pagination", {
33
+ readonly perPage: number;
34
+ readonly total?: number | null | undefined;
35
+ }, {
36
+ readonly page: number;
37
+ readonly perPage: number;
38
+ readonly total: number | null;
39
+ }, {
40
+ readonly _tag: "GoToPage";
41
+ readonly page: number;
42
+ } | {
43
+ readonly _tag: "NextPage";
44
+ } | {
45
+ readonly _tag: "PrevPage";
46
+ } | {
47
+ readonly _tag: "SetPerPage";
48
+ readonly perPage: number;
49
+ } | {
50
+ readonly _tag: "SetTotal";
51
+ readonly total: number | null;
52
+ }, never, never, never, void, {}, {}>;
53
+ //# sourceMappingURL=pagination.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pagination.d.ts","names":[],"sources":["../../src/state/pagination.ts"],"mappings":";;qBAKa,iBAAe,OAAA;;;;;YAKhB,yBAAyB,gBAAgB;qBAExC,6CAAiB;;IAChB,MAAI,OAAA;;;;;IAGF,SAAO,OAAA;;;IACT,OAAK,OAAA,OAAA,OAAA;;;YAEP,2BAA2B,kBAAkB;;qBAU5C,YAAS,OAAW;;qBAIpB,SAAM,OAAW;;;;;;qBAOjB,YAAU,OAAA"}
@@ -0,0 +1,72 @@
1
+ import { Schema } from "effect";
2
+ import { defineMessageUnion } from "foldkit/message";
3
+ import { Bundle } from "foldkit-bundle";
4
+ import { unlessSame } from "../internal.js";
5
+ // src/state/pagination.ts
6
+ const PaginationModel = Schema.Struct({
7
+ page: Schema.Number,
8
+ perPage: Schema.Number,
9
+ total: Schema.NullOr(Schema.Number)
10
+ });
11
+ const PaginationMessage = defineMessageUnion({
12
+ GoToPage: { page: Schema.Number },
13
+ NextPage: {},
14
+ PrevPage: {},
15
+ SetPerPage: { perPage: Schema.Number },
16
+ SetTotal: { total: Schema.NullOr(Schema.Number) }
17
+ });
18
+ const clampPage = (page, perPage, total) => {
19
+ if (!Number.isInteger(page)) return 1;
20
+ if (page < 1) return 1;
21
+ if (total === null) return page;
22
+ return Math.min(page, Math.max(1, Math.ceil(total / perPage)));
23
+ };
24
+ /** The number of pages, or null while the total is unknown. */
25
+ const pageCount = (model) => model.total === null ? null : Math.max(1, Math.ceil(model.total / model.perPage));
26
+ /** The offset of the first item on the page, for a slice or a query. */
27
+ const offset = (model) => (model.page - 1) * model.perPage;
28
+ /**
29
+ * Pagination as a bundle: the page, page size, and total live in the Model,
30
+ * so page changes replay and every transition clamps into range. Pure logic,
31
+ * no streams: data loading stays the application's job.
32
+ */
33
+ const Pagination = Bundle.make("Pagination", {
34
+ Model: PaginationModel,
35
+ Message: PaginationMessage,
36
+ args: Schema.Struct({
37
+ perPage: Schema.Number.pipe(Schema.check(Schema.isGreaterThan(0)), Schema.check(Schema.isFinite())),
38
+ total: Schema.optional(Schema.NullOr(Schema.Number.pipe(Schema.check(Schema.isFinite()))))
39
+ }),
40
+ init: (args) => ({ model: {
41
+ page: 1,
42
+ perPage: args.perPage,
43
+ total: args.total ?? null
44
+ } }),
45
+ update: (model, message) => PaginationMessage.match(message, {
46
+ GoToPage: ({ page }) => ({ model: unlessSame(model, {
47
+ ...model,
48
+ page: clampPage(page, model.perPage, model.total)
49
+ }) }),
50
+ NextPage: () => ({ model: unlessSame(model, {
51
+ ...model,
52
+ page: clampPage(model.page + 1, model.perPage, model.total)
53
+ }) }),
54
+ PrevPage: () => ({ model: unlessSame(model, {
55
+ ...model,
56
+ page: clampPage(model.page - 1, model.perPage, model.total)
57
+ }) }),
58
+ SetPerPage: ({ perPage }) => perPage > 0 ? { model: unlessSame(model, {
59
+ ...model,
60
+ perPage,
61
+ page: clampPage(model.page, perPage, model.total)
62
+ }) } : { model },
63
+ SetTotal: ({ total }) => total === null || total >= 0 ? { model: unlessSame(model, {
64
+ ...model,
65
+ total,
66
+ page: clampPage(model.page, model.perPage, total)
67
+ }) } : { model }
68
+ })
69
+ });
70
+ export { Pagination, PaginationMessage, PaginationModel, offset, pageCount };
71
+
72
+ //# sourceMappingURL=pagination.js.map