@studiometa/js-toolkit 4.0.0-alpha.1 → 4.0.0-alpha.2

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 (125) hide show
  1. package/README.md +10 -0
  2. package/package.json +5 -2
  3. package/skills/studiometa-js-toolkit/SKILL.md +87 -0
  4. package/skills/studiometa-js-toolkit/references/api/configuration.md +169 -0
  5. package/skills/studiometa-js-toolkit/references/api/context/createContext.md +46 -0
  6. package/skills/studiometa-js-toolkit/references/api/context/createGroup.md +67 -0
  7. package/skills/studiometa-js-toolkit/references/api/context/index.md +69 -0
  8. package/skills/studiometa-js-toolkit/references/api/context/injectContext.md +58 -0
  9. package/skills/studiometa-js-toolkit/references/api/context/injectContextSync.md +44 -0
  10. package/skills/studiometa-js-toolkit/references/api/context/provideContext.md +61 -0
  11. package/skills/studiometa-js-toolkit/references/api/context/provideRootContext.md +42 -0
  12. package/skills/studiometa-js-toolkit/references/api/context/signal.md +85 -0
  13. package/skills/studiometa-js-toolkit/references/api/context/subscribeContext.md +71 -0
  14. package/skills/studiometa-js-toolkit/references/api/decorators/children.md +92 -0
  15. package/skills/studiometa-js-toolkit/references/api/decorators/component.md +75 -0
  16. package/skills/studiometa-js-toolkit/references/api/decorators/index.md +41 -0
  17. package/skills/studiometa-js-toolkit/references/api/decorators/inject.md +73 -0
  18. package/skills/studiometa-js-toolkit/references/api/decorators/on.md +149 -0
  19. package/skills/studiometa-js-toolkit/references/api/decorators/provide.md +77 -0
  20. package/skills/studiometa-js-toolkit/references/api/decorators/read-write.md +93 -0
  21. package/skills/studiometa-js-toolkit/references/api/diagnostics/DIAGNOSTICS.md +137 -0
  22. package/skills/studiometa-js-toolkit/references/api/diagnostics/EVENTS.md +45 -0
  23. package/skills/studiometa-js-toolkit/references/api/diagnostics/index.md +58 -0
  24. package/skills/studiometa-js-toolkit/references/api/diagnostics/reportDiagnostic.md +67 -0
  25. package/skills/studiometa-js-toolkit/references/api/diagnostics/warn.md +54 -0
  26. package/skills/studiometa-js-toolkit/references/api/dom/breakpoints.md +81 -0
  27. package/skills/studiometa-js-toolkit/references/api/dom/domUpdate.md +70 -0
  28. package/skills/studiometa-js-toolkit/references/api/dom/emitExtendable.md +68 -0
  29. package/skills/studiometa-js-toolkit/references/api/dom/index.md +26 -0
  30. package/skills/studiometa-js-toolkit/references/api/dom/swap.md +105 -0
  31. package/skills/studiometa-js-toolkit/references/api/dom/watchAttributeNamespace.md +96 -0
  32. package/skills/studiometa-js-toolkit/references/api/dom/watchAttributes.md +56 -0
  33. package/skills/studiometa-js-toolkit/references/api/dom/whenDOMSettled.md +41 -0
  34. package/skills/studiometa-js-toolkit/references/api/html/data-component.md +105 -0
  35. package/skills/studiometa-js-toolkit/references/api/html/data-mount.md +69 -0
  36. package/skills/studiometa-js-toolkit/references/api/html/data-option.md +106 -0
  37. package/skills/studiometa-js-toolkit/references/api/html/data-ref.md +63 -0
  38. package/skills/studiometa-js-toolkit/references/api/html/index.md +32 -0
  39. package/skills/studiometa-js-toolkit/references/api/index.md +73 -0
  40. package/skills/studiometa-js-toolkit/references/api/instance-events.md +75 -0
  41. package/skills/studiometa-js-toolkit/references/api/instance-methods.md +267 -0
  42. package/skills/studiometa-js-toolkit/references/api/instance-properties.md +90 -0
  43. package/skills/studiometa-js-toolkit/references/api/methods-hooks-events.md +149 -0
  44. package/skills/studiometa-js-toolkit/references/api/methods-hooks-lifecycle.md +90 -0
  45. package/skills/studiometa-js-toolkit/references/api/methods-hooks-options.md +96 -0
  46. package/skills/studiometa-js-toolkit/references/api/methods-hooks-services.md +164 -0
  47. package/skills/studiometa-js-toolkit/references/api/registry/defineManifest.md +57 -0
  48. package/skills/studiometa-js-toolkit/references/api/registry/fromMetaGlob.md +33 -0
  49. package/skills/studiometa-js-toolkit/references/api/registry/fromWebpackContext.md +37 -0
  50. package/skills/studiometa-js-toolkit/references/api/registry/getInstance.md +52 -0
  51. package/skills/studiometa-js-toolkit/references/api/registry/getInstances.md +48 -0
  52. package/skills/studiometa-js-toolkit/references/api/registry/getMountedInstances.md +39 -0
  53. package/skills/studiometa-js-toolkit/references/api/registry/getUnmountedInstances.md +46 -0
  54. package/skills/studiometa-js-toolkit/references/api/registry/index.md +49 -0
  55. package/skills/studiometa-js-toolkit/references/api/registry/registerComponent.md +93 -0
  56. package/skills/studiometa-js-toolkit/references/api/registry/registerComponents.md +37 -0
  57. package/skills/studiometa-js-toolkit/references/api/registry/registerManifest.md +72 -0
  58. package/skills/studiometa-js-toolkit/references/api/scheduler/defaultScheduler.md +104 -0
  59. package/skills/studiometa-js-toolkit/references/api/scheduler/index.md +27 -0
  60. package/skills/studiometa-js-toolkit/references/api/scheduler/nextFrame.md +31 -0
  61. package/skills/studiometa-js-toolkit/references/api/scheduler/viewTransition.md +53 -0
  62. package/skills/studiometa-js-toolkit/references/api/services/createService.md +95 -0
  63. package/skills/studiometa-js-toolkit/references/api/services/createServiceMixin.md +81 -0
  64. package/skills/studiometa-js-toolkit/references/api/services/index.md +94 -0
  65. package/skills/studiometa-js-toolkit/references/api/services/mixins.md +148 -0
  66. package/skills/studiometa-js-toolkit/references/api/services/perTarget.md +65 -0
  67. package/skills/studiometa-js-toolkit/references/api/services/toggle.md +80 -0
  68. package/skills/studiometa-js-toolkit/references/api/services/until.md +44 -0
  69. package/skills/studiometa-js-toolkit/references/api/services/useBreakpoint.md +42 -0
  70. package/skills/studiometa-js-toolkit/references/api/services/useDrag.md +119 -0
  71. package/skills/studiometa-js-toolkit/references/api/services/useInView.md +64 -0
  72. package/skills/studiometa-js-toolkit/references/api/services/useKey.md +105 -0
  73. package/skills/studiometa-js-toolkit/references/api/services/useMediaQuery.md +45 -0
  74. package/skills/studiometa-js-toolkit/references/api/services/useMutation.md +69 -0
  75. package/skills/studiometa-js-toolkit/references/api/services/usePointer.md +91 -0
  76. package/skills/studiometa-js-toolkit/references/api/services/usePrefersReducedMotion.md +42 -0
  77. package/skills/studiometa-js-toolkit/references/api/services/useRaf.md +91 -0
  78. package/skills/studiometa-js-toolkit/references/api/services/useResize.md +60 -0
  79. package/skills/studiometa-js-toolkit/references/api/services/useScroll.md +88 -0
  80. package/skills/studiometa-js-toolkit/references/api/services/useScrollProgress.md +88 -0
  81. package/skills/studiometa-js-toolkit/references/api/services/useWindowScroll.md +25 -0
  82. package/skills/studiometa-js-toolkit/references/api/services/useWindowSize.md +25 -0
  83. package/skills/studiometa-js-toolkit/references/api/storage/createStorage.md +126 -0
  84. package/skills/studiometa-js-toolkit/references/api/storage/index.md +33 -0
  85. package/skills/studiometa-js-toolkit/references/api/storage/presets.md +58 -0
  86. package/skills/studiometa-js-toolkit/references/api/storage/providers.md +109 -0
  87. package/skills/studiometa-js-toolkit/references/api/test/index.md +214 -0
  88. package/skills/studiometa-js-toolkit/references/guide/concepts/attribute-grammar.md +93 -0
  89. package/skills/studiometa-js-toolkit/references/guide/concepts/mutation-engine.md +71 -0
  90. package/skills/studiometa-js-toolkit/references/guide/concepts/philosophy.md +78 -0
  91. package/skills/studiometa-js-toolkit/references/guide/concepts/the-registry.md +110 -0
  92. package/skills/studiometa-js-toolkit/references/guide/going-further/autoloading.md +104 -0
  93. package/skills/studiometa-js-toolkit/references/guide/going-further/handling-diagnostics.md +104 -0
  94. package/skills/studiometa-js-toolkit/references/guide/going-further/mount-strategies.md +95 -0
  95. package/skills/studiometa-js-toolkit/references/guide/going-further/scheduling-work.md +124 -0
  96. package/skills/studiometa-js-toolkit/references/guide/going-further/sharing-state.md +218 -0
  97. package/skills/studiometa-js-toolkit/references/guide/going-further/swapping-content.md +92 -0
  98. package/skills/studiometa-js-toolkit/references/guide/going-further/testing-components.md +137 -0
  99. package/skills/studiometa-js-toolkit/references/guide/going-further/typing-components.md +190 -0
  100. package/skills/studiometa-js-toolkit/references/guide/going-further/using-decorators.md +168 -0
  101. package/skills/studiometa-js-toolkit/references/guide/going-further/using-storage.md +125 -0
  102. package/skills/studiometa-js-toolkit/references/guide/index.md +163 -0
  103. package/skills/studiometa-js-toolkit/references/guide/introduction/installation.md +144 -0
  104. package/skills/studiometa-js-toolkit/references/guide/introduction/lifecycle-hooks.md +174 -0
  105. package/skills/studiometa-js-toolkit/references/guide/introduction/managing-components.md +229 -0
  106. package/skills/studiometa-js-toolkit/references/guide/introduction/managing-options.md +235 -0
  107. package/skills/studiometa-js-toolkit/references/guide/introduction/managing-refs.md +174 -0
  108. package/skills/studiometa-js-toolkit/references/guide/introduction/using-services.md +218 -0
  109. package/skills/studiometa-js-toolkit/references/guide/introduction/working-with-events.md +251 -0
  110. package/skills/studiometa-js-toolkit/references/guide/migration/v3-to-v4.md +373 -0
  111. package/skills/studiometa-js-toolkit/references/utils/css.md +98 -0
  112. package/skills/studiometa-js-toolkit/references/utils/dom.md +54 -0
  113. package/skills/studiometa-js-toolkit/references/utils/easings.md +217 -0
  114. package/skills/studiometa-js-toolkit/references/utils/focus.md +84 -0
  115. package/skills/studiometa-js-toolkit/references/utils/history.md +69 -0
  116. package/skills/studiometa-js-toolkit/references/utils/index.md +53 -0
  117. package/skills/studiometa-js-toolkit/references/utils/is.md +84 -0
  118. package/skills/studiometa-js-toolkit/references/utils/load.md +59 -0
  119. package/skills/studiometa-js-toolkit/references/utils/math.md +129 -0
  120. package/skills/studiometa-js-toolkit/references/utils/motion.md +218 -0
  121. package/skills/studiometa-js-toolkit/references/utils/objects.md +68 -0
  122. package/skills/studiometa-js-toolkit/references/utils/scroll.md +128 -0
  123. package/skills/studiometa-js-toolkit/references/utils/strings.md +176 -0
  124. package/skills/studiometa-js-toolkit/references/utils/timing.md +111 -0
  125. package/skills/studiometa-js-toolkit/references/utils/transitions.md +122 -0
@@ -0,0 +1,373 @@
1
+ # Migrating from v3 to v4
2
+
3
+ v4 is a full breaking major. There is no bridge release and no compatibility layer: `@studiometa/js-toolkit` 4.0 and `@studiometa/ui` 2.0 ship together.
4
+
5
+ Migration help is tooling, not runtime shims. Lint rules flag `$children`, `$parent`, `updated()` and the old handler signatures, and codemods cover mechanical renames only.
6
+
7
+ ## The component tree
8
+
9
+ ### `$parent`, `$children` and `$root` are removed
10
+
11
+ Parent and child are DOM ancestry, never ownership, so nothing holds a reference in either direction.
12
+
13
+ ```js
14
+ this.$children.SliderItem; // [!code --]
15
+ this.$query('SliderItem'); // [!code ++]
16
+
17
+ this.$parent.goTo(index); // [!code --]
18
+ this.$closest('Slider')?.goTo(index); // [!code ++]
19
+
20
+ this.$root.doSomething(); // [!code --]
21
+ this.$closest('App')?.doSomething(); // [!code ++]
22
+ ```
23
+
24
+ `$query(name)` returns a flat `Base[]` of all matching descendants, at any depth — not the keyed object `$children` was. `$closest(name)` is resolved on every access and returns `Base | null`, so guard it and never dereference it unguarded in `mounted()`.
25
+
26
+ Better than either: a parent watches its children, and a child emits.
27
+
28
+ ```js
29
+ items = this.$watchChildren('SliderItem'); // [!code ++]
30
+ ```
31
+
32
+ ### `createApp()` is removed
33
+
34
+ There is no root component and no application object.
35
+
36
+ ```js
37
+ createApp(App); // [!code --]
38
+ registerComponents(Accordion, Slider, TodoList); // [!code ++]
39
+ ```
40
+
41
+ A component is registered, not mounted by a parent, so nothing has to own the page.
42
+
43
+ ### `ChildrenManager` is gone
44
+
45
+ A nested `data-component` is discovered by the registry on its own. `config.components` still exists, but it now declares a **family** — it registers those names and supplies the name set that `on<Child><Event>` resolution needs. It does not construct anything.
46
+
47
+ Unmounting a parent no longer unmounts its children.
48
+
49
+ ## Refs
50
+
51
+ ### `$update()` is removed
52
+
53
+ Refs are live: each `$refs` property reads the DOM on access.
54
+
55
+ ```js
56
+ this.$refs.list.append(li);
57
+ this.$update(); // [!code --]
58
+ console.log(this.$refs.items.length); // already correct
59
+ ```
60
+
61
+ ### A list ref keeps the `[]` in the attribute
62
+
63
+ ```html
64
+ <li data-ref="items"></li>
65
+ <!-- [!code --] -->
66
+ <li data-ref="items[]"></li>
67
+ <!-- [!code ++] -->
68
+ ```
69
+
70
+ `config.refs: ['items[]']` matches `data-ref="items[]"` **and nothing else**. The mismatch gives a `ref.mismatch` warning naming both spellings.
71
+
72
+ The property name never carries the suffix: `$refs.items`, `onItemsClick`, `@on('items[]', 'click')`.
73
+
74
+ ## Options
75
+
76
+ ### `$options` is read-only
77
+
78
+ Every property is a getter with no setter, so an assignment throws.
79
+
80
+ ```js
81
+ this.$options.open = true; // [!code --]
82
+ this.$el.setAttribute('data-option-open', ''); // [!code ++]
83
+ ```
84
+
85
+ Or keep a private field, when the value was never an input:
86
+
87
+ ```js
88
+ #isOpen = this.$options.open; // [!code ++]
89
+ ```
90
+
91
+ ### A boolean option reads presence
92
+
93
+ The attribute's value is never read.
94
+
95
+ ```html
96
+ <div data-option-open="false"></div>
97
+ <!-- v3: false · v4: true -->
98
+ ```
99
+
100
+ Turn one off by removing the attribute, or — for an option declared `default: true` — with the negated spelling:
101
+
102
+ ```html
103
+ <div data-component="Dialog" data-option-no-trap-focus></div>
104
+ ```
105
+
106
+ Templates must write the attribute conditionally rather than interpolate a boolean into it.
107
+
108
+ ### Non-primitive defaults must be factories
109
+
110
+ ```js
111
+ options: {
112
+ tween: { type: Object, default: { ease: 'linear' } }, // [!code --]
113
+ tween: { type: Object, default: () => ({ ease: 'linear' }) }, // [!code ++]
114
+ }
115
+ ```
116
+
117
+ A literal gives an `option.literal-default` warning, and the value is then shared between instances.
118
+
119
+ ### Responsive options lose the list syntax
120
+
121
+ Every option is responsive with nothing to declare. `withResponsiveOptions` is gone, and so is the set spelling.
122
+
123
+ ```html
124
+ <div data-option-columns:xs:s="2"></div>
125
+ <!-- [!code --] -->
126
+ <div data-option-columns:xs="2"></div>
127
+ <!-- [!code ++] -->
128
+ ```
129
+
130
+ A suffix names **one** breakpoint and cascades upwards. An unknown suffix warns once per mount.
131
+
132
+ ### `config.emits` is a type now
133
+
134
+ ```js
135
+ static config = { name: 'Slider', emits: ['goto'] }; // [!code --]
136
+ ```
137
+
138
+ ```ts
139
+ class Slider extends Base<{ $emits: { goto: { index: number } } }> {} // [!code ++]
140
+ ```
141
+
142
+ Nothing of it stays in the bundle.
143
+
144
+ ## Events
145
+
146
+ ### `$emit()` takes one payload object
147
+
148
+ ```js
149
+ this.$emit('slide', 1, 'left'); // [!code --]
150
+ this.$emit('slide', { index: 1, direction: 'left' }); // [!code ++]
151
+ ```
152
+
153
+ `detail` **is** that object, and an omitted payload leaves `detail` at the platform value `null`. A value that is not an object is refused by the type and reported as `event.invalid-emit-payload`.
154
+
155
+ ### Handler payloads are one object
156
+
157
+ ```js
158
+ onSliderItemClick(event, index) {} // [!code --]
159
+ onSliderItemClick({ event, target, index }) {} // [!code ++]
160
+ ```
161
+
162
+ - a ref handler receives `{ event, target, index }`, where `target` is the **ref element**, not `event.target`;
163
+ - a child handler receives `{ event, target, payload }`, where `target` is the **instance**;
164
+ - a global handler receives `{ event, target }`, with no `payload` and no `index`.
165
+
166
+ ### `onWindow<Event>` and `onDocument<Event>` are reserved prefixes
167
+
168
+ They match before children and refs. To reach a child named `Window`, use `@on('Window', 'resize')`.
169
+
170
+ ## Lifecycle
171
+
172
+ ### `updated()` is removed
173
+
174
+ There is no third lifecycle notion. Use [`option<Name>Changed()`](../introduction/managing-options.md#live-effects) for an option that chooses a resource, and [`watchAttributes()`](../../api/dom/watchAttributes.md) for an attribute the framework does not read.
175
+
176
+ ### `mounted()` can return its cleanup
177
+
178
+ ```js
179
+ mounted() {
180
+ this.unsubscribe = useScroll().subscribe(this.onScroll); // [!code --]
181
+ return useScroll().subscribe(this.onScroll); // [!code ++]
182
+ }
183
+
184
+ unmounted() {
185
+ this.unsubscribe(); // [!code --]
186
+ }
187
+ ```
188
+
189
+ Sync or async, a function or an array of functions. An async `mounted()` that resolves after the unmount runs its cleanup immediately.
190
+
191
+ ### `terminated` and the permanent state are gone
192
+
193
+ `$unmount()` leaves the instance on its element, so "do this once per element" is a plain field:
194
+
195
+ ```js
196
+ mounted() {
197
+ if (this.hasLoaded) return;
198
+ …
199
+ this.hasLoaded = true;
200
+ }
201
+ ```
202
+
203
+ ## Loading and mounting
204
+
205
+ ### `data-load` becomes `data-mount`
206
+
207
+ Deferring the import and deferring the mount are one decision.
208
+
209
+ ```html
210
+ <div data-component="Map" data-load="visible"></div>
211
+ <!-- [!code --] -->
212
+ <div data-component="Map" data-mount="visible"></div>
213
+ <!-- [!code ++] -->
214
+ ```
215
+
216
+ ### The `withMountWhen*` decorators are deleted
217
+
218
+ | v3 | v4 |
219
+ | --------------------------------------------------- | ------------------------------------------------------------ |
220
+ | `withMountWhenInView(Base)` | `data-mount="visible"` or `config.mountStrategy` |
221
+ | `withMountOnMediaQuery(Base, '(min-width: 48rem)')` | `data-mount="media:(min-width: 48rem)"` |
222
+ | `withMountWhenPrefersMotion(Base)` | `data-mount="media:(prefers-reduced-motion: no-preference)"` |
223
+
224
+ A strategy constructs nothing; it decides when the registry calls the mount and unmount hooks. See [Mount strategies](../going-further/mount-strategies.md).
225
+
226
+ ### The lazy import helpers are replaced by the manifest
227
+
228
+ `importWhenVisible`, `importWhenIdle`, `importOnInteraction`, `importOnMediaQuery` and `importWhenPrefersMotion` are gone. One entry carries both halves:
229
+
230
+ ```js
231
+ registerManifest({
232
+ Map: { load: () => import('./Map.js'), mountStrategy: 'visible' },
233
+ });
234
+ ```
235
+
236
+ `readEagerTokens` and `<meta name="js-toolkit:eager">` are not ported — `data-mount` on the element says the same thing.
237
+
238
+ ### `<tk-name>` and arbitrary selectors are removed
239
+
240
+ Only plain and configured scoped `data-component` declarations are discovered. `data-component` still works on native elements.
241
+
242
+ ## Configuration and composition
243
+
244
+ ### `withExtraConfig()` is removed
245
+
246
+ `$config` merges along the prototype chain, so declare a class:
247
+
248
+ ```js
249
+ const Compact = withExtraConfig(Vendor, { options: { compact: Boolean } }); // [!code --]
250
+ ```
251
+
252
+ ```js
253
+ registerComponent(
254
+ // [!code ++]
255
+ class extends Vendor {
256
+ // [!code ++]
257
+ static config = { name: 'CompactVendor', options: { compact: Boolean } }; // [!code ++]
258
+ }, // [!code ++]
259
+ ); // [!code ++]
260
+ ```
261
+
262
+ `refs`, `options` and `components` merge; scalar keys stay overridable by the most derived class.
263
+
264
+ ### `withGroup` is removed
265
+
266
+ Use `provideRootContext()` for page state, and `createGroup()` with provide/inject for a scoped set of peers. See [Shared state](../going-further/sharing-state.md).
267
+
268
+ ### `defineFeatures()` is removed
269
+
270
+ Breakpoints are set with `setBreakpoints()`. The attribute names and the prefix are not configurable.
271
+
272
+ ## Services
273
+
274
+ ### `LoadService` is not ported
275
+
276
+ ### Props are flat
277
+
278
+ The grouped objects are gone, and so are the derived fields.
279
+
280
+ ```js
281
+ scrolled({ y, changed, direction, max, progress }) {} // [!code --]
282
+ scrolled({ y, deltaY, maxY, progressY, directionY, isScrolling }) {} // [!code ++]
283
+ ```
284
+
285
+ - `lastX` is `x - deltaX`; `changedX` is `deltaX !== 0`.
286
+ - `directionX` and `directionY` are `-1 | 0 | 1`, one signed value that multiplies.
287
+ - `ResizeService` keeps `width`, `height`, `ratio` and `orientation`, and drops `breakpoints` and `activeBreakpoints`.
288
+ - `DragService` drops `isGrabbing`, `hasInertia`, `target` and `props.MODES`, fixes the `dragTreshold` spelling, and gains an `idle` mode.
289
+ - `PointerService` uses pointer events only and follows one `pointerId` at a time.
290
+ - **Every prop field is `readonly`, and the props object belongs to its service.** Use `{ ...props }` to keep one.
291
+
292
+ ### Services are scoped to a target
293
+
294
+ ```js
295
+ useScroll(); // the document element
296
+ useWindowScroll(); // the same, named
297
+ useScroll(this.$refs.panel); // a region
298
+ ```
299
+
300
+ `useKey()` takes a target too, which is what removes the `hasFocus` bookkeeping a document-only service forced on a consumer. Its named key booleans are resolved from `KeyboardEvent.key` rather than the deprecated `keyCode`, and `triggered` now counts repeats of **one** key.
301
+
302
+ ### A mixin never occupies a lifecycle hook
303
+
304
+ `withRaf`, `withScroll` and friends override `$mount()`/`$unmount()`, not `mounted()`. A class that mixes a service in and writes its own `mounted()` **without** `super.mounted()` still subscribes.
305
+
306
+ `hook` options are gone: one method name per mixin, and it is the name of the service. Any other target is an explicit `subscribe()` in `mounted()`.
307
+
308
+ ## Scheduling and animation
309
+
310
+ ### One scheduler replaces three
311
+
312
+ `domScheduler`, the `RafService` loop, `SmartQueue` and the view-transition scheduler are one frame-aligned scheduler. `this.$read()` and `this.$write()` tie tasks to the instance.
313
+
314
+ **`afterWrite` is removed.** rAF callbacks run before style, layout and paint, so no phase inside the frame can read post-layout geometry. Measure in the next frame's `read` phase, or use a `ResizeObserver`.
315
+
316
+ ### `tween` and `animate` are not shipped
317
+
318
+ Time-based playback, stagger, sequencing, morphing and text splitting move to a separate `ui-animation` package, with Motion as declarative components and GSAP as a lifecycle-and-scoping decorator.
319
+
320
+ `exit`, `layout` and `layoutId` are not an engine's job — native view transitions solve them, and [`viewTransition()`](../../api/scheduler/viewTransition.md) is in core.
321
+
322
+ What was promoted into core instead: `transition` with `enterTransition` and `leaveTransition`, the easing functions, `spring()` and `smoothTo()`.
323
+
324
+ ### `damp()` takes the elapsed time
325
+
326
+ ```js
327
+ damp(current, target, 0.1); // [!code --]
328
+ damp(current, target, 0.1, delta); // [!code ++]
329
+ ```
330
+
331
+ `factor` is the fraction of the gap that closes per reference frame, which makes it stable for every value a caller can pass. Decay is expressed in time, not in frames.
332
+
333
+ ### `scrollTo()` splits in two
334
+
335
+ `scrollPosition()` measures and returns; `scrollTo()` calls it and moves. A carousel that asks which slide is nearest no longer has to scroll to find out.
336
+
337
+ ## Diagnostics
338
+
339
+ `EVENTS.error`, `ToolkitErrorDetail` and `ToolkitErrorStage` are removed with **no alias**:
340
+
341
+ ```js
342
+ document.addEventListener(EVENTS.error, …); // [!code --]
343
+ document.addEventListener(EVENTS.diagnostic, …); // [!code ++]
344
+ ```
345
+
346
+ The detail now carries `severity`, `code`, `message`, an optional `component`, and — for an error only — the original caught value as `error`. See [Diagnostics](../going-further/handling-diagnostics.md).
347
+
348
+ ## What is not promoted to core
349
+
350
+ `Action`, `SafeAction`, `Fetch`, `Transition` and the `Data*` family stay out of core. Core keeps general primitives only; those components belong to `@studiometa/ui`.
351
+
352
+ ## Removal checklist
353
+
354
+ | Removed | Replacement |
355
+ | --------------------------------- | ---------------------------------------------- |
356
+ | `$parent`, `$children`, `$root` | `$closest()`, `$query()`, `$watchChildren()` |
357
+ | `createApp()` | `registerComponent()` / `registerComponents()` |
358
+ | `$update()` | nothing — refs are live |
359
+ | `updated()` | `option<Name>Changed()`, `watchAttributes()` |
360
+ | `config.emits` | the `$emits` props type |
361
+ | `withExtraConfig()` | a subclass |
362
+ | `withGroup` | `provideRootContext()`, `createGroup()` |
363
+ | `withResponsiveOptions` | nothing — every option is responsive |
364
+ | `withMountWhenInView` and friends | mount strategies |
365
+ | `data-load`, `loadStrategy` | `data-mount` |
366
+ | the `importWhen*` helpers | `registerManifest()` entries |
367
+ | `defineFeatures()` | `setBreakpoints()` |
368
+ | `LoadService` | — |
369
+ | `domScheduler`, `SmartQueue` | `defaultScheduler` |
370
+ | `afterWrite` | the next frame's `read`, or a `ResizeObserver` |
371
+ | `tween`, `animate` | the `ui-animation` package |
372
+ | `EVENTS.error` | `EVENTS.diagnostic` |
373
+ | `<tk-name>`, arbitrary selectors | `data-component` |
@@ -0,0 +1,98 @@
1
+ # CSS
2
+
3
+ ```js
4
+ import { matrix, transform } from '@studiometa/js-toolkit/utils';
5
+ ```
6
+
7
+ ## Transforms
8
+
9
+ ### transform
10
+
11
+ ```ts
12
+ transform(props: TransformProps): string
13
+ ```
14
+
15
+ ```js
16
+ import { transform } from '@studiometa/js-toolkit/utils';
17
+
18
+ transform({ x: 10, y: 20, scale: 1.5, rotate: 45 });
19
+ ```
20
+
21
+ Builds a `transform` value from named parts, so a component composes a transform instead of assembling a string. `TransformProps` takes `x`, `y`, `z`, `rotate`, `rotateX`, `rotateY`, `rotateZ`, `scale`, `scaleX`, `scaleY`, `scaleZ`, `skew` and the rest of the family.
22
+
23
+ **The order is fixed by `TRANSFORM_PROPS`, not by the object.** Transform functions do not commute, so two components building "the same" transform from differently-ordered literals must still get the same matrix.
24
+
25
+ ### matrix
26
+
27
+ ```ts
28
+ matrix(props?: MatrixProps): string
29
+ ```
30
+
31
+ ```js
32
+ import { matrix } from '@studiometa/js-toolkit/utils';
33
+
34
+ matrix({ scaleX: 2, translateX: 10 });
35
+ ```
36
+
37
+ A `matrix()` string. Reach for it when a value has to be interpolated as a matrix rather than as separate functions.
38
+
39
+ ### TRANSFORM_PROPS
40
+
41
+ ```ts
42
+ const TRANSFORM_PROPS: readonly (keyof TransformProps)[];
43
+ ```
44
+
45
+ The ordered list of keys `transform()` reads.
46
+
47
+ ## Measuring
48
+
49
+ ### getOffsetSizes
50
+
51
+ ```ts
52
+ getOffsetSizes(element: HTMLElement): { x, y, width, height, top, right, bottom, left }
53
+ ```
54
+
55
+ ```js
56
+ import { getOffsetSizes } from '@studiometa/js-toolkit/utils';
57
+
58
+ const box = getOffsetSizes(document.body);
59
+ ```
60
+
61
+ The element's box from its **offset** properties rather than from `getBoundingClientRect()` — so a transform the component itself applied does not move the measurement.
62
+
63
+ That is exactly what a drag or a tilt needs: the layout box is the frame of reference, and the transform is the output.
64
+
65
+ **It is a layout read**
66
+
67
+ Call it from the `read` phase — [`$read()`](../api/instance-methods.md#read-and-write) — so it batches with every other measurement of the frame.
68
+
69
+ ## Applying
70
+
71
+ ### setClassesOrStyles
72
+
73
+ ```ts
74
+ setClassesOrStyles(
75
+ el: HTMLElement,
76
+ value: string | string[] | Partial<CSSStyleDeclaration> | undefined,
77
+ method?: 'add' | 'remove',
78
+ ): void
79
+ ```
80
+
81
+ ```js
82
+ import { setClassesOrStyles } from '@studiometa/js-toolkit/utils';
83
+
84
+ const el = document.body;
85
+
86
+ setClassesOrStyles(el, 'is-active'); // a class
87
+ setClassesOrStyles(el, ['is-active', 'is-open']); // several
88
+ setClassesOrStyles(el, { opacity: '0' }); // inline styles
89
+ setClassesOrStyles(el, 'is-active', 'remove'); // undo it
90
+ ```
91
+
92
+ Applies a value that may be **either** classes or inline styles, which is what lets [`transition()`](transitions.md) take one option in both forms.
93
+
94
+ An `undefined` value does nothing, so a caller with an optional state does not have to branch.
95
+
96
+ ## What is not here
97
+
98
+ `addClass`, `removeClass`, `toggleClass`, `addStyle`, `removeStyle` and `animate` are not shipped. `el.classList` and `el.style` say the first five, and time-based playback belongs to the separate `ui-animation` package.
@@ -0,0 +1,54 @@
1
+ # DOM
2
+
3
+ ```js
4
+ import { createElement, selectorFor } from '@studiometa/js-toolkit/utils';
5
+ ```
6
+
7
+ ## createElement
8
+
9
+ ```ts
10
+ createElement(tag?, children?): HTMLElement
11
+ createElement(tag?, attributes?, children?): HTMLElement
12
+ ```
13
+
14
+ ```js
15
+ import { createElement } from '@studiometa/js-toolkit/utils';
16
+
17
+ createElement('div');
18
+ createElement('p', 'Hello');
19
+ createElement('ul', [createElement('li', 'One'), createElement('li', 'Two')]);
20
+ createElement('button', { class: 'btn', data: { component: 'Action' } }, 'Send');
21
+ ```
22
+
23
+ **Parameters**
24
+
25
+ - `tag` — defaults to `'div'`, and the return type follows it: `createElement('input')` gives an `HTMLInputElement`.
26
+ - `attributes` — plain attributes, plus a `data` object whose keys become `data-*`.
27
+ - `children` — a string, a `Node`, or an array of either.
28
+
29
+ The `data` key is why this exists rather than three lines of `document.createElement`: building an element that carries `data-component` and a few `data-option-*` is the common case, and spelling each `setAttribute()` out loses the shape.
30
+
31
+ ## selectorFor
32
+
33
+ ```ts
34
+ selectorFor(name: string): string
35
+ ```
36
+
37
+ ```js
38
+ import { selectorFor } from '@studiometa/js-toolkit/utils';
39
+
40
+ selectorFor('Dialog');
41
+ ```
42
+
43
+ The CSS selector that matches every element declaring a component name — **including the responsive `data-component:<breakpoint>` spellings**.
44
+
45
+ It is the **one place** that writes the name-to-selector contract, which is why it is public: a consumer that queries for components must match what the registry matches, and a hand-written `[data-component="X"]` misses the scoped declarations.
46
+
47
+ **It over-matches on purpose**
48
+
49
+ A responsive declaration that is not active still matches the selector. That is why the four [instance lookups](../api/registry/getInstances.md) read the element's instance map afterwards: **a matching element with no instance is skipped, and that is the whole narrowing.**
50
+
51
+ ## See also
52
+
53
+ - [CSS](css.md) — `getOffsetSizes`, `transform`, `matrix`
54
+ - [`swap()`](../api/dom/swap.md) — replacing content, with the framework waiting