@usels/core 0.0.1-beta.3

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 (341) hide show
  1. package/README.md +21 -0
  2. package/dist/browser/useEventListener/index.d.mts +56 -0
  3. package/dist/browser/useEventListener/index.d.ts +56 -0
  4. package/dist/browser/useEventListener/index.js +112 -0
  5. package/dist/browser/useEventListener/index.js.map +1 -0
  6. package/dist/browser/useEventListener/index.mjs +88 -0
  7. package/dist/browser/useEventListener/index.mjs.map +1 -0
  8. package/dist/browser/useMediaQuery/demo.d.mts +5 -0
  9. package/dist/browser/useMediaQuery/demo.d.ts +5 -0
  10. package/dist/browser/useMediaQuery/demo.js +82 -0
  11. package/dist/browser/useMediaQuery/demo.js.map +1 -0
  12. package/dist/browser/useMediaQuery/demo.mjs +62 -0
  13. package/dist/browser/useMediaQuery/demo.mjs.map +1 -0
  14. package/dist/browser/useMediaQuery/index.d.mts +11 -0
  15. package/dist/browser/useMediaQuery/index.d.ts +11 -0
  16. package/dist/browser/useMediaQuery/index.js +89 -0
  17. package/dist/browser/useMediaQuery/index.js.map +1 -0
  18. package/dist/browser/useMediaQuery/index.mjs +64 -0
  19. package/dist/browser/useMediaQuery/index.mjs.map +1 -0
  20. package/dist/components/Auto/index.d.mts +33 -0
  21. package/dist/components/Auto/index.d.ts +33 -0
  22. package/dist/components/Auto/index.js +66 -0
  23. package/dist/components/Auto/index.js.map +1 -0
  24. package/dist/components/Auto/index.mjs +34 -0
  25. package/dist/components/Auto/index.mjs.map +1 -0
  26. package/dist/elements/useDocumentVisibility/demo.d.mts +5 -0
  27. package/dist/elements/useDocumentVisibility/demo.d.ts +5 -0
  28. package/dist/elements/useDocumentVisibility/demo.js +130 -0
  29. package/dist/elements/useDocumentVisibility/demo.js.map +1 -0
  30. package/dist/elements/useDocumentVisibility/demo.mjs +114 -0
  31. package/dist/elements/useDocumentVisibility/demo.mjs.map +1 -0
  32. package/dist/elements/useDocumentVisibility/index.d.mts +5 -0
  33. package/dist/elements/useDocumentVisibility/index.d.ts +5 -0
  34. package/dist/elements/useDocumentVisibility/index.js +45 -0
  35. package/dist/elements/useDocumentVisibility/index.js.map +1 -0
  36. package/dist/elements/useDocumentVisibility/index.mjs +21 -0
  37. package/dist/elements/useDocumentVisibility/index.mjs.map +1 -0
  38. package/dist/elements/useElementBounding/demo.d.mts +5 -0
  39. package/dist/elements/useElementBounding/demo.d.ts +5 -0
  40. package/dist/elements/useElementBounding/demo.js +86 -0
  41. package/dist/elements/useElementBounding/demo.js.map +1 -0
  42. package/dist/elements/useElementBounding/demo.mjs +66 -0
  43. package/dist/elements/useElementBounding/demo.mjs.map +1 -0
  44. package/dist/elements/useElementBounding/index.d.mts +46 -0
  45. package/dist/elements/useElementBounding/index.d.ts +46 -0
  46. package/dist/elements/useElementBounding/index.js +122 -0
  47. package/dist/elements/useElementBounding/index.js.map +1 -0
  48. package/dist/elements/useElementBounding/index.mjs +98 -0
  49. package/dist/elements/useElementBounding/index.mjs.map +1 -0
  50. package/dist/elements/useElementSize/demo.d.mts +5 -0
  51. package/dist/elements/useElementSize/demo.d.ts +5 -0
  52. package/dist/elements/useElementSize/demo.js +82 -0
  53. package/dist/elements/useElementSize/demo.js.map +1 -0
  54. package/dist/elements/useElementSize/demo.mjs +62 -0
  55. package/dist/elements/useElementSize/demo.mjs.map +1 -0
  56. package/dist/elements/useElementSize/index.d.mts +34 -0
  57. package/dist/elements/useElementSize/index.d.ts +34 -0
  58. package/dist/elements/useElementSize/index.js +85 -0
  59. package/dist/elements/useElementSize/index.js.map +1 -0
  60. package/dist/elements/useElementSize/index.mjs +61 -0
  61. package/dist/elements/useElementSize/index.mjs.map +1 -0
  62. package/dist/elements/useElementVisibility/demo.d.mts +5 -0
  63. package/dist/elements/useElementVisibility/demo.d.ts +5 -0
  64. package/dist/elements/useElementVisibility/demo.js +110 -0
  65. package/dist/elements/useElementVisibility/demo.js.map +1 -0
  66. package/dist/elements/useElementVisibility/demo.mjs +90 -0
  67. package/dist/elements/useElementVisibility/demo.mjs.map +1 -0
  68. package/dist/elements/useElementVisibility/index.d.mts +43 -0
  69. package/dist/elements/useElementVisibility/index.d.ts +43 -0
  70. package/dist/elements/useElementVisibility/index.js +58 -0
  71. package/dist/elements/useElementVisibility/index.js.map +1 -0
  72. package/dist/elements/useElementVisibility/index.mjs +34 -0
  73. package/dist/elements/useElementVisibility/index.mjs.map +1 -0
  74. package/dist/elements/useIntersectionObserver/demo.d.mts +5 -0
  75. package/dist/elements/useIntersectionObserver/demo.d.ts +5 -0
  76. package/dist/elements/useIntersectionObserver/demo.js +173 -0
  77. package/dist/elements/useIntersectionObserver/demo.js.map +1 -0
  78. package/dist/elements/useIntersectionObserver/demo.mjs +153 -0
  79. package/dist/elements/useIntersectionObserver/demo.mjs.map +1 -0
  80. package/dist/elements/useIntersectionObserver/index.d.mts +47 -0
  81. package/dist/elements/useIntersectionObserver/index.d.ts +47 -0
  82. package/dist/elements/useIntersectionObserver/index.js +111 -0
  83. package/dist/elements/useIntersectionObserver/index.js.map +1 -0
  84. package/dist/elements/useIntersectionObserver/index.mjs +87 -0
  85. package/dist/elements/useIntersectionObserver/index.mjs.map +1 -0
  86. package/dist/elements/useMouseInElement/demo.d.mts +5 -0
  87. package/dist/elements/useMouseInElement/demo.d.ts +5 -0
  88. package/dist/elements/useMouseInElement/demo.js +103 -0
  89. package/dist/elements/useMouseInElement/demo.js.map +1 -0
  90. package/dist/elements/useMouseInElement/demo.mjs +83 -0
  91. package/dist/elements/useMouseInElement/demo.mjs.map +1 -0
  92. package/dist/elements/useMouseInElement/index.d.mts +56 -0
  93. package/dist/elements/useMouseInElement/index.d.ts +56 -0
  94. package/dist/elements/useMouseInElement/index.js +148 -0
  95. package/dist/elements/useMouseInElement/index.js.map +1 -0
  96. package/dist/elements/useMouseInElement/index.mjs +124 -0
  97. package/dist/elements/useMouseInElement/index.mjs.map +1 -0
  98. package/dist/elements/useMutationObserver/demo.d.mts +5 -0
  99. package/dist/elements/useMutationObserver/demo.d.ts +5 -0
  100. package/dist/elements/useMutationObserver/demo.js +240 -0
  101. package/dist/elements/useMutationObserver/demo.js.map +1 -0
  102. package/dist/elements/useMutationObserver/demo.mjs +220 -0
  103. package/dist/elements/useMutationObserver/demo.mjs.map +1 -0
  104. package/dist/elements/useMutationObserver/index.d.mts +15 -0
  105. package/dist/elements/useMutationObserver/index.d.ts +15 -0
  106. package/dist/elements/useMutationObserver/index.js +69 -0
  107. package/dist/elements/useMutationObserver/index.js.map +1 -0
  108. package/dist/elements/useMutationObserver/index.mjs +45 -0
  109. package/dist/elements/useMutationObserver/index.mjs.map +1 -0
  110. package/dist/elements/useParentElement/demo.d.mts +5 -0
  111. package/dist/elements/useParentElement/demo.d.ts +5 -0
  112. package/dist/elements/useParentElement/demo.js +132 -0
  113. package/dist/elements/useParentElement/demo.js.map +1 -0
  114. package/dist/elements/useParentElement/demo.mjs +112 -0
  115. package/dist/elements/useParentElement/demo.mjs.map +1 -0
  116. package/dist/elements/useParentElement/index.d.mts +7 -0
  117. package/dist/elements/useParentElement/index.d.ts +7 -0
  118. package/dist/elements/useParentElement/index.js +47 -0
  119. package/dist/elements/useParentElement/index.js.map +1 -0
  120. package/dist/elements/useParentElement/index.mjs +23 -0
  121. package/dist/elements/useParentElement/index.mjs.map +1 -0
  122. package/dist/elements/useRef$/index.js +89 -0
  123. package/dist/elements/useRef$/index.js.map +1 -0
  124. package/dist/elements/useRef$/index.mjs +62 -0
  125. package/dist/elements/useRef$/index.mjs.map +1 -0
  126. package/dist/elements/useRef_/index.d.mts +60 -0
  127. package/dist/elements/useRef_/index.d.ts +60 -0
  128. package/dist/elements/useResizeObserver/demo.d.mts +5 -0
  129. package/dist/elements/useResizeObserver/demo.d.ts +5 -0
  130. package/dist/elements/useResizeObserver/demo.js +90 -0
  131. package/dist/elements/useResizeObserver/demo.js.map +1 -0
  132. package/dist/elements/useResizeObserver/demo.mjs +70 -0
  133. package/dist/elements/useResizeObserver/demo.mjs.map +1 -0
  134. package/dist/elements/useResizeObserver/index.d.mts +36 -0
  135. package/dist/elements/useResizeObserver/index.d.ts +36 -0
  136. package/dist/elements/useResizeObserver/index.js +74 -0
  137. package/dist/elements/useResizeObserver/index.js.map +1 -0
  138. package/dist/elements/useResizeObserver/index.mjs +49 -0
  139. package/dist/elements/useResizeObserver/index.mjs.map +1 -0
  140. package/dist/elements/useWindowFocus/demo.d.mts +5 -0
  141. package/dist/elements/useWindowFocus/demo.d.ts +5 -0
  142. package/dist/elements/useWindowFocus/demo.js +100 -0
  143. package/dist/elements/useWindowFocus/demo.js.map +1 -0
  144. package/dist/elements/useWindowFocus/demo.mjs +80 -0
  145. package/dist/elements/useWindowFocus/demo.mjs.map +1 -0
  146. package/dist/elements/useWindowFocus/index.d.mts +5 -0
  147. package/dist/elements/useWindowFocus/index.d.ts +5 -0
  148. package/dist/elements/useWindowFocus/index.js +42 -0
  149. package/dist/elements/useWindowFocus/index.js.map +1 -0
  150. package/dist/elements/useWindowFocus/index.mjs +18 -0
  151. package/dist/elements/useWindowFocus/index.mjs.map +1 -0
  152. package/dist/elements/useWindowSize/demo.d.mts +5 -0
  153. package/dist/elements/useWindowSize/demo.d.ts +5 -0
  154. package/dist/elements/useWindowSize/demo.js +78 -0
  155. package/dist/elements/useWindowSize/demo.js.map +1 -0
  156. package/dist/elements/useWindowSize/demo.mjs +58 -0
  157. package/dist/elements/useWindowSize/demo.mjs.map +1 -0
  158. package/dist/elements/useWindowSize/index.d.mts +17 -0
  159. package/dist/elements/useWindowSize/index.d.ts +17 -0
  160. package/dist/elements/useWindowSize/index.js +96 -0
  161. package/dist/elements/useWindowSize/index.js.map +1 -0
  162. package/dist/elements/useWindowSize/index.mjs +76 -0
  163. package/dist/elements/useWindowSize/index.mjs.map +1 -0
  164. package/dist/function/get/index.d.mts +45 -0
  165. package/dist/function/get/index.d.ts +45 -0
  166. package/dist/function/get/index.js +39 -0
  167. package/dist/function/get/index.js.map +1 -0
  168. package/dist/function/get/index.mjs +15 -0
  169. package/dist/function/get/index.mjs.map +1 -0
  170. package/dist/function/peek/index.d.mts +46 -0
  171. package/dist/function/peek/index.d.ts +46 -0
  172. package/dist/function/peek/index.js +39 -0
  173. package/dist/function/peek/index.js.map +1 -0
  174. package/dist/function/peek/index.mjs +15 -0
  175. package/dist/function/peek/index.mjs.map +1 -0
  176. package/dist/function/useMayObservableOptions/index.d.mts +59 -0
  177. package/dist/function/useMayObservableOptions/index.d.ts +59 -0
  178. package/dist/function/useMayObservableOptions/index.js +109 -0
  179. package/dist/function/useMayObservableOptions/index.js.map +1 -0
  180. package/dist/function/useMayObservableOptions/index.mjs +88 -0
  181. package/dist/function/useMayObservableOptions/index.mjs.map +1 -0
  182. package/dist/function/useSupported/index.d.mts +6 -0
  183. package/dist/function/useSupported/index.d.ts +6 -0
  184. package/dist/function/useSupported/index.js +37 -0
  185. package/dist/function/useSupported/index.js.map +1 -0
  186. package/dist/function/useSupported/index.mjs +13 -0
  187. package/dist/function/useSupported/index.mjs.map +1 -0
  188. package/dist/function/useWhenMounted/index.d.mts +6 -0
  189. package/dist/function/useWhenMounted/index.d.ts +6 -0
  190. package/dist/function/useWhenMounted/index.js +37 -0
  191. package/dist/function/useWhenMounted/index.js.map +1 -0
  192. package/dist/function/useWhenMounted/index.mjs +13 -0
  193. package/dist/function/useWhenMounted/index.mjs.map +1 -0
  194. package/dist/index.d.mts +24 -0
  195. package/dist/index.d.ts +24 -0
  196. package/dist/index.js +63 -0
  197. package/dist/index.js.map +1 -0
  198. package/dist/index.mjs +22 -0
  199. package/dist/index.mjs.map +1 -0
  200. package/dist/sensors/useScroll/demo.d.mts +5 -0
  201. package/dist/sensors/useScroll/demo.d.ts +5 -0
  202. package/dist/sensors/useScroll/demo.js +121 -0
  203. package/dist/sensors/useScroll/demo.js.map +1 -0
  204. package/dist/sensors/useScroll/demo.mjs +101 -0
  205. package/dist/sensors/useScroll/demo.mjs.map +1 -0
  206. package/dist/sensors/useScroll/index.d.mts +42 -0
  207. package/dist/sensors/useScroll/index.d.ts +42 -0
  208. package/dist/sensors/useScroll/index.js +149 -0
  209. package/dist/sensors/useScroll/index.js.map +1 -0
  210. package/dist/sensors/useScroll/index.mjs +125 -0
  211. package/dist/sensors/useScroll/index.mjs.map +1 -0
  212. package/dist/sensors/useWindowScroll/demo.d.mts +5 -0
  213. package/dist/sensors/useWindowScroll/demo.d.ts +5 -0
  214. package/dist/sensors/useWindowScroll/demo.js +84 -0
  215. package/dist/sensors/useWindowScroll/demo.js.map +1 -0
  216. package/dist/sensors/useWindowScroll/demo.mjs +64 -0
  217. package/dist/sensors/useWindowScroll/demo.mjs.map +1 -0
  218. package/dist/sensors/useWindowScroll/index.d.mts +9 -0
  219. package/dist/sensors/useWindowScroll/index.d.ts +9 -0
  220. package/dist/sensors/useWindowScroll/index.js +36 -0
  221. package/dist/sensors/useWindowScroll/index.js.map +1 -0
  222. package/dist/sensors/useWindowScroll/index.mjs +12 -0
  223. package/dist/sensors/useWindowScroll/index.mjs.map +1 -0
  224. package/dist/shared/configurable.d.mts +21 -0
  225. package/dist/shared/configurable.d.ts +21 -0
  226. package/dist/shared/configurable.js +39 -0
  227. package/dist/shared/configurable.js.map +1 -0
  228. package/dist/shared/configurable.mjs +12 -0
  229. package/dist/shared/configurable.mjs.map +1 -0
  230. package/dist/shared/index.d.mts +4 -0
  231. package/dist/shared/index.d.ts +4 -0
  232. package/dist/shared/index.js +31 -0
  233. package/dist/shared/index.js.map +1 -0
  234. package/dist/shared/index.mjs +7 -0
  235. package/dist/shared/index.mjs.map +1 -0
  236. package/dist/shared/normalizeTargets/index.d.mts +21 -0
  237. package/dist/shared/normalizeTargets/index.d.ts +21 -0
  238. package/dist/shared/normalizeTargets/index.js +36 -0
  239. package/dist/shared/normalizeTargets/index.js.map +1 -0
  240. package/dist/shared/normalizeTargets/index.mjs +12 -0
  241. package/dist/shared/normalizeTargets/index.mjs.map +1 -0
  242. package/dist/shared/utils.d.mts +15 -0
  243. package/dist/shared/utils.d.ts +15 -0
  244. package/dist/shared/utils.js +87 -0
  245. package/dist/shared/utils.js.map +1 -0
  246. package/dist/shared/utils.mjs +52 -0
  247. package/dist/shared/utils.mjs.map +1 -0
  248. package/dist/types.d.mts +52 -0
  249. package/dist/types.d.ts +52 -0
  250. package/dist/types.js +17 -0
  251. package/dist/types.js.map +1 -0
  252. package/dist/types.mjs +1 -0
  253. package/dist/types.mjs.map +1 -0
  254. package/package.json +54 -0
  255. package/src/browser/useEventListener/index.md +109 -0
  256. package/src/browser/useEventListener/index.spec.ts +611 -0
  257. package/src/browser/useEventListener/index.ts +242 -0
  258. package/src/browser/useMediaQuery/demo.tsx +58 -0
  259. package/src/browser/useMediaQuery/index.md +40 -0
  260. package/src/browser/useMediaQuery/index.spec.ts +267 -0
  261. package/src/browser/useMediaQuery/index.ts +96 -0
  262. package/src/components/Auto/index.tsx +65 -0
  263. package/src/elements/useDocumentVisibility/demo.tsx +111 -0
  264. package/src/elements/useDocumentVisibility/index.md +51 -0
  265. package/src/elements/useDocumentVisibility/index.spec.ts +114 -0
  266. package/src/elements/useDocumentVisibility/index.ts +26 -0
  267. package/src/elements/useElementBounding/demo.tsx +63 -0
  268. package/src/elements/useElementBounding/index.md +59 -0
  269. package/src/elements/useElementBounding/index.ts +159 -0
  270. package/src/elements/useElementSize/demo.tsx +48 -0
  271. package/src/elements/useElementSize/index.md +60 -0
  272. package/src/elements/useElementSize/index.spec.ts +295 -0
  273. package/src/elements/useElementSize/index.ts +100 -0
  274. package/src/elements/useElementVisibility/deep-observable-pattern.spec.ts +453 -0
  275. package/src/elements/useElementVisibility/demo.tsx +97 -0
  276. package/src/elements/useElementVisibility/index.md +98 -0
  277. package/src/elements/useElementVisibility/index.spec.ts +227 -0
  278. package/src/elements/useElementVisibility/index.ts +78 -0
  279. package/src/elements/useIntersectionObserver/demo.tsx +180 -0
  280. package/src/elements/useIntersectionObserver/index.md +99 -0
  281. package/src/elements/useIntersectionObserver/index.spec.ts +482 -0
  282. package/src/elements/useIntersectionObserver/index.ts +149 -0
  283. package/src/elements/useMouseInElement/demo.tsx +79 -0
  284. package/src/elements/useMouseInElement/index.md +71 -0
  285. package/src/elements/useMouseInElement/index.spec.ts +398 -0
  286. package/src/elements/useMouseInElement/index.ts +209 -0
  287. package/src/elements/useMutationObserver/demo.tsx +270 -0
  288. package/src/elements/useMutationObserver/index.md +99 -0
  289. package/src/elements/useMutationObserver/index.spec.ts +421 -0
  290. package/src/elements/useMutationObserver/index.ts +66 -0
  291. package/src/elements/useParentElement/demo.tsx +120 -0
  292. package/src/elements/useParentElement/index.md +67 -0
  293. package/src/elements/useParentElement/index.spec.ts +208 -0
  294. package/src/elements/useParentElement/index.ts +35 -0
  295. package/src/elements/useRef$/index.md +62 -0
  296. package/src/elements/useRef$/index.spec.ts +205 -0
  297. package/src/elements/useRef$/index.ts +137 -0
  298. package/src/elements/useRef$/useImperativeHandle.spec.ts +339 -0
  299. package/src/elements/useResizeObserver/demo.tsx +56 -0
  300. package/src/elements/useResizeObserver/index.md +51 -0
  301. package/src/elements/useResizeObserver/index.spec.ts +312 -0
  302. package/src/elements/useResizeObserver/index.ts +106 -0
  303. package/src/elements/useWindowFocus/demo.tsx +71 -0
  304. package/src/elements/useWindowFocus/index.md +35 -0
  305. package/src/elements/useWindowFocus/index.spec.ts +103 -0
  306. package/src/elements/useWindowFocus/index.ts +21 -0
  307. package/src/elements/useWindowSize/demo.tsx +46 -0
  308. package/src/elements/useWindowSize/index.md +50 -0
  309. package/src/elements/useWindowSize/index.spec.ts +310 -0
  310. package/src/elements/useWindowSize/index.ts +107 -0
  311. package/src/function/get/index.md +25 -0
  312. package/src/function/get/index.spec.ts +87 -0
  313. package/src/function/get/index.ts +70 -0
  314. package/src/function/peek/index.spec.ts +97 -0
  315. package/src/function/peek/index.ts +69 -0
  316. package/src/function/useMayObservableOptions/index.spec.ts +521 -0
  317. package/src/function/useMayObservableOptions/index.ts +173 -0
  318. package/src/function/useSupported/index.md +38 -0
  319. package/src/function/useSupported/index.spec.ts +116 -0
  320. package/src/function/useSupported/index.ts +14 -0
  321. package/src/function/useWhenMounted/index.md +25 -0
  322. package/src/function/useWhenMounted/index.spec.ts +120 -0
  323. package/src/function/useWhenMounted/index.ts +16 -0
  324. package/src/index.ts +25 -0
  325. package/src/sensors/useScroll/demo.tsx +98 -0
  326. package/src/sensors/useScroll/index.md +112 -0
  327. package/src/sensors/useScroll/index.spec.ts +678 -0
  328. package/src/sensors/useScroll/index.ts +201 -0
  329. package/src/sensors/useWindowScroll/demo.tsx +69 -0
  330. package/src/sensors/useWindowScroll/index.md +88 -0
  331. package/src/sensors/useWindowScroll/index.spec.ts +69 -0
  332. package/src/sensors/useWindowScroll/index.ts +11 -0
  333. package/src/shared/configurable.ts +35 -0
  334. package/src/shared/index.ts +4 -0
  335. package/src/shared/normalizeTargets/index.spec.ts +76 -0
  336. package/src/shared/normalizeTargets/index.ts +27 -0
  337. package/src/shared/utils.ts +67 -0
  338. package/src/types.ts +56 -0
  339. package/tsconfig.json +9 -0
  340. package/tsup.config.ts +10 -0
  341. package/vitest.config.ts +22 -0
@@ -0,0 +1,270 @@
1
+ import { useRef$ } from "../useRef$";
2
+ import { useMutationObserver } from ".";
3
+ import { Computed, useObservable } from "@legendapp/state/react";
4
+ import { batch, beginBatch, endBatch } from "@legendapp/state";
5
+
6
+ const MAX_LOG = 6;
7
+
8
+ const btn: React.CSSProperties = {
9
+ height: "26px",
10
+ padding: "0 10px",
11
+ fontSize: "12px",
12
+ cursor: "pointer",
13
+ borderRadius: "4px",
14
+ border: "1px solid var(--sl-color-gray-4, #94a3b8)",
15
+ background: "transparent",
16
+ fontFamily: "monospace",
17
+ display: "inline-flex",
18
+ alignItems: "center",
19
+ margin: 0,
20
+ };
21
+
22
+ const rowLabel: React.CSSProperties = {
23
+ fontSize: "11px",
24
+ color: "var(--sl-color-gray-3, #94a3b8)",
25
+ alignSelf: "center",
26
+ userSelect: "none",
27
+ minWidth: "52px",
28
+ };
29
+
30
+ export default function UseMutationObserverDemo() {
31
+ const el$ = useRef$<HTMLDivElement>();
32
+ const log$ = useObservable<string[]>([]);
33
+ const active$ = useObservable(false);
34
+ const childCount$ = useObservable(0);
35
+ const stopped$ = useObservable(false);
36
+
37
+ const { stop, resume } = useMutationObserver(
38
+ el$,
39
+ (records) => {
40
+ const lines = records.map((r): string => {
41
+ if (r.type === "attributes") {
42
+ return `[attributes] ${r.attributeName} ← was: ${
43
+ r.oldValue ?? "—"
44
+ }`;
45
+ }
46
+ const a = r.addedNodes.length;
47
+ const rm = r.removedNodes.length;
48
+ return `[childList] ${[a && `+${a} added`, rm && `-${rm} removed`]
49
+ .filter(Boolean)
50
+ .join(", ")}`;
51
+ });
52
+ batch(() => {
53
+ log$.unshift(...lines);
54
+ if (MAX_LOG < log$.peek().length) {
55
+ log$.splice(-1, 1);
56
+ }
57
+ });
58
+ },
59
+ { attributes: true, attributeOldValue: true, childList: true },
60
+ );
61
+
62
+ const toggleAttr = () => {
63
+ batch(() => {
64
+ const el = el$.peek();
65
+ if (!el) return;
66
+
67
+ const next = !active$.peek();
68
+ active$.set(next);
69
+ if (next) el.setAttribute("data-active", "true");
70
+ else el.removeAttribute("data-active");
71
+ });
72
+ };
73
+
74
+ const addChild = () => {
75
+ const el = el$.peek();
76
+ if (!el) return;
77
+ beginBatch();
78
+ childCount$.set((n) => n + 1);
79
+ const span = document.createElement("span");
80
+ span.textContent = `child-${childCount$.peek()}`;
81
+ span.style.cssText =
82
+ "display:block;font-size:12px;font-family:monospace;" +
83
+ "color:var(--sl-color-gray-2,#475569);padding:1px 0";
84
+ el.appendChild(span);
85
+ endBatch();
86
+ };
87
+
88
+ const removeChild = () => {
89
+ const el = el$.peek();
90
+ if (!el) return;
91
+ const last = el.querySelector("span:last-of-type");
92
+ if (!last) return;
93
+ el.removeChild(last);
94
+ childCount$.set((n) => Math.max(0, n - 1));
95
+ };
96
+
97
+ return (
98
+ <div
99
+ style={{
100
+ display: "flex",
101
+ flexDirection: "column",
102
+ gap: "8px",
103
+ fontFamily: "monospace",
104
+ fontSize: "13px",
105
+ }}
106
+ >
107
+ {/* Status bar */}
108
+ <div
109
+ style={{
110
+ display: "flex",
111
+ gap: "16px",
112
+ alignItems: "center",
113
+ padding: "6px 12px",
114
+ background: "var(--sl-color-gray-6, #f1f5f9)",
115
+ borderRadius: "6px",
116
+ }}
117
+ >
118
+ <Computed>
119
+ {() => (
120
+ <span>
121
+ status:{" "}
122
+ <strong
123
+ style={{
124
+ color: stopped$.get()
125
+ ? "var(--sl-color-red, #ef4444)"
126
+ : "var(--sl-color-green, #22c55e)",
127
+ }}
128
+ >
129
+ {stopped$.get() ? "stopped" : "observing"}
130
+ </strong>
131
+ </span>
132
+ )}
133
+ </Computed>
134
+ <Computed>
135
+ {() => (
136
+ <span style={{ color: "var(--sl-color-gray-3, #94a3b8)" }}>
137
+ data-active: <strong>{active$.get() ? '"true"' : "—"}</strong>
138
+ </span>
139
+ )}
140
+ </Computed>
141
+ <Computed>
142
+ {() => (
143
+ <span style={{ color: "var(--sl-color-gray-3, #94a3b8)" }}>
144
+ children: <strong>{childCount$.get()}</strong>
145
+ </span>
146
+ )}
147
+ </Computed>
148
+ </div>
149
+
150
+ {/* DOM mutation actions */}
151
+ <div style={{ display: "flex", gap: "6px", alignItems: "center" }}>
152
+ <span style={rowLabel}>DOM</span>
153
+ <button onClick={toggleAttr} style={btn}>
154
+ toggle data-active
155
+ </button>
156
+ <button onClick={addChild} style={btn}>
157
+ add child
158
+ </button>
159
+ <button onClick={removeChild} style={btn}>
160
+ remove child
161
+ </button>
162
+ <button onClick={() => log$.set([])} style={btn}>
163
+ clear log
164
+ </button>
165
+ </div>
166
+
167
+ {/* Observer control */}
168
+ <div style={{ display: "flex", gap: "6px", alignItems: "center" }}>
169
+ <span style={rowLabel}>Observer</span>
170
+ <Computed>
171
+ {() =>
172
+ stopped$.get() ? (
173
+ <button
174
+ onClick={() => {
175
+ resume();
176
+ stopped$.set(false);
177
+ }}
178
+ style={{
179
+ ...btn,
180
+ borderColor: "var(--sl-color-green, #22c55e)",
181
+ color: "var(--sl-color-green, #22c55e)",
182
+ }}
183
+ >
184
+ resume observe()
185
+ </button>
186
+ ) : (
187
+ <button
188
+ onClick={() => {
189
+ stop();
190
+ stopped$.set(true);
191
+ }}
192
+ style={{
193
+ ...btn,
194
+ borderColor: "var(--sl-color-red, #ef4444)",
195
+ color: "var(--sl-color-red, #ef4444)",
196
+ }}
197
+ >
198
+ stop observe()
199
+ </button>
200
+ )
201
+ }
202
+ </Computed>
203
+ </div>
204
+
205
+ {/* Observed target element — children appended/removed by buttons above */}
206
+ <Computed>
207
+ {() => (
208
+ <div
209
+ ref={el$}
210
+ style={{
211
+ minHeight: "52px",
212
+ padding: "8px 12px",
213
+ borderRadius: "6px",
214
+ border: `1px dashed ${
215
+ active$.get()
216
+ ? "var(--sl-color-green, #22c55e)"
217
+ : "var(--sl-color-gray-4, #94a3b8)"
218
+ }`,
219
+ background: active$.get()
220
+ ? "var(--sl-color-green-low, #f0fdf4)"
221
+ : "transparent",
222
+ transition: "border-color 0.2s, background 0.2s",
223
+ }}
224
+ />
225
+ )}
226
+ </Computed>
227
+
228
+ {/* Mutation log */}
229
+ <div
230
+ style={{
231
+ minHeight: "80px",
232
+ maxHeight: "168px",
233
+ overflowY: "auto",
234
+ padding: "8px 12px",
235
+ background: "var(--sl-color-gray-6, #f1f5f9)",
236
+ borderRadius: "6px",
237
+ fontSize: "12px",
238
+ }}
239
+ >
240
+ <Computed>
241
+ {() => {
242
+ const entries = log$.get();
243
+ if (!entries.length) {
244
+ return (
245
+ <span style={{ opacity: 0.4 }}>
246
+ — no mutations recorded yet
247
+ </span>
248
+ );
249
+ }
250
+ return (
251
+ <>
252
+ {entries.map((line, i) => (
253
+ <div
254
+ key={i}
255
+ style={{
256
+ padding: "1px 0",
257
+ opacity: Math.max(0.2, 1 - i * 0.15),
258
+ }}
259
+ >
260
+ {line}
261
+ </div>
262
+ ))}
263
+ </>
264
+ );
265
+ }}
266
+ </Computed>
267
+ </div>
268
+ </div>
269
+ );
270
+ }
@@ -0,0 +1,99 @@
1
+ ---
2
+ title: useMutationObserver
3
+ category: elements
4
+ ---
5
+
6
+ Reactive wrapper around the [MutationObserver API](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver).
7
+ Observes one or more DOM nodes for mutations — attribute changes, child additions/removals, and text content changes.
8
+ Targets can be `Ref$`, `MaybeElement`, or a plain `Element`.
9
+
10
+ ## Demo
11
+
12
+ ## Usage
13
+
14
+ ```tsx twoslash
15
+ // @noErrors
16
+ import { useRef$, useMutationObserver } from '@usels/core'
17
+ function Component() {
18
+ const el$ = useRef$<HTMLDivElement>()
19
+
20
+ useMutationObserver(
21
+ el$,
22
+ (records) => {
23
+ records.forEach((r) => { /* handle r.type, r.target */ })
24
+ },
25
+ { attributes: true, childList: true },
26
+ )
27
+
28
+ return <div ref={el$} />
29
+ }
30
+ ```
31
+
32
+ ### Watching attributes only
33
+
34
+ ```tsx
35
+ useMutationObserver(el$, callback, { attributes: true })
36
+ ```
37
+
38
+ ### Filtering specific attributes
39
+
40
+ Only fire when `aria-expanded` or `data-active` change:
41
+
42
+ ```tsx
43
+ useMutationObserver(el$, callback, {
44
+ attributes: true,
45
+ attributeFilter: ['aria-expanded', 'data-active'],
46
+ })
47
+ ```
48
+
49
+ ### Recording the previous attribute value
50
+
51
+ ```tsx
52
+ useMutationObserver(
53
+ el$,
54
+ (records) => {
55
+ records.forEach((r) => {
56
+ const next = (r.target as Element).getAttribute(r.attributeName!)
57
+ console.log('old:', r.oldValue, '→ new:', next)
58
+ })
59
+ },
60
+ { attributes: true, attributeOldValue: true },
61
+ )
62
+ ```
63
+
64
+ ### Watching descendant nodes with `subtree`
65
+
66
+ ```tsx
67
+ useMutationObserver(el$, callback, { childList: true, subtree: true })
68
+ ```
69
+
70
+ ### Multiple targets
71
+
72
+ ```tsx
73
+ useMutationObserver([el$, anotherEl], callback, { attributes: true })
74
+ ```
75
+
76
+ ### Stop and resume
77
+
78
+ ```tsx
79
+ const { stop, resume } = useMutationObserver(el$, callback, { childList: true })
80
+
81
+ stop() // disconnects the observer
82
+ resume() // reconnects with the same target and options
83
+ ```
84
+
85
+ ### Flushing pending records
86
+
87
+ ```tsx
88
+ const { takeRecords } = useMutationObserver(el$, callback, { attributes: true })
89
+
90
+ const pending = takeRecords()
91
+ ```
92
+
93
+ ### Checking browser support
94
+
95
+ ```tsx
96
+ const { isSupported$ } = useMutationObserver(el$, callback, { attributes: true })
97
+
98
+ console.log(isSupported$.get()) // Observable<boolean>
99
+ ```