@studiometa/js-toolkit 4.0.0-alpha.1 → 4.0.0-alpha.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 (455) hide show
  1. package/README.md +10 -0
  2. package/dist/Base.d.ts +0 -2
  3. package/dist/Base.js +1 -2
  4. package/dist/Base.js.map +1 -1
  5. package/dist/attribute-namespaces.d.ts +0 -2
  6. package/dist/attribute-namespaces.js +1 -2
  7. package/dist/attributes.d.ts +0 -2
  8. package/dist/attributes.js +1 -2
  9. package/dist/children-watchers.d.ts +0 -2
  10. package/dist/children-watchers.js +1 -2
  11. package/dist/component-brand.d.ts +0 -2
  12. package/dist/component-brand.js +1 -2
  13. package/dist/component-declarations.d.ts +0 -2
  14. package/dist/component-declarations.js +1 -2
  15. package/dist/context-subscription.d.ts +0 -2
  16. package/dist/context-subscription.js +1 -2
  17. package/dist/context.d.ts +0 -2
  18. package/dist/context.js +1 -2
  19. package/dist/decorators.d.ts +0 -2
  20. package/dist/decorators.js +1 -2
  21. package/dist/diagnostic-contract.d.ts +0 -2
  22. package/dist/diagnostic-contract.js +1 -2
  23. package/dist/diagnostics.d.ts +0 -2
  24. package/dist/diagnostics.js +1 -2
  25. package/dist/document-order.d.ts +0 -2
  26. package/dist/document-order.js +1 -2
  27. package/dist/dom-mutations.d.ts +0 -2
  28. package/dist/dom-mutations.js +1 -2
  29. package/dist/events.d.ts +0 -2
  30. package/dist/events.js +1 -2
  31. package/dist/group.d.ts +0 -2
  32. package/dist/group.js +1 -2
  33. package/dist/instances.d.ts +0 -2
  34. package/dist/instances.js +1 -2
  35. package/dist/manifest.d.ts +0 -2
  36. package/dist/manifest.js +1 -2
  37. package/dist/mount-strategies.d.ts +0 -2
  38. package/dist/mount-strategies.js +1 -2
  39. package/dist/negotiated-events.d.ts +0 -2
  40. package/dist/negotiated-events.js +1 -2
  41. package/dist/protocol-symbols.d.ts +0 -2
  42. package/dist/protocol-symbols.js +1 -2
  43. package/dist/registry.d.ts +0 -2
  44. package/dist/registry.js +1 -2
  45. package/dist/responsive-options.d.ts +0 -2
  46. package/dist/responsive-options.js +1 -2
  47. package/dist/scheduler.d.ts +0 -2
  48. package/dist/scheduler.js +1 -2
  49. package/dist/scheduler.js.map +1 -1
  50. package/dist/services/breakpoint.d.ts +0 -2
  51. package/dist/services/breakpoint.js +1 -2
  52. package/dist/services/drag.d.ts +0 -2
  53. package/dist/services/drag.js +1 -2
  54. package/dist/services/in-view.d.ts +0 -2
  55. package/dist/services/in-view.js +1 -2
  56. package/dist/services/key.d.ts +0 -2
  57. package/dist/services/key.js +1 -2
  58. package/dist/services/media.d.ts +0 -2
  59. package/dist/services/media.js +1 -2
  60. package/dist/services/mixin.d.ts +0 -2
  61. package/dist/services/mixin.js +1 -2
  62. package/dist/services/mutation.d.ts +0 -2
  63. package/dist/services/mutation.js +1 -2
  64. package/dist/services/pointer.d.ts +0 -2
  65. package/dist/services/pointer.js +1 -2
  66. package/dist/services/raf.d.ts +0 -2
  67. package/dist/services/raf.js +1 -2
  68. package/dist/services/resize.d.ts +0 -2
  69. package/dist/services/resize.js +1 -2
  70. package/dist/services/scroll-progress-offset.d.ts +0 -2
  71. package/dist/services/scroll-progress-offset.js +1 -2
  72. package/dist/services/scroll-progress.d.ts +0 -2
  73. package/dist/services/scroll-progress.js +1 -2
  74. package/dist/services/scroll.d.ts +0 -2
  75. package/dist/services/scroll.js +1 -2
  76. package/dist/services/service.d.ts +0 -2
  77. package/dist/services/service.js +1 -2
  78. package/dist/services/toggle.d.ts +0 -2
  79. package/dist/services/toggle.js +1 -2
  80. package/dist/services/until.d.ts +0 -2
  81. package/dist/services/until.js +1 -2
  82. package/dist/shared-runtime.d.ts +0 -2
  83. package/dist/shared-runtime.js +1 -2
  84. package/dist/storage/createStorage.d.ts +0 -2
  85. package/dist/storage/createStorage.js +1 -2
  86. package/dist/storage/index.d.ts +0 -2
  87. package/dist/storage/index.js +1 -2
  88. package/dist/storage/providers.d.ts +0 -2
  89. package/dist/storage/providers.js +1 -2
  90. package/dist/storage/serializers.d.ts +0 -2
  91. package/dist/storage/serializers.js +1 -2
  92. package/dist/storage/sync.d.ts +0 -2
  93. package/dist/storage/sync.js +1 -2
  94. package/dist/storage/types.d.ts +0 -2
  95. package/dist/subpaths/BREAKPOINTS.js +1 -2
  96. package/dist/subpaths/Base.js +1 -2
  97. package/dist/subpaths/DIAGNOSTICS.js +1 -2
  98. package/dist/subpaths/DRAG_MODES.js +1 -2
  99. package/dist/subpaths/EVENTS.js +1 -2
  100. package/dist/subpaths/MOUNT_ATTRIBUTE.js +1 -2
  101. package/dist/subpaths/SWAP_MODES.js +1 -2
  102. package/dist/subpaths/children.js +1 -2
  103. package/dist/subpaths/component.js +1 -2
  104. package/dist/subpaths/createContext.js +1 -2
  105. package/dist/subpaths/createFallbackProvider.js +1 -2
  106. package/dist/subpaths/createGroup.js +1 -2
  107. package/dist/subpaths/createLocalStorage.js +1 -2
  108. package/dist/subpaths/createMemoryStorageProvider.js +1 -2
  109. package/dist/subpaths/createService.js +1 -2
  110. package/dist/subpaths/createServiceMixin.js +1 -2
  111. package/dist/subpaths/createSessionStorage.js +1 -2
  112. package/dist/subpaths/createStorage.js +1 -2
  113. package/dist/subpaths/createUrlSearchParamsInHashProvider.js +1 -2
  114. package/dist/subpaths/createUrlSearchParamsInHashStorage.js +1 -2
  115. package/dist/subpaths/createUrlSearchParamsProvider.js +1 -2
  116. package/dist/subpaths/createUrlSearchParamsStorage.js +1 -2
  117. package/dist/subpaths/defaultScheduler.js +1 -2
  118. package/dist/subpaths/defineManifest.js +1 -2
  119. package/dist/subpaths/domUpdate.js +1 -2
  120. package/dist/subpaths/emitExtendable.js +1 -2
  121. package/dist/subpaths/fromMetaGlob.js +1 -2
  122. package/dist/subpaths/fromWebpackContext.js +1 -2
  123. package/dist/subpaths/getBreakpoints.js +1 -2
  124. package/dist/subpaths/getInstance.js +1 -2
  125. package/dist/subpaths/getInstances.js +1 -2
  126. package/dist/subpaths/getMountedInstances.js +1 -2
  127. package/dist/subpaths/getUnmountedInstances.js +1 -2
  128. package/dist/subpaths/inject.js +1 -2
  129. package/dist/subpaths/injectContext.js +1 -2
  130. package/dist/subpaths/injectContextSync.js +1 -2
  131. package/dist/subpaths/jsonSerializer.js +1 -2
  132. package/dist/subpaths/localStorageProvider.js +1 -2
  133. package/dist/subpaths/memoryStorageProvider.js +1 -2
  134. package/dist/subpaths/namespaceQualifier.js +1 -2
  135. package/dist/subpaths/nextFrame.js +1 -2
  136. package/dist/subpaths/on.js +1 -2
  137. package/dist/subpaths/perTarget.js +1 -2
  138. package/dist/subpaths/provide.js +1 -2
  139. package/dist/subpaths/provideContext.js +1 -2
  140. package/dist/subpaths/provideRootContext.js +1 -2
  141. package/dist/subpaths/read.js +1 -2
  142. package/dist/subpaths/registerComponent.js +1 -2
  143. package/dist/subpaths/registerComponents.js +1 -2
  144. package/dist/subpaths/registerManifest.js +1 -2
  145. package/dist/subpaths/reportDiagnostic.js +1 -2
  146. package/dist/subpaths/sessionStorageProvider.js +1 -2
  147. package/dist/subpaths/setBreakpoints.js +1 -2
  148. package/dist/subpaths/signal.js +1 -2
  149. package/dist/subpaths/subscribeContext.js +1 -2
  150. package/dist/subpaths/swap.js +1 -2
  151. package/dist/subpaths/toggle.js +1 -2
  152. package/dist/subpaths/until.js +1 -2
  153. package/dist/subpaths/urlSearchParamsInHashProvider.js +1 -2
  154. package/dist/subpaths/urlSearchParamsProvider.js +1 -2
  155. package/dist/subpaths/useBreakpoint.js +1 -2
  156. package/dist/subpaths/useDrag.js +1 -2
  157. package/dist/subpaths/useInView.js +1 -2
  158. package/dist/subpaths/useKey.js +1 -2
  159. package/dist/subpaths/useMediaQuery.js +1 -2
  160. package/dist/subpaths/useMutation.js +1 -2
  161. package/dist/subpaths/usePointer.js +1 -2
  162. package/dist/subpaths/usePrefersReducedMotion.js +1 -2
  163. package/dist/subpaths/useRaf.js +1 -2
  164. package/dist/subpaths/useResize.js +1 -2
  165. package/dist/subpaths/useScroll.js +1 -2
  166. package/dist/subpaths/useScrollProgress.js +1 -2
  167. package/dist/subpaths/useWindowScroll.js +1 -2
  168. package/dist/subpaths/useWindowSize.js +1 -2
  169. package/dist/subpaths/utils/DEFAULT_DAMP_FACTOR.js +1 -2
  170. package/dist/subpaths/utils/INERTIA_FRAME.js +1 -2
  171. package/dist/subpaths/utils/MAX_SPRING_RATIO.js +1 -2
  172. package/dist/subpaths/utils/SCROLL_ALIGNMENTS.js +1 -2
  173. package/dist/subpaths/utils/SCROLL_AXES.js +1 -2
  174. package/dist/subpaths/utils/TRANSFORM_PROPS.js +1 -2
  175. package/dist/subpaths/utils/TRANSITION_OPTIONS.js +1 -2
  176. package/dist/subpaths/utils/camelCase.js +1 -2
  177. package/dist/subpaths/utils/capitalize.js +1 -2
  178. package/dist/subpaths/utils/clamp.js +1 -2
  179. package/dist/subpaths/utils/clamp01.js +1 -2
  180. package/dist/subpaths/utils/clampDampFactor.js +1 -2
  181. package/dist/subpaths/utils/createEaseInOut.js +1 -2
  182. package/dist/subpaths/utils/createEaseOut.js +1 -2
  183. package/dist/subpaths/utils/createElement.js +1 -2
  184. package/dist/subpaths/utils/createRange.js +1 -2
  185. package/dist/subpaths/utils/damp.js +1 -2
  186. package/dist/subpaths/utils/debounce.js +1 -2
  187. package/dist/subpaths/utils/decayOver.js +1 -2
  188. package/dist/subpaths/utils/deepmerge.js +1 -2
  189. package/dist/subpaths/utils/easeInCirc.js +1 -2
  190. package/dist/subpaths/utils/easeInCubic.js +1 -2
  191. package/dist/subpaths/utils/easeInExpo.js +1 -2
  192. package/dist/subpaths/utils/easeInOutCirc.js +1 -2
  193. package/dist/subpaths/utils/easeInOutCubic.js +1 -2
  194. package/dist/subpaths/utils/easeInOutExpo.js +1 -2
  195. package/dist/subpaths/utils/easeInOutQuad.js +1 -2
  196. package/dist/subpaths/utils/easeInOutQuart.js +1 -2
  197. package/dist/subpaths/utils/easeInOutQuint.js +1 -2
  198. package/dist/subpaths/utils/easeInOutSine.js +1 -2
  199. package/dist/subpaths/utils/easeInQuad.js +1 -2
  200. package/dist/subpaths/utils/easeInQuart.js +1 -2
  201. package/dist/subpaths/utils/easeInQuint.js +1 -2
  202. package/dist/subpaths/utils/easeInSine.js +1 -2
  203. package/dist/subpaths/utils/easeLinear.js +1 -2
  204. package/dist/subpaths/utils/easeOutCirc.js +1 -2
  205. package/dist/subpaths/utils/easeOutCubic.js +1 -2
  206. package/dist/subpaths/utils/easeOutExpo.js +1 -2
  207. package/dist/subpaths/utils/easeOutQuad.js +1 -2
  208. package/dist/subpaths/utils/easeOutQuart.js +1 -2
  209. package/dist/subpaths/utils/easeOutQuint.js +1 -2
  210. package/dist/subpaths/utils/easeOutSine.js +1 -2
  211. package/dist/subpaths/utils/enterTransition.js +1 -2
  212. package/dist/subpaths/utils/fold.js +1 -2
  213. package/dist/subpaths/utils/getOffsetSizes.js +1 -2
  214. package/dist/subpaths/utils/historyPush.js +1 -2
  215. package/dist/subpaths/utils/historyReplace.js +1 -2
  216. package/dist/subpaths/utils/inertiaDecay.js +1 -2
  217. package/dist/subpaths/utils/inertiaFinalValue.js +1 -2
  218. package/dist/subpaths/utils/inertiaStep.js +1 -2
  219. package/dist/subpaths/utils/inertiaTimeConstant.js +1 -2
  220. package/dist/subpaths/utils/isBoolean.js +1 -2
  221. package/dist/subpaths/utils/isDefined.js +1 -2
  222. package/dist/subpaths/utils/isFunction.js +1 -2
  223. package/dist/subpaths/utils/isNull.js +1 -2
  224. package/dist/subpaths/utils/isNumber.js +1 -2
  225. package/dist/subpaths/utils/isObject.js +1 -2
  226. package/dist/subpaths/utils/isString.js +1 -2
  227. package/dist/subpaths/utils/kebabCase.js +1 -2
  228. package/dist/subpaths/utils/leaveTransition.js +1 -2
  229. package/dist/subpaths/utils/lerp.js +1 -2
  230. package/dist/subpaths/utils/loadImage.js +1 -2
  231. package/dist/subpaths/utils/loadLink.js +1 -2
  232. package/dist/subpaths/utils/loadScript.js +1 -2
  233. package/dist/subpaths/utils/lockScroll.js +1 -2
  234. package/dist/subpaths/utils/lowerCase.js +1 -2
  235. package/dist/subpaths/utils/map.js +1 -2
  236. package/dist/subpaths/utils/matrix.js +1 -2
  237. package/dist/subpaths/utils/mean.js +1 -2
  238. package/dist/subpaths/utils/memo.js +1 -2
  239. package/dist/subpaths/utils/noop.js +1 -2
  240. package/dist/subpaths/utils/noopValue.js +1 -2
  241. package/dist/subpaths/utils/objectToURLSearchParams.js +1 -2
  242. package/dist/subpaths/utils/pascalCase.js +1 -2
  243. package/dist/subpaths/utils/random.js +1 -2
  244. package/dist/subpaths/utils/randomInt.js +1 -2
  245. package/dist/subpaths/utils/randomItem.js +1 -2
  246. package/dist/subpaths/utils/round.js +1 -2
  247. package/dist/subpaths/utils/saveActiveElement.js +1 -2
  248. package/dist/subpaths/utils/scrollPosition.js +1 -2
  249. package/dist/subpaths/utils/scrollTo.js +1 -2
  250. package/dist/subpaths/utils/selectorFor.js +1 -2
  251. package/dist/subpaths/utils/setClassesOrStyles.js +1 -2
  252. package/dist/subpaths/utils/smoothTo.js +1 -2
  253. package/dist/subpaths/utils/snakeCase.js +1 -2
  254. package/dist/subpaths/utils/spring.js +1 -2
  255. package/dist/subpaths/utils/throttle.js +1 -2
  256. package/dist/subpaths/utils/transform.js +1 -2
  257. package/dist/subpaths/utils/transition.js +1 -2
  258. package/dist/subpaths/utils/trapFocus.js +1 -2
  259. package/dist/subpaths/utils/untrapFocus.js +1 -2
  260. package/dist/subpaths/utils/upperCase.js +1 -2
  261. package/dist/subpaths/utils/wait.js +1 -2
  262. package/dist/subpaths/utils/withLeadingCharacters.js +1 -2
  263. package/dist/subpaths/utils/withLeadingSlash.js +1 -2
  264. package/dist/subpaths/utils/withTrailingCharacters.js +1 -2
  265. package/dist/subpaths/utils/withTrailingSlash.js +1 -2
  266. package/dist/subpaths/utils/withoutLeadingCharacters.js +1 -2
  267. package/dist/subpaths/utils/withoutLeadingCharactersRecursive.js +1 -2
  268. package/dist/subpaths/utils/withoutLeadingSlash.js +1 -2
  269. package/dist/subpaths/utils/withoutTrailingCharacters.js +1 -2
  270. package/dist/subpaths/utils/withoutTrailingCharactersRecursive.js +1 -2
  271. package/dist/subpaths/utils/withoutTrailingSlash.js +1 -2
  272. package/dist/subpaths/utils/wrap.js +1 -2
  273. package/dist/subpaths/viewTransition.js +1 -2
  274. package/dist/subpaths/warn.js +1 -2
  275. package/dist/subpaths/watchAttributeNamespace.js +1 -2
  276. package/dist/subpaths/watchAttributes.js +1 -2
  277. package/dist/subpaths/whenDOMSettled.js +1 -2
  278. package/dist/subpaths/withDrag.js +1 -2
  279. package/dist/subpaths/withInView.js +1 -2
  280. package/dist/subpaths/withKey.js +1 -2
  281. package/dist/subpaths/withMutation.js +1 -2
  282. package/dist/subpaths/withPointer.js +1 -2
  283. package/dist/subpaths/withRaf.js +1 -2
  284. package/dist/subpaths/withResize.js +1 -2
  285. package/dist/subpaths/withScroll.js +1 -2
  286. package/dist/subpaths/withScrollProgress.js +1 -2
  287. package/dist/subpaths/write.js +1 -2
  288. package/dist/swap.d.ts +0 -2
  289. package/dist/swap.js +1 -2
  290. package/dist/test/index.d.ts +0 -2
  291. package/dist/test/index.js +1 -2
  292. package/dist/utils/deepmerge.d.ts +0 -2
  293. package/dist/utils/deepmerge.js +1 -2
  294. package/dist/utils/dom.d.ts +0 -2
  295. package/dist/utils/dom.js +1 -2
  296. package/dist/utils/easings.d.ts +0 -2
  297. package/dist/utils/easings.js +1 -2
  298. package/dist/utils/focus.d.ts +0 -2
  299. package/dist/utils/focus.js +1 -2
  300. package/dist/utils/history.d.ts +0 -2
  301. package/dist/utils/history.js +1 -2
  302. package/dist/utils/is.d.ts +0 -2
  303. package/dist/utils/is.js +1 -2
  304. package/dist/utils/load.d.ts +0 -2
  305. package/dist/utils/load.js +1 -2
  306. package/dist/utils/maths.d.ts +0 -2
  307. package/dist/utils/maths.js +1 -2
  308. package/dist/utils/memo.d.ts +0 -2
  309. package/dist/utils/memo.js +1 -2
  310. package/dist/utils/noop.d.ts +0 -2
  311. package/dist/utils/noop.js +1 -2
  312. package/dist/utils/random.d.ts +0 -2
  313. package/dist/utils/random.js +1 -2
  314. package/dist/utils/scroll-lock.d.ts +0 -2
  315. package/dist/utils/scroll-lock.js +1 -2
  316. package/dist/utils/scrollTo.d.ts +0 -2
  317. package/dist/utils/scrollTo.js +1 -2
  318. package/dist/utils/selectors.d.ts +0 -2
  319. package/dist/utils/selectors.js +1 -2
  320. package/dist/utils/smoothTo.d.ts +0 -2
  321. package/dist/utils/smoothTo.js +1 -2
  322. package/dist/utils/strings.d.ts +0 -2
  323. package/dist/utils/strings.js +1 -2
  324. package/dist/utils/timing.d.ts +0 -2
  325. package/dist/utils/timing.js +1 -2
  326. package/dist/utils/transform.d.ts +0 -2
  327. package/dist/utils/transform.js +1 -2
  328. package/dist/utils/transition.d.ts +0 -2
  329. package/dist/utils/transition.js +1 -2
  330. package/dist/viewTransition.d.ts +0 -2
  331. package/dist/viewTransition.js +1 -2
  332. package/package.json +6 -3
  333. package/skills/studiometa-js-toolkit/SKILL.md +87 -0
  334. package/skills/studiometa-js-toolkit/references/api/configuration.md +169 -0
  335. package/skills/studiometa-js-toolkit/references/api/context/createContext.md +46 -0
  336. package/skills/studiometa-js-toolkit/references/api/context/createGroup.md +67 -0
  337. package/skills/studiometa-js-toolkit/references/api/context/index.md +69 -0
  338. package/skills/studiometa-js-toolkit/references/api/context/injectContext.md +58 -0
  339. package/skills/studiometa-js-toolkit/references/api/context/injectContextSync.md +44 -0
  340. package/skills/studiometa-js-toolkit/references/api/context/provideContext.md +61 -0
  341. package/skills/studiometa-js-toolkit/references/api/context/provideRootContext.md +42 -0
  342. package/skills/studiometa-js-toolkit/references/api/context/signal.md +85 -0
  343. package/skills/studiometa-js-toolkit/references/api/context/subscribeContext.md +71 -0
  344. package/skills/studiometa-js-toolkit/references/api/decorators/children.md +92 -0
  345. package/skills/studiometa-js-toolkit/references/api/decorators/component.md +75 -0
  346. package/skills/studiometa-js-toolkit/references/api/decorators/index.md +41 -0
  347. package/skills/studiometa-js-toolkit/references/api/decorators/inject.md +73 -0
  348. package/skills/studiometa-js-toolkit/references/api/decorators/on.md +149 -0
  349. package/skills/studiometa-js-toolkit/references/api/decorators/provide.md +77 -0
  350. package/skills/studiometa-js-toolkit/references/api/decorators/read-write.md +93 -0
  351. package/skills/studiometa-js-toolkit/references/api/diagnostics/DIAGNOSTICS.md +137 -0
  352. package/skills/studiometa-js-toolkit/references/api/diagnostics/EVENTS.md +45 -0
  353. package/skills/studiometa-js-toolkit/references/api/diagnostics/index.md +58 -0
  354. package/skills/studiometa-js-toolkit/references/api/diagnostics/reportDiagnostic.md +67 -0
  355. package/skills/studiometa-js-toolkit/references/api/diagnostics/warn.md +54 -0
  356. package/skills/studiometa-js-toolkit/references/api/dom/breakpoints.md +81 -0
  357. package/skills/studiometa-js-toolkit/references/api/dom/domUpdate.md +70 -0
  358. package/skills/studiometa-js-toolkit/references/api/dom/emitExtendable.md +68 -0
  359. package/skills/studiometa-js-toolkit/references/api/dom/index.md +26 -0
  360. package/skills/studiometa-js-toolkit/references/api/dom/swap.md +105 -0
  361. package/skills/studiometa-js-toolkit/references/api/dom/watchAttributeNamespace.md +96 -0
  362. package/skills/studiometa-js-toolkit/references/api/dom/watchAttributes.md +56 -0
  363. package/skills/studiometa-js-toolkit/references/api/dom/whenDOMSettled.md +41 -0
  364. package/skills/studiometa-js-toolkit/references/api/html/data-component.md +105 -0
  365. package/skills/studiometa-js-toolkit/references/api/html/data-mount.md +69 -0
  366. package/skills/studiometa-js-toolkit/references/api/html/data-option.md +106 -0
  367. package/skills/studiometa-js-toolkit/references/api/html/data-ref.md +63 -0
  368. package/skills/studiometa-js-toolkit/references/api/html/index.md +32 -0
  369. package/skills/studiometa-js-toolkit/references/api/index.md +73 -0
  370. package/skills/studiometa-js-toolkit/references/api/instance-events.md +75 -0
  371. package/skills/studiometa-js-toolkit/references/api/instance-methods.md +267 -0
  372. package/skills/studiometa-js-toolkit/references/api/instance-properties.md +90 -0
  373. package/skills/studiometa-js-toolkit/references/api/methods-hooks-events.md +149 -0
  374. package/skills/studiometa-js-toolkit/references/api/methods-hooks-lifecycle.md +90 -0
  375. package/skills/studiometa-js-toolkit/references/api/methods-hooks-options.md +96 -0
  376. package/skills/studiometa-js-toolkit/references/api/methods-hooks-services.md +164 -0
  377. package/skills/studiometa-js-toolkit/references/api/registry/defineManifest.md +57 -0
  378. package/skills/studiometa-js-toolkit/references/api/registry/fromMetaGlob.md +33 -0
  379. package/skills/studiometa-js-toolkit/references/api/registry/fromWebpackContext.md +37 -0
  380. package/skills/studiometa-js-toolkit/references/api/registry/getInstance.md +52 -0
  381. package/skills/studiometa-js-toolkit/references/api/registry/getInstances.md +48 -0
  382. package/skills/studiometa-js-toolkit/references/api/registry/getMountedInstances.md +39 -0
  383. package/skills/studiometa-js-toolkit/references/api/registry/getUnmountedInstances.md +46 -0
  384. package/skills/studiometa-js-toolkit/references/api/registry/index.md +49 -0
  385. package/skills/studiometa-js-toolkit/references/api/registry/registerComponent.md +93 -0
  386. package/skills/studiometa-js-toolkit/references/api/registry/registerComponents.md +37 -0
  387. package/skills/studiometa-js-toolkit/references/api/registry/registerManifest.md +72 -0
  388. package/skills/studiometa-js-toolkit/references/api/scheduler/defaultScheduler.md +104 -0
  389. package/skills/studiometa-js-toolkit/references/api/scheduler/index.md +27 -0
  390. package/skills/studiometa-js-toolkit/references/api/scheduler/nextFrame.md +31 -0
  391. package/skills/studiometa-js-toolkit/references/api/scheduler/viewTransition.md +53 -0
  392. package/skills/studiometa-js-toolkit/references/api/services/createService.md +95 -0
  393. package/skills/studiometa-js-toolkit/references/api/services/createServiceMixin.md +81 -0
  394. package/skills/studiometa-js-toolkit/references/api/services/index.md +94 -0
  395. package/skills/studiometa-js-toolkit/references/api/services/mixins.md +148 -0
  396. package/skills/studiometa-js-toolkit/references/api/services/perTarget.md +65 -0
  397. package/skills/studiometa-js-toolkit/references/api/services/toggle.md +80 -0
  398. package/skills/studiometa-js-toolkit/references/api/services/until.md +44 -0
  399. package/skills/studiometa-js-toolkit/references/api/services/useBreakpoint.md +42 -0
  400. package/skills/studiometa-js-toolkit/references/api/services/useDrag.md +119 -0
  401. package/skills/studiometa-js-toolkit/references/api/services/useInView.md +64 -0
  402. package/skills/studiometa-js-toolkit/references/api/services/useKey.md +105 -0
  403. package/skills/studiometa-js-toolkit/references/api/services/useMediaQuery.md +45 -0
  404. package/skills/studiometa-js-toolkit/references/api/services/useMutation.md +69 -0
  405. package/skills/studiometa-js-toolkit/references/api/services/usePointer.md +91 -0
  406. package/skills/studiometa-js-toolkit/references/api/services/usePrefersReducedMotion.md +42 -0
  407. package/skills/studiometa-js-toolkit/references/api/services/useRaf.md +91 -0
  408. package/skills/studiometa-js-toolkit/references/api/services/useResize.md +60 -0
  409. package/skills/studiometa-js-toolkit/references/api/services/useScroll.md +88 -0
  410. package/skills/studiometa-js-toolkit/references/api/services/useScrollProgress.md +88 -0
  411. package/skills/studiometa-js-toolkit/references/api/services/useWindowScroll.md +25 -0
  412. package/skills/studiometa-js-toolkit/references/api/services/useWindowSize.md +25 -0
  413. package/skills/studiometa-js-toolkit/references/api/storage/createStorage.md +126 -0
  414. package/skills/studiometa-js-toolkit/references/api/storage/index.md +33 -0
  415. package/skills/studiometa-js-toolkit/references/api/storage/presets.md +58 -0
  416. package/skills/studiometa-js-toolkit/references/api/storage/providers.md +109 -0
  417. package/skills/studiometa-js-toolkit/references/api/test/index.md +214 -0
  418. package/skills/studiometa-js-toolkit/references/guide/concepts/attribute-grammar.md +93 -0
  419. package/skills/studiometa-js-toolkit/references/guide/concepts/mutation-engine.md +71 -0
  420. package/skills/studiometa-js-toolkit/references/guide/concepts/philosophy.md +78 -0
  421. package/skills/studiometa-js-toolkit/references/guide/concepts/the-registry.md +110 -0
  422. package/skills/studiometa-js-toolkit/references/guide/going-further/autoloading.md +104 -0
  423. package/skills/studiometa-js-toolkit/references/guide/going-further/handling-diagnostics.md +104 -0
  424. package/skills/studiometa-js-toolkit/references/guide/going-further/mount-strategies.md +95 -0
  425. package/skills/studiometa-js-toolkit/references/guide/going-further/scheduling-work.md +124 -0
  426. package/skills/studiometa-js-toolkit/references/guide/going-further/sharing-state.md +218 -0
  427. package/skills/studiometa-js-toolkit/references/guide/going-further/swapping-content.md +92 -0
  428. package/skills/studiometa-js-toolkit/references/guide/going-further/testing-components.md +137 -0
  429. package/skills/studiometa-js-toolkit/references/guide/going-further/typing-components.md +190 -0
  430. package/skills/studiometa-js-toolkit/references/guide/going-further/using-decorators.md +168 -0
  431. package/skills/studiometa-js-toolkit/references/guide/going-further/using-storage.md +125 -0
  432. package/skills/studiometa-js-toolkit/references/guide/index.md +163 -0
  433. package/skills/studiometa-js-toolkit/references/guide/introduction/installation.md +144 -0
  434. package/skills/studiometa-js-toolkit/references/guide/introduction/lifecycle-hooks.md +174 -0
  435. package/skills/studiometa-js-toolkit/references/guide/introduction/managing-components.md +229 -0
  436. package/skills/studiometa-js-toolkit/references/guide/introduction/managing-options.md +235 -0
  437. package/skills/studiometa-js-toolkit/references/guide/introduction/managing-refs.md +174 -0
  438. package/skills/studiometa-js-toolkit/references/guide/introduction/using-services.md +218 -0
  439. package/skills/studiometa-js-toolkit/references/guide/introduction/working-with-events.md +251 -0
  440. package/skills/studiometa-js-toolkit/references/guide/migration/v3-to-v4.md +373 -0
  441. package/skills/studiometa-js-toolkit/references/utils/css.md +98 -0
  442. package/skills/studiometa-js-toolkit/references/utils/dom.md +54 -0
  443. package/skills/studiometa-js-toolkit/references/utils/easings.md +217 -0
  444. package/skills/studiometa-js-toolkit/references/utils/focus.md +84 -0
  445. package/skills/studiometa-js-toolkit/references/utils/history.md +69 -0
  446. package/skills/studiometa-js-toolkit/references/utils/index.md +53 -0
  447. package/skills/studiometa-js-toolkit/references/utils/is.md +84 -0
  448. package/skills/studiometa-js-toolkit/references/utils/load.md +59 -0
  449. package/skills/studiometa-js-toolkit/references/utils/math.md +129 -0
  450. package/skills/studiometa-js-toolkit/references/utils/motion.md +218 -0
  451. package/skills/studiometa-js-toolkit/references/utils/objects.md +68 -0
  452. package/skills/studiometa-js-toolkit/references/utils/scroll.md +128 -0
  453. package/skills/studiometa-js-toolkit/references/utils/strings.md +176 -0
  454. package/skills/studiometa-js-toolkit/references/utils/timing.md +111 -0
  455. package/skills/studiometa-js-toolkit/references/utils/transitions.md +122 -0
@@ -0,0 +1,235 @@
1
+ # Options
2
+
3
+ An option is a value a component reads from its element. It is declared in `config.options` and written in the markup as `data-option-<name>`.
4
+
5
+ Two rules carry everything else on this page:
6
+
7
+ > **An option is an input, never a store.**
8
+ >
9
+ > **Every option is responsive. There is nothing to declare for it.**
10
+
11
+ ## Declaring options
12
+
13
+ ```js
14
+ import { Base } from '@studiometa/js-toolkit';
15
+
16
+ class Slider extends Base {
17
+ static config = {
18
+ name: 'Slider',
19
+ options: {
20
+ // The short form: just the type.
21
+ label: String,
22
+ // The long form: a type and a default.
23
+ speed: { type: Number, default: 1 },
24
+ loop: { type: Boolean, default: true },
25
+ // Array and Object defaults must be factory functions.
26
+ tween: { type: Object, default: () => ({ ease: 'linear' }) },
27
+ },
28
+ };
29
+
30
+ mounted() {
31
+ console.log(this.$options.speed);
32
+ }
33
+ }
34
+ ```
35
+
36
+ ```html
37
+ <div data-component="Slider" data-option-speed="2" data-option-label="Gallery"></div>
38
+ ```
39
+
40
+ The attribute name is the option name in kebab case: `dragThreshold` is `data-option-drag-threshold`.
41
+
42
+ ## `$options` is a read-only view
43
+
44
+ `buildOptions()` defines every property with a **getter and no setter**. The value is derived from the element and the viewport on each access, and nothing is written in. An assignment throws, because a module is strict code:
45
+
46
+ ```js
47
+ this.$options.open = true;
48
+ // TypeError: Cannot set property open of #<Object> which has only a getter
49
+ ```
50
+
51
+ Two idioms replace the write, and which one you want depends on what the value is.
52
+
53
+ **The DOM is meant to change** — write the attribute. It is the same statement the markup makes:
54
+
55
+ ```js
56
+ import { Base } from '@studiometa/js-toolkit';
57
+
58
+ class Panel extends Base {
59
+ static config = { name: 'Panel', options: { disabled: Boolean } };
60
+
61
+ enable() {
62
+ this.$el.removeAttribute('data-option-disabled');
63
+ }
64
+
65
+ disable() {
66
+ this.$el.setAttribute('data-option-disabled', '');
67
+ }
68
+ }
69
+ ```
70
+
71
+ The next read gives the new value, and [`option<Name>Changed()`](#live-effects) announces it to anyone listening.
72
+
73
+ **The value was never an input** — keep a private field seeded from the option. The attribute says where the component starts; the field carries where it has got to:
74
+
75
+ ```js
76
+ import { Base } from '@studiometa/js-toolkit';
77
+
78
+ class Carousel extends Base {
79
+ static config = { name: 'Carousel', options: { start: { type: Number, default: 0 } } };
80
+
81
+ #index = this.$options.start;
82
+
83
+ next() {
84
+ this.#index += 1;
85
+ }
86
+ }
87
+ ```
88
+
89
+ An option a component only reads keeps neither: it reads `this.$options.x` where it needs it.
90
+
91
+ ## Defaults
92
+
93
+ **A primitive can be a default. Every other data type needs a factory function.**
94
+
95
+ ```js
96
+ options: {
97
+ speed: { type: Number, default: 1 }, // fine
98
+ tween: { type: Object, default: () => ({ ease: 'linear' }) }, // required form
99
+ items: { type: Array, default: () => [] }, // required form
100
+ }
101
+ ```
102
+
103
+ - `Function` is not an option type, so a `default` that is a function is always a factory.
104
+ - A default is built **once per instance** and then kept. Two instances never share one default.
105
+ - A factory is **lazy**. Nothing is built for an option nobody reads, and a component whose attribute is present never runs its factory.
106
+ - `Array` and `Object` with no declared default get an empty value per instance.
107
+ - A literal object or array default gives one `option.literal-default` warning, naming the component, the option and the correction. The value is then used as declared and **shared** between instances.
108
+
109
+ A default is the one option value that lives on the instance, so mutating the object a factory built sticks — `this.$options.tween.ease = 'ease-out'` is kept, for that instance. Replacing the option itself does not: `this.$options.tween = {}` throws, like every other write to the view.
110
+
111
+ ## Boolean options read presence
112
+
113
+ `data-option-open` is on, an absent attribute is the declared default, and the string the attribute carries is **never read** — the way `disabled` and `checked` work on the platform:
114
+
115
+ ```html
116
+ <div data-component="Panel" data-option-open></div>
117
+ <!-- true -->
118
+ <div data-component="Panel" data-option-open="false"></div>
119
+ <!-- true — the value says nothing -->
120
+ <div data-component="Panel"></div>
121
+ <!-- the declared default -->
122
+ ```
123
+
124
+ Update one from code by adding or removing the attribute:
125
+
126
+ ```js
127
+ flag ? el.setAttribute('data-option-open', '') : el.removeAttribute('data-option-open');
128
+ ```
129
+
130
+ A template must therefore write the attribute conditionally rather than interpolate a boolean into it:
131
+
132
+ ```html
133
+ {# Correct #}
134
+ <div data-component="Panel" {% if isOpen %}data-option-open{% endif %}></div>
135
+
136
+ {# Wrong — always true #}
137
+ <div data-component="Panel" data-option-open="{{ isOpen }}"></div>
138
+ ```
139
+
140
+ ### Turning one off — `data-option-no-<name>`
141
+
142
+ A boolean option is turned off by an attribute that only has to be there:
143
+
144
+ ```html
145
+ <div data-component="Dialog" data-option-no-trap-focus></div>
146
+ ```
147
+
148
+ - It is how an option declared `default: true` is turned off, since removing an attribute that is not there says nothing.
149
+ - **Only an option that can hold `false` has one** — a declared `Boolean`, or a union containing it. A `String` option has nothing to turn off, so `data-option-no-label` is not an attribute and the observer never watches for it.
150
+ - **Presence is the whole statement.** `data-option-no-x="false"` is not a double negative; it is the same flag.
151
+ - It is responsive like every other spelling.
152
+ - An option whose own name starts with `no` negates independently: `noSort` owns `data-option-no-sort`, and its off spelling doubles the prefix, `data-option-no-no-sort`.
153
+
154
+ ## Several types
155
+
156
+ An option can accept several types. Declare the constructors in order:
157
+
158
+ ```js
159
+ import { Base } from '@studiometa/js-toolkit';
160
+
161
+ class Sticky extends Base {
162
+ static config = {
163
+ name: 'Sticky',
164
+ options: {
165
+ // "10" reads as a number; "[10, 20]" reads as an array.
166
+ offset: [Number, Array],
167
+ },
168
+ };
169
+ }
170
+ ```
171
+
172
+ Each parser must give a value of its declared type before the next parser runs. An absent union option uses its declared default, or the empty value of its first type.
173
+
174
+ ## Responsive options
175
+
176
+ Every option takes a breakpoint suffix, with no flag to declare:
177
+
178
+ ```html
179
+ <div
180
+ data-component="Grid"
181
+ data-option-columns="1"
182
+ data-option-columns:s="2"
183
+ data-option-columns:l="4"></div>
184
+ ```
185
+
186
+ - **The suffix names one breakpoint and it cascades upwards.** `$options.columns` walks from the active breakpoint down to the base value and gives the first attribute present. v3 spelled a set (`:xs:s`); v4 does not.
187
+ - **The separator is a colon**, because an option name in kebab case can contain a dash.
188
+ - **The value is derived on read.** Nothing is stored and nothing is written.
189
+ - A suffix naming no configured breakpoint gives one `responsive.unknown-breakpoint` warning per mount.
190
+ - A `matchMedia` subscription opens **only** for a component that declares `option<Name>Changed()`. A page that only reads options holds no listener.
191
+
192
+ See [`setBreakpoints()`](../../api/dom/breakpoints.md) to replace the named set.
193
+
194
+ ## Live effects {#live-effects}
195
+
196
+ A declared method named `option<Name>Changed()` makes that option a live effect. It is how an option that chooses a resource stays correct:
197
+
198
+ ```js
199
+ import { Base } from '@studiometa/js-toolkit';
200
+
201
+ function connect(url) {
202
+ return { dispose() {} };
203
+ }
204
+
205
+ class Feed extends Base {
206
+ static config = { name: 'Feed', options: { source: String } };
207
+
208
+ optionSourceChanged({ value, previousValue, initial }) {
209
+ const connection = connect(value);
210
+ // The returned function is the cleanup for *this* value.
211
+ return () => connection.dispose();
212
+ }
213
+ }
214
+ ```
215
+
216
+ - The hook runs **before `mounted()`** on each mount cycle, with `initial: true`.
217
+ - Several writes in one mutation batch give **one** change, from the first old raw value to the final DOM value. A write that ends where it started is not a change.
218
+ - The previous cleanup runs before an update. Every active cleanup runs on `$unmount()`.
219
+ - Removal of the attribute applies the declared default.
220
+ - A breakpoint crossing reports through the same hook. A crossing to the same resolved value announces nothing.
221
+ - A component without the convention pays no setup cost.
222
+
223
+ The payload is an [`OptionChange`](../../api/methods-hooks-options.md):
224
+
225
+ ```ts
226
+ import { Base, type OptionChange } from '@studiometa/js-toolkit';
227
+
228
+ class Feed extends Base {
229
+ static config = { name: 'Feed', options: { source: String } };
230
+
231
+ optionSourceChanged({ value, previousValue, rawValue, initial }: OptionChange<string>) {
232
+ console.log(value, previousValue, rawValue, initial);
233
+ }
234
+ }
235
+ ```
@@ -0,0 +1,174 @@
1
+ # Refs
2
+
3
+ A ref is an element of a component's own markup, named in the HTML with `data-ref` and declared in `config.refs`.
4
+
5
+ **Refs are live.** Each `$refs` property reads the DOM on access, so markup put into a component is found with no refresh, and no detached element stays in a list. There is no `$update()`.
6
+
7
+ ## A single ref
8
+
9
+ ```html
10
+ <div data-component="Dialog">
11
+ <button data-ref="close">Close</button>
12
+ </div>
13
+ ```
14
+
15
+ ```js
16
+ import { Base } from '@studiometa/js-toolkit';
17
+
18
+ class Dialog extends Base {
19
+ static config = {
20
+ name: 'Dialog',
21
+ refs: ['close'],
22
+ };
23
+
24
+ mounted() {
25
+ this.$refs.close.focus();
26
+ }
27
+
28
+ onCloseClick() {
29
+ this.$el.removeAttribute('data-option-open');
30
+ }
31
+ }
32
+ ```
33
+
34
+ A plain declaration selects `[data-ref="close"]` and gives the **first** match.
35
+
36
+ ## A list of refs
37
+
38
+ **A list ref keeps the `[]` in the attribute.** The suffix is part of the name, in the config and in the markup:
39
+
40
+ ```html
41
+ <ul data-component="Tabs">
42
+ <li><button data-ref="tabs[]">One</button></li>
43
+ <li><button data-ref="tabs[]">Two</button></li>
44
+ </ul>
45
+ ```
46
+
47
+ ```js
48
+ import { Base } from '@studiometa/js-toolkit';
49
+
50
+ class Tabs extends Base {
51
+ static config = {
52
+ name: 'Tabs',
53
+ refs: ['tabs[]'],
54
+ };
55
+
56
+ onTabsClick({ index }) {
57
+ console.log(`tab ${index} was clicked`);
58
+ }
59
+ }
60
+ ```
61
+
62
+ `$refs.tabs` is an array. The property name never carries the suffix — `tabs[]` in the declaration, `$refs.tabs` everywhere else.
63
+
64
+ **The two spellings must agree**
65
+
66
+ `config.refs: ['tabs[]']` matches `data-ref="tabs[]"` and nothing else. The opposite mistake — the suffix missing from the attribute — gives one `ref.mismatch` warning per instance and per ref, naming the component and both spellings.
67
+
68
+ ## Ref boundaries
69
+
70
+ By default a ref belongs to the **nearest enclosing component**. A ref inside a nested component is that component's, not yours:
71
+
72
+ ```html
73
+ <div data-component="Slider">
74
+ <button data-ref="next">Slider's own</button>
75
+ <div data-component="SliderItem">
76
+ <button data-ref="next">SliderItem's, not Slider's</button>
77
+ </div>
78
+ </div>
79
+ ```
80
+
81
+ ### Naming the owner
82
+
83
+ A ref can name the component it belongs to, and then it crosses boundaries:
84
+
85
+ ```html
86
+ <div data-component="Slider">
87
+ <div data-component="SliderItem">
88
+ <button data-ref="Slider.next">Slider's, from inside a child</button>
89
+ </div>
90
+ </div>
91
+ ```
92
+
93
+ `Slider.next` passes every boundary **except** another `Slider`, so the nearest `Slider` wins and a nested `Slider` shadows its parent.
94
+
95
+ The namespace is written in the markup only, never in `config.refs`, and the name elsewhere never carries it:
96
+
97
+ | markup | `config.refs` | property | handler | decorator |
98
+ | -------------------------- | ------------- | ------------ | ------------- | ------------------ |
99
+ | `data-ref="next"` | `'next'` | `$refs.next` | `onNextClick` | `@on('next', …)` |
100
+ | `data-ref="Slider.next"` | `'next'` | `$refs.next` | `onNextClick` | `@on('next', …)` |
101
+ | `data-ref="dots[]"` | `'dots[]'` | `$refs.dots` | `onDotsClick` | `@on('dots[]', …)` |
102
+ | `data-ref="Slider.dots[]"` | `'dots[]'` | `$refs.dots` | `onDotsClick` | `@on('dots[]', …)` |
103
+
104
+ The namespace goes **before** the suffix: `Component.name[]`.
105
+
106
+ ## Event handlers
107
+
108
+ `on<Ref><Event>` handlers are **delegated from the root element**, so a ref that appears later needs no new binding:
109
+
110
+ ```js
111
+ import { Base } from '@studiometa/js-toolkit';
112
+
113
+ class Todo extends Base {
114
+ static config = {
115
+ name: 'Todo',
116
+ refs: ['items[]', 'input'],
117
+ };
118
+
119
+ // Fires for any `items[]` ref, including the ones added after mount.
120
+ onItemsClick({ event, target, index }) {
121
+ console.log(index, target);
122
+ }
123
+
124
+ onInputInput({ target }) {
125
+ console.log(target.value);
126
+ }
127
+ }
128
+ ```
129
+
130
+ The payload is `{ event, target, index }`:
131
+
132
+ - `event` — the DOM event.
133
+ - `target` — the ref element the handler matched, **not** `event.target`.
134
+ - `index` — the position in the list, or `0` for a single ref.
135
+
136
+ Events that do not bubble — `focus`, `blur`, `scroll`, `mouseenter`, `mouseleave` — are delegated from the **capture** phase, so they are heard all the same.
137
+
138
+ In TypeScript, annotate the payload with `RefEvent`:
139
+
140
+ ```ts
141
+ import { Base, type RefEvent } from '@studiometa/js-toolkit';
142
+
143
+ class Todo extends Base {
144
+ static config = { name: 'Todo', refs: ['input'] };
145
+
146
+ onInputInput({ target }: RefEvent<HTMLInputElement>) {
147
+ console.log(target.value);
148
+ }
149
+ }
150
+ ```
151
+
152
+ ## How the live read works
153
+
154
+ Ref lookups are cached, and the cache is invalidated by a counter that the framework's own MutationObserver increases. Reading that counter drains the pending records with `takeRecords()`, so the read is current even inside the same task as the mutation. Detached elements are never cached.
155
+
156
+ The practical consequence: you never refresh anything.
157
+
158
+ ```js
159
+ import { Base } from '@studiometa/js-toolkit';
160
+
161
+ class Todo extends Base {
162
+ static config = { name: 'Todo', refs: ['list', 'items[]'] };
163
+
164
+ add(title) {
165
+ const li = document.createElement('li');
166
+ li.dataset.ref = 'items[]';
167
+ li.textContent = title;
168
+ this.$refs.list.append(li);
169
+
170
+ // Already there. No `$update()`, no re-query.
171
+ console.log(this.$refs.items.length);
172
+ }
173
+ }
174
+ ```
@@ -0,0 +1,218 @@
1
+ # Services
2
+
3
+ A service is a shared source of props that components subscribe to. It is **lazy and reference-counted**: the source starts on the first subscriber and stops on the last, so with no subscriber there is no listener, no observer and no frame.
4
+
5
+ ## The sources
6
+
7
+ | Service | Hook | Props |
8
+ | ----------------------------------------------------------------------------- | ---------------- | ---------------------------------------------------------------------------- |
9
+ | [`useRaf()`](../../api/services/useRaf.md) | `ticked` | `time`, `delta` |
10
+ | [`useScroll(target?)`](../../api/services/useScroll.md) | `scrolled` | `x`, `y`, `deltaX/Y`, `maxX/Y`, `progressX/Y`, `directionX/Y`, `isScrolling` |
11
+ | [`useResize(target?)`](../../api/services/useResize.md) | `resized` | `width`, `height`, `ratio`, `orientation` |
12
+ | [`usePointer(target?)`](../../api/services/usePointer.md) | `moved` | `event`, `isDown`, `x`, `y`, `deltaX/Y`, `maxX/Y`, `progressX/Y` |
13
+ | [`useDrag(target, options?)`](../../api/services/useDrag.md) | `dragged` | `mode`, `x`, `y`, `deltaX/Y`, `originX/Y`, `distanceX/Y`, `finalX/Y` |
14
+ | [`useKey(target?)`](../../api/services/useKey.md) | `keyed` | `event`, `triggered`, `isDown`, `isUp`, plus one boolean per named key |
15
+ | [`useInView(target, init?)`](../../api/services/useInView.md) | `intersected` | `isInView`, `entry` |
16
+ | [`useMutation(target, init?)`](../../api/services/useMutation.md) | `mutated` | `records` |
17
+ | [`useScrollProgress(target, options?)`](../../api/services/useScrollProgress.md) | `scrolledInView` | `startX/Y`, `endX/Y`, `currentX/Y`, `progressX/Y` |
18
+ | [`useBreakpoint()`](../../api/services/useBreakpoint.md) | — | `name` |
19
+ | [`useMediaQuery(query)`](../../api/services/useMediaQuery.md) | — | `matches` |
20
+
21
+ `useWindowScroll()` and `useWindowSize()` name the default cases. `usePrefersReducedMotion()` is the named media query.
22
+
23
+ ## Subscribing by hand
24
+
25
+ Every service has the same two-method surface, so subscribing is one line and the release is what `mounted()` returns:
26
+
27
+ ```js
28
+ import { Base, useScroll } from '@studiometa/js-toolkit';
29
+
30
+ class Header extends Base {
31
+ static config = { name: 'Header' };
32
+
33
+ mounted() {
34
+ return useScroll().subscribe(({ directionY, y }) => {
35
+ this.$el.classList.toggle('is-hidden', directionY > 0 && y > 100);
36
+ });
37
+ }
38
+ }
39
+ ```
40
+
41
+ `subscribe(callback, options?)` returns the unsubscribe function. `props()` reads the current props with no subscription.
42
+
43
+ ### Asking for the first delivery
44
+
45
+ ```js
46
+ useScroll().subscribe(callback, { immediate: true });
47
+ ```
48
+
49
+ The sources that have a current value honour it; the ones that do not, do nothing. The frame tick has no current value between two frames, the pointer has none before it is seen, and a drag has none outside a gesture. Only the new subscriber is called, and the first props of a run carry no movement.
50
+
51
+ ## Mixins — the declarative form
52
+
53
+ A mixin binds one subscription per mount cycle, under the one method name the service owns:
54
+
55
+ ```js
56
+ import { Base, withScroll } from '@studiometa/js-toolkit';
57
+
58
+ class Header extends withScroll(Base) {
59
+ static config = { name: 'Header' };
60
+
61
+ scrolled({ directionY }) {
62
+ this.$el.classList.toggle('is-hidden', directionY > 0);
63
+ }
64
+ }
65
+ ```
66
+
67
+ The mixins are `withRaf`, `withScroll`, `withResize`, `withScrollProgress`, `withPointer`, `withDrag`, `withInView`, `withMutation` and `withKey`.
68
+
69
+ **A mixin never occupies a lifecycle hook**
70
+
71
+ `mounted()` and `unmounted()` belong to the component author. The subscription rides on the framework's own `$mount()`/`$unmount()` pair, so a class that mixes a service in and writes its own `mounted()` **without** `super.mounted()` still subscribes.
72
+
73
+ The subscription therefore starts once the whole of `mounted()` has run — including an `immediate` first delivery, which reaches a component that is fully set up — and is released before `unmounted()`.
74
+
75
+ ### Scoping a mixin to a ref
76
+
77
+ ```js
78
+ import { Base, withResize } from '@studiometa/js-toolkit';
79
+
80
+ class Panel extends withResize(Base, { target: (instance) => instance.$refs.inner }) {
81
+ static config = { name: 'Panel' };
82
+
83
+ resized({ width }) {
84
+ console.log(width);
85
+ }
86
+ }
87
+ ```
88
+
89
+ A resolver that comes back with `undefined` or `null` reports `service.missing-target` and starts **no** subscription — because a renamed ref arrives here as nothing, and a service with a default target would otherwise observe the wrong thing and look like it worked.
90
+
91
+ ### Suspending a hook
92
+
93
+ `{ manual: true }` declares the hook without running it. `$services.<hook>` is the switch:
94
+
95
+ ```js
96
+ import { Base, withRaf } from '@studiometa/js-toolkit';
97
+
98
+ class SliderItem extends withRaf(Base, { manual: true }) {
99
+ static config = { name: 'SliderItem' };
100
+
101
+ ticked({ delta }) {
102
+ // declared, not running
103
+ }
104
+
105
+ start() {
106
+ this.$services.ticked.start();
107
+ }
108
+
109
+ stop() {
110
+ this.$services.ticked.stop();
111
+ }
112
+ }
113
+ ```
114
+
115
+ ### One hook per class, and that is the limit
116
+
117
+ A mixin binds **one** subscription, under one name, per mount cycle. A component whose subscriptions are one per markup declaration — an attribute-driven set, with its own modifiers and its own threshold, known only when the element is read — has no method to name and no fixed count. It calls `subscribe()` itself and returns the release from `mounted()`. That is the intended path, not a workaround.
118
+
119
+ `on<Event>` has the same shape: a handler name belongs to the class, while a set of events can be data.
120
+
121
+ ## Two combinators
122
+
123
+ ### `toggle()` — a subscription you can switch
124
+
125
+ ```js
126
+ import { Base, toggle, useRaf } from '@studiometa/js-toolkit';
127
+
128
+ class SliderItem extends Base {
129
+ static config = { name: 'SliderItem' };
130
+
131
+ #frame = toggle(() => useRaf().subscribe(({ delta }) => this.follow(delta)));
132
+
133
+ mounted() {
134
+ // `stop` is bound, so it is a cleanup as it is.
135
+ return this.#frame.stop;
136
+ }
137
+
138
+ follow(delta) {}
139
+
140
+ onSelected() {
141
+ this.#frame.start();
142
+ }
143
+
144
+ onSettled() {
145
+ this.#frame.stop();
146
+ }
147
+ }
148
+ ```
149
+
150
+ `start()` is idempotent and `stop()` is safe to repeat. It works on a `Signal`, on a bare listener, and outside a component.
151
+
152
+ ### `until()` — a one-shot wait
153
+
154
+ ```js
155
+ import { until, useScroll } from '@studiometa/js-toolkit';
156
+
157
+ async function afterScroll() {
158
+ const props = await until(useScroll(), ({ isScrolling }) => !isScrolling);
159
+ console.log(props.y);
160
+ }
161
+ ```
162
+
163
+ It resolves on the first update that matches, releases the subscription **before** it resolves, and resolves with a copy of the props. It resolves at once when the current props already match.
164
+
165
+ ## The props contract
166
+
167
+ - **Props are flat, one field per axis, and nothing derivable is a field.** `lastX` is `x - deltaX`; `changedX` is `deltaX !== 0`. The grouped objects of v3 (`last`, `delta`, `max`, `progress`, `direction`, `changed`) are gone.
168
+ - **`directionX` and `directionY` are `-1 | 0 | 1`** — one signed value that multiplies.
169
+ - **Every field is `readonly`, and the props object belongs to its service.** It is valid for the duration of the call that received it. Use `{ ...props }` to keep one.
170
+
171
+ ## One instance per target and per options
172
+
173
+ Services are keyed in a `WeakMap` by target **and** by the meaning of their options, so two callers asking for the same thing share one source:
174
+
175
+ ```js
176
+ import { useInView } from '@studiometa/js-toolkit';
177
+
178
+ const el = document.body;
179
+
180
+ // The same service — the key is read by meaning, not by spelling.
181
+ useInView(el, { threshold: 0.5, rootMargin: '0px' });
182
+ useInView(el, { rootMargin: '0px', threshold: 0.5 });
183
+ ```
184
+
185
+ Nothing groups observers across targets.
186
+
187
+ ## No service owns a loop
188
+
189
+ The raf service and an active drag inertia subscribe to `scheduler.tick()`. The scroll service coalesces its events into one `read` per frame. The resize service is a `ResizeObserver`. See [The scheduler](../going-further/scheduling-work.md).
190
+
191
+ ## Writing your own
192
+
193
+ `createService()` is the whole primitive. Give it a `props` reader and a `start` function that returns its teardown:
194
+
195
+ ```ts
196
+ import { createService, perTarget } from '@studiometa/js-toolkit';
197
+
198
+ interface FocusProps {
199
+ readonly hasFocus: boolean;
200
+ }
201
+
202
+ const useFocus = perTarget((target: Element) =>
203
+ createService<FocusProps>({
204
+ props: () => ({ hasFocus: target.contains(document.activeElement) }),
205
+ start(emit) {
206
+ const onChange = () => emit({ hasFocus: target.contains(document.activeElement) });
207
+ document.addEventListener('focusin', onChange);
208
+ document.addEventListener('focusout', onChange);
209
+ return () => {
210
+ document.removeEventListener('focusin', onChange);
211
+ document.removeEventListener('focusout', onChange);
212
+ };
213
+ },
214
+ }),
215
+ );
216
+ ```
217
+
218
+ `perTarget()` gives it the one-instance-per-target caching every built-in service has. See [`createService()`](../../api/services/createService.md) and [`createServiceMixin()`](../../api/services/createServiceMixin.md).