@wardic/dom 0.0.0-stage → 1.0.0-rc.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 (285) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +8 -2
  3. package/THIRD_PARTY_NOTICES.md +145 -0
  4. package/dist/Appear.d.ts +24 -0
  5. package/dist/Appear.d.ts.map +1 -0
  6. package/dist/Appear.js +25 -0
  7. package/dist/Appear.js.map +1 -0
  8. package/dist/Color.d.ts +14 -0
  9. package/dist/Color.d.ts.map +1 -0
  10. package/dist/Color.js +16 -0
  11. package/dist/Color.js.map +1 -0
  12. package/dist/DomAnnouncer.d.ts +13 -0
  13. package/dist/DomAnnouncer.d.ts.map +1 -0
  14. package/dist/DomAnnouncer.js +14 -0
  15. package/dist/DomAnnouncer.js.map +1 -0
  16. package/dist/DomClock.d.ts +11 -0
  17. package/dist/DomClock.d.ts.map +1 -0
  18. package/dist/DomClock.js +12 -0
  19. package/dist/DomClock.js.map +1 -0
  20. package/dist/DomDefaultTransition.d.ts +12 -0
  21. package/dist/DomDefaultTransition.d.ts.map +1 -0
  22. package/dist/DomDefaultTransition.js +13 -0
  23. package/dist/DomDefaultTransition.js.map +1 -0
  24. package/dist/DomInput.d.ts +13 -0
  25. package/dist/DomInput.d.ts.map +1 -0
  26. package/dist/DomInput.js +15 -0
  27. package/dist/DomInput.js.map +1 -0
  28. package/dist/DomInterpolators.d.ts +13 -0
  29. package/dist/DomInterpolators.d.ts.map +1 -0
  30. package/dist/DomInterpolators.js +14 -0
  31. package/dist/DomInterpolators.js.map +1 -0
  32. package/dist/DomKeyRules.d.ts +13 -0
  33. package/dist/DomKeyRules.d.ts.map +1 -0
  34. package/dist/DomKeyRules.js +14 -0
  35. package/dist/DomKeyRules.js.map +1 -0
  36. package/dist/DomPositionalKeys.d.ts +13 -0
  37. package/dist/DomPositionalKeys.d.ts.map +1 -0
  38. package/dist/DomPositionalKeys.js +14 -0
  39. package/dist/DomPositionalKeys.js.map +1 -0
  40. package/dist/DomProbe.d.ts +13 -0
  41. package/dist/DomProbe.d.ts.map +1 -0
  42. package/dist/DomProbe.js +14 -0
  43. package/dist/DomProbe.js.map +1 -0
  44. package/dist/DomProjectionSystem.d.ts +28 -0
  45. package/dist/DomProjectionSystem.d.ts.map +1 -0
  46. package/dist/DomProjectionSystem.js +41 -0
  47. package/dist/DomProjectionSystem.js.map +1 -0
  48. package/dist/DomRenderer.d.ts +13 -0
  49. package/dist/DomRenderer.d.ts.map +1 -0
  50. package/dist/DomRenderer.js +15 -0
  51. package/dist/DomRenderer.js.map +1 -0
  52. package/dist/FlushGate.d.ts +48 -0
  53. package/dist/FlushGate.d.ts.map +1 -0
  54. package/dist/FlushGate.js +62 -0
  55. package/dist/FlushGate.js.map +1 -0
  56. package/dist/MeasuredPair.d.ts +14 -0
  57. package/dist/MeasuredPair.d.ts.map +1 -0
  58. package/dist/MeasuredPair.js +16 -0
  59. package/dist/MeasuredPair.js.map +1 -0
  60. package/dist/OwnValues.d.ts +14 -0
  61. package/dist/OwnValues.d.ts.map +1 -0
  62. package/dist/OwnValues.js +15 -0
  63. package/dist/OwnValues.js.map +1 -0
  64. package/dist/ProjectionSystem.d.ts +34 -0
  65. package/dist/ProjectionSystem.d.ts.map +1 -0
  66. package/dist/ProjectionSystem.js +29 -0
  67. package/dist/ProjectionSystem.js.map +1 -0
  68. package/dist/ReorderController.d.ts +41 -0
  69. package/dist/ReorderController.d.ts.map +1 -0
  70. package/dist/ReorderController.js +44 -0
  71. package/dist/ReorderController.js.map +1 -0
  72. package/dist/Report.d.ts +12 -0
  73. package/dist/Report.d.ts.map +1 -0
  74. package/dist/Report.js +13 -0
  75. package/dist/Report.js.map +1 -0
  76. package/dist/ScrollOffset.d.ts +34 -0
  77. package/dist/ScrollOffset.d.ts.map +1 -0
  78. package/dist/ScrollOffset.js +42 -0
  79. package/dist/ScrollOffset.js.map +1 -0
  80. package/dist/Style.d.ts +15 -0
  81. package/dist/Style.d.ts.map +1 -0
  82. package/dist/Style.js +17 -0
  83. package/dist/Style.js.map +1 -0
  84. package/dist/Svg.d.ts +13 -0
  85. package/dist/Svg.d.ts.map +1 -0
  86. package/dist/Svg.js +14 -0
  87. package/dist/Svg.js.map +1 -0
  88. package/dist/Variables.d.ts +13 -0
  89. package/dist/Variables.d.ts.map +1 -0
  90. package/dist/Variables.js +14 -0
  91. package/dist/Variables.js.map +1 -0
  92. package/dist/index.d.ts +72 -0
  93. package/dist/index.d.ts.map +1 -0
  94. package/dist/index.js +60 -0
  95. package/dist/index.js.map +1 -0
  96. package/dist/internal/announcer.d.ts +50 -0
  97. package/dist/internal/announcer.d.ts.map +1 -0
  98. package/dist/internal/announcer.js +115 -0
  99. package/dist/internal/announcer.js.map +1 -0
  100. package/dist/internal/appear.d.ts +169 -0
  101. package/dist/internal/appear.d.ts.map +1 -0
  102. package/dist/internal/appear.js +499 -0
  103. package/dist/internal/appear.js.map +1 -0
  104. package/dist/internal/auto-scroll.d.ts +24 -0
  105. package/dist/internal/auto-scroll.d.ts.map +1 -0
  106. package/dist/internal/auto-scroll.js +124 -0
  107. package/dist/internal/auto-scroll.js.map +1 -0
  108. package/dist/internal/clock.d.ts +19 -0
  109. package/dist/internal/clock.d.ts.map +1 -0
  110. package/dist/internal/clock.js +39 -0
  111. package/dist/internal/clock.js.map +1 -0
  112. package/dist/internal/colors.d.ts +45 -0
  113. package/dist/internal/colors.d.ts.map +1 -0
  114. package/dist/internal/colors.js +193 -0
  115. package/dist/internal/colors.js.map +1 -0
  116. package/dist/internal/complex.d.ts +24 -0
  117. package/dist/internal/complex.d.ts.map +1 -0
  118. package/dist/internal/complex.js +28 -0
  119. package/dist/internal/complex.js.map +1 -0
  120. package/dist/internal/content-watch.d.ts +20 -0
  121. package/dist/internal/content-watch.d.ts.map +1 -0
  122. package/dist/internal/content-watch.js +76 -0
  123. package/dist/internal/content-watch.js.map +1 -0
  124. package/dist/internal/default-transition.d.ts +25 -0
  125. package/dist/internal/default-transition.d.ts.map +1 -0
  126. package/dist/internal/default-transition.js +41 -0
  127. package/dist/internal/default-transition.js.map +1 -0
  128. package/dist/internal/drag-defaults.d.ts +18 -0
  129. package/dist/internal/drag-defaults.d.ts.map +1 -0
  130. package/dist/internal/drag-defaults.js +38 -0
  131. package/dist/internal/drag-defaults.js.map +1 -0
  132. package/dist/internal/gate.d.ts +186 -0
  133. package/dist/internal/gate.d.ts.map +1 -0
  134. package/dist/internal/gate.js +453 -0
  135. package/dist/internal/gate.js.map +1 -0
  136. package/dist/internal/input.d.ts +41 -0
  137. package/dist/internal/input.d.ts.map +1 -0
  138. package/dist/internal/input.js +476 -0
  139. package/dist/internal/input.js.map +1 -0
  140. package/dist/internal/interpolators.d.ts +19 -0
  141. package/dist/internal/interpolators.d.ts.map +1 -0
  142. package/dist/internal/interpolators.js +30 -0
  143. package/dist/internal/interpolators.js.map +1 -0
  144. package/dist/internal/key-rules.d.ts +11 -0
  145. package/dist/internal/key-rules.d.ts.map +1 -0
  146. package/dist/internal/key-rules.js +244 -0
  147. package/dist/internal/key-rules.js.map +1 -0
  148. package/dist/internal/measure.d.ts +150 -0
  149. package/dist/internal/measure.d.ts.map +1 -0
  150. package/dist/internal/measure.js +278 -0
  151. package/dist/internal/measure.js.map +1 -0
  152. package/dist/internal/measured-pairs.d.ts +38 -0
  153. package/dist/internal/measured-pairs.d.ts.map +1 -0
  154. package/dist/internal/measured-pairs.js +251 -0
  155. package/dist/internal/measured-pairs.js.map +1 -0
  156. package/dist/internal/own-values.d.ts +35 -0
  157. package/dist/internal/own-values.d.ts.map +1 -0
  158. package/dist/internal/own-values.js +117 -0
  159. package/dist/internal/own-values.js.map +1 -0
  160. package/dist/internal/pass-ends.d.ts +21 -0
  161. package/dist/internal/pass-ends.d.ts.map +1 -0
  162. package/dist/internal/pass-ends.js +14 -0
  163. package/dist/internal/pass-ends.js.map +1 -0
  164. package/dist/internal/positional-keys.d.ts +16 -0
  165. package/dist/internal/positional-keys.d.ts.map +1 -0
  166. package/dist/internal/positional-keys.js +21 -0
  167. package/dist/internal/positional-keys.js.map +1 -0
  168. package/dist/internal/probe.d.ts +10 -0
  169. package/dist/internal/probe.d.ts.map +1 -0
  170. package/dist/internal/probe.js +117 -0
  171. package/dist/internal/probe.js.map +1 -0
  172. package/dist/internal/projection-defaults.d.ts +34 -0
  173. package/dist/internal/projection-defaults.d.ts.map +1 -0
  174. package/dist/internal/projection-defaults.js +21 -0
  175. package/dist/internal/projection-defaults.js.map +1 -0
  176. package/dist/internal/projection.d.ts +529 -0
  177. package/dist/internal/projection.d.ts.map +1 -0
  178. package/dist/internal/projection.js +4990 -0
  179. package/dist/internal/projection.js.map +1 -0
  180. package/dist/internal/renderer.d.ts +86 -0
  181. package/dist/internal/renderer.d.ts.map +1 -0
  182. package/dist/internal/renderer.js +616 -0
  183. package/dist/internal/renderer.js.map +1 -0
  184. package/dist/internal/reorder.d.ts +159 -0
  185. package/dist/internal/reorder.d.ts.map +1 -0
  186. package/dist/internal/reorder.js +437 -0
  187. package/dist/internal/reorder.js.map +1 -0
  188. package/dist/internal/report.d.ts +30 -0
  189. package/dist/internal/report.d.ts.map +1 -0
  190. package/dist/internal/report.js +60 -0
  191. package/dist/internal/report.js.map +1 -0
  192. package/dist/internal/require-global.d.ts +11 -0
  193. package/dist/internal/require-global.d.ts.map +1 -0
  194. package/dist/internal/require-global.js +31 -0
  195. package/dist/internal/require-global.js.map +1 -0
  196. package/dist/internal/reveal.d.ts +16 -0
  197. package/dist/internal/reveal.d.ts.map +1 -0
  198. package/dist/internal/reveal.js +66 -0
  199. package/dist/internal/reveal.js.map +1 -0
  200. package/dist/internal/runner.d.ts +21 -0
  201. package/dist/internal/runner.d.ts.map +1 -0
  202. package/dist/internal/runner.js +48 -0
  203. package/dist/internal/runner.js.map +1 -0
  204. package/dist/internal/scale-correction.d.ts +80 -0
  205. package/dist/internal/scale-correction.d.ts.map +1 -0
  206. package/dist/internal/scale-correction.js +227 -0
  207. package/dist/internal/scale-correction.js.map +1 -0
  208. package/dist/internal/scroll.d.ts +35 -0
  209. package/dist/internal/scroll.d.ts.map +1 -0
  210. package/dist/internal/scroll.js +244 -0
  211. package/dist/internal/scroll.js.map +1 -0
  212. package/dist/internal/scrollers.d.ts +35 -0
  213. package/dist/internal/scrollers.d.ts.map +1 -0
  214. package/dist/internal/scrollers.js +38 -0
  215. package/dist/internal/scrollers.js.map +1 -0
  216. package/dist/internal/starting-style.d.ts +141 -0
  217. package/dist/internal/starting-style.d.ts.map +1 -0
  218. package/dist/internal/starting-style.js +300 -0
  219. package/dist/internal/starting-style.js.map +1 -0
  220. package/dist/internal/svg.d.ts +60 -0
  221. package/dist/internal/svg.d.ts.map +1 -0
  222. package/dist/internal/svg.js +257 -0
  223. package/dist/internal/svg.js.map +1 -0
  224. package/dist/internal/variables.d.ts +45 -0
  225. package/dist/internal/variables.d.ts.map +1 -0
  226. package/dist/internal/variables.js +92 -0
  227. package/dist/internal/variables.js.map +1 -0
  228. package/package.json +65 -4
  229. package/src/Appear.ts +45 -0
  230. package/src/Color.ts +24 -0
  231. package/src/DomAnnouncer.ts +22 -0
  232. package/src/DomClock.ts +13 -0
  233. package/src/DomDefaultTransition.ts +16 -0
  234. package/src/DomInput.ts +22 -0
  235. package/src/DomInterpolators.ts +16 -0
  236. package/src/DomKeyRules.ts +17 -0
  237. package/src/DomPositionalKeys.ts +16 -0
  238. package/src/DomProbe.ts +15 -0
  239. package/src/DomProjectionSystem.ts +44 -0
  240. package/src/DomRenderer.ts +26 -0
  241. package/src/FlushGate.ts +81 -0
  242. package/src/MeasuredPair.ts +15 -0
  243. package/src/OwnValues.ts +19 -0
  244. package/src/ProjectionSystem.ts +51 -0
  245. package/src/ReorderController.ts +72 -0
  246. package/src/Report.ts +17 -0
  247. package/src/ScrollOffset.ts +54 -0
  248. package/src/Style.ts +37 -0
  249. package/src/Svg.ts +21 -0
  250. package/src/Variables.ts +17 -0
  251. package/src/index.ts +106 -0
  252. package/src/internal/announcer.ts +132 -0
  253. package/src/internal/appear.ts +739 -0
  254. package/src/internal/auto-scroll.ts +176 -0
  255. package/src/internal/clock.ts +45 -0
  256. package/src/internal/colors.ts +258 -0
  257. package/src/internal/complex.ts +29 -0
  258. package/src/internal/content-watch.ts +84 -0
  259. package/src/internal/culori.d.ts +58 -0
  260. package/src/internal/default-transition.ts +50 -0
  261. package/src/internal/drag-defaults.ts +54 -0
  262. package/src/internal/gate.ts +593 -0
  263. package/src/internal/input.ts +579 -0
  264. package/src/internal/interpolators.ts +33 -0
  265. package/src/internal/key-rules.ts +357 -0
  266. package/src/internal/measure.ts +357 -0
  267. package/src/internal/measured-pairs.ts +297 -0
  268. package/src/internal/own-values.ts +166 -0
  269. package/src/internal/pass-ends.ts +23 -0
  270. package/src/internal/positional-keys.ts +24 -0
  271. package/src/internal/probe.ts +176 -0
  272. package/src/internal/projection-defaults.ts +45 -0
  273. package/src/internal/projection.ts +5999 -0
  274. package/src/internal/renderer.ts +646 -0
  275. package/src/internal/reorder.ts +604 -0
  276. package/src/internal/report.ts +69 -0
  277. package/src/internal/require-global.ts +46 -0
  278. package/src/internal/reveal.ts +69 -0
  279. package/src/internal/runner.ts +64 -0
  280. package/src/internal/scale-correction.ts +310 -0
  281. package/src/internal/scroll.ts +356 -0
  282. package/src/internal/scrollers.ts +51 -0
  283. package/src/internal/starting-style.ts +396 -0
  284. package/src/internal/svg.ts +300 -0
  285. package/src/internal/variables.ts +145 -0
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Variable values in the DOM (#55, ADR-0035 *Amendment (#55)*; CONTEXT.md): a value that is wholly a
3
+ * `var(--name)`, with or without a fallback, stands for that custom property's value on the element.
4
+ * `variableValues(element)` is a Key rule bound to one element, which a binding adds to each leg it
5
+ * builds (`InterpolatorRegistry.withKeyRules`). Motion's rule (`getVariableValue`,
6
+ * css-variables-conversion.ts:18-53, and `DOMKeyframesResolver.readKeyframes` at 16c6122):
7
+ *
8
+ * - Either end that is a Variable value is resolved against the element, once, when the leg is
9
+ * built: the custom property's computed value, else its fallback, following a fallback that is
10
+ * itself a Variable value up to 4 deep. A numeric result is a number.
11
+ * - The resolved pair goes on through `next`, so the rules after this one still apply (`"none"` →
12
+ * `var(--shadow)` grows from its Animatable none), then blends by value.
13
+ * - The leg's last frame writes the target as written, so at rest the element follows the custom
14
+ * property again; a change mid-leg is followed from there.
15
+ * - A Variable value that doesn't resolve leaves the pair as written: the rule declines, and it
16
+ * switches as a Discrete pair, as Motion's does. A `var()` inside a larger value is text (#158).
17
+ *
18
+ * Client-only: it reads the element's computed style, after mount (ADR-0021).
19
+ *
20
+ * @module
21
+ */
22
+ import type * as InterpolatorRegistry from "@wardic/core/InterpolatorRegistry";
23
+ import * as Option from "effect/Option";
24
+ /** A value a key blends: a number or a string. */
25
+ /** What a Variable value resolves to: a number or a string. */
26
+ type Value = number | string;
27
+ /** Whether `value` is a Variable value: a string that's wholly a `var()`. */
28
+ export declare const isVariableValue: (value: unknown) => value is string;
29
+ /**
30
+ * What a Variable value stands for on `element`: its custom property's computed value, else its
31
+ * fallback, a fallback that is itself a Variable value followed up to 4 deep. `None` when nothing
32
+ * resolves. Reads the element's computed style.
33
+ */
34
+ export declare const resolveVariable: (element: Element, value: string) => Option.Option<Value>;
35
+ /**
36
+ * The Key rule for `element`'s Variable values: a pair with one at either end blends what they resolve
37
+ * to on `element`, through the rules after it and then by value, and lands on its target as written. It
38
+ * declines a pair with none, and one that doesn't resolve.
39
+ *
40
+ * @example
41
+ * yield* buildLegs.pipe(InterpolatorRegistry.withKeyRules([Variables.values(element)]))
42
+ */
43
+ export declare const variableValues: (element: Element) => InterpolatorRegistry.KeyRule;
44
+ export {};
45
+ //# sourceMappingURL=variables.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"variables.d.ts","sourceRoot":"","sources":["../../src/internal/variables.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,KAAK,KAAK,oBAAoB,MAAM,mCAAmC,CAAA;AAK9E,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAIvC,kDAAkD;AAClD,+DAA+D;AAC/D,KAAK,KAAK,GAAG,MAAM,GAAG,MAAM,CAAA;AA4C5B,6EAA6E;AAE7E,eAAO,MAAM,eAAe,UAAW,OAAO,KAAG,KAAK,IAAI,MAAoE,CAAA;AAK9H;;;;GAIG;AACH,eAAO,MAAM,eAAe,YAAa,OAAO,SAAS,MAAM,KAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAiC,CAAA;AAuCtH;;;;;;;GAOG;AAEH,eAAO,MAAM,cAAc,YAAa,OAAO,KAAG,oBAAoB,CAAC,OAQrE,CAAA"}
@@ -0,0 +1,92 @@
1
+ import * as Arr from "effect/Array";
2
+ import * as Bool from "effect/Boolean";
3
+ import * as Effect from "effect/Effect";
4
+ import { pipe } from "effect/Function";
5
+ import * as Option from "effect/Option";
6
+ import * as Predicate from "effect/Predicate";
7
+ import * as Str from "effect/String";
8
+ /** A Variable value's custom property, and its fallback when it has one (Motion's `parseCSSVariable`). */
9
+ const PARTS_RE = /^var\(\s*(--[\w-]+)\s*(?:,\s*([\s\S]*?))?\s*\)$/;
10
+ /** The cheap first check: a string that starts as a `var()` does. */
11
+ const VAR_START_RE = /^\s*var\(/;
12
+ /** How a character moves the bracket depth. */
13
+ const depthStep = (ch) => Bool.match(ch === "(", { onTrue: () => 1, onFalse: () => Bool.match(ch === ")", { onTrue: () => -1, onFalse: () => 0 }) });
14
+ /** Brackets that close as they open: a fallback that is one value, not the rest of a longer string. */
15
+ const isBalanced = (text) => {
16
+ const end = Arr.reduce(Str.split(text, ""), 0, (depth, ch) => Bool.match(depth < 0, { onTrue: () => depth, onFalse: () => depth + depthStep(ch) }));
17
+ return end === 0;
18
+ };
19
+ /**
20
+ * A Variable value's parts, or `None` for any other value: `var(--name)` or `var(--name, fallback)`,
21
+ * the fallback's brackets balanced, at any depth of nested `var()`s (a pattern alone stops at one).
22
+ * So `var(--a, 1px) var(--b)` isn't one: two values side by side.
23
+ */
24
+ const partsOf = (value) => {
25
+ // Asked of a string end of every key, each leg (#460): one that doesn't start as one builds nothing.
26
+ if (!VAR_START_RE.test(value))
27
+ return Option.none();
28
+ return pipe(Option.fromNullishOr(PARTS_RE.exec(Str.trim(value))), Option.map(([, name, fallback]) => ({ name, fallback: Option.map(Option.fromUndefinedOr(fallback), Str.trim) })), Option.filter((parts) => Option.match(parts.fallback, { onNone: () => true, onSome: isBalanced })));
29
+ };
30
+ /** How deep a fallback that is itself a Variable value is followed (Motion's `maxDepth`). */
31
+ const MAX_DEPTH = 4;
32
+ /** A numeric string, which a resolved value becomes a number from (Motion's `isNumericalString`). */
33
+ const NUMERIC_RE = /^-?\d*\.?\d+(?:e[-+]?\d+)?$/i;
34
+ /** Whether `value` is a Variable value: a string that's wholly a `var()`. */
35
+ // CONTEXT.md's Variable value.
36
+ export const isVariableValue = (value) => Predicate.isString(value) && Option.isSome(partsOf(value));
37
+ /** A resolved value as a key blends it: a number when it reads as one, else the string. */
38
+ const valueOf = (raw) => Bool.match(NUMERIC_RE.test(raw), { onTrue: () => Number.parseFloat(raw), onFalse: () => raw });
39
+ /**
40
+ * What a Variable value stands for on `element`: its custom property's computed value, else its
41
+ * fallback, a fallback that is itself a Variable value followed up to 4 deep. `None` when nothing
42
+ * resolves. Reads the element's computed style.
43
+ */
44
+ export const resolveVariable = (element, value) => resolveAt(element, value, 1);
45
+ /** {@link resolveVariable} at `depth`, following a fallback that's itself a Variable value. */
46
+ // #618 (F7): the depth counter was the public function's third parameter.
47
+ const resolveAt = (element, value, depth) => {
48
+ if (depth > MAX_DEPTH)
49
+ return Option.none();
50
+ return Option.flatMap(partsOf(value), ({ name, fallback }) => {
51
+ const own = Str.trim(getComputedStyle(element).getPropertyValue(name));
52
+ if (Str.isNonEmpty(own))
53
+ return Option.some(valueOf(own));
54
+ return pipe(fallback, Option.filter(Str.isNonEmpty), Option.flatMap((rest) => Bool.match(isVariableValue(rest), {
55
+ onTrue: () => resolveAt(element, rest, depth + 1),
56
+ onFalse: () => Option.some(valueOf(rest)),
57
+ })));
58
+ });
59
+ };
60
+ /** An end as the leg blends it: a Variable value resolved on `element`, any other value as it is. */
61
+ const endOf = (element, value) => Bool.match(isVariableValue(value), {
62
+ onTrue: () => resolveVariable(element, value),
63
+ onFalse: () => Option.some(value),
64
+ });
65
+ /**
66
+ * A blend that writes its target as written on the run's last Frame: a Variable value rests as the
67
+ * `var()` itself, so the element follows its custom property again. Per frame: a statement `if`.
68
+ */
69
+ const landOn = (blend, to) => (t, done) => {
70
+ if (done)
71
+ return to;
72
+ return blend(t, done);
73
+ };
74
+ /**
75
+ * The Key rule for `element`'s Variable values: a pair with one at either end blends what they resolve
76
+ * to on `element`, through the rules after it and then by value, and lands on its target as written. It
77
+ * declines a pair with none, and one that doesn't resolve.
78
+ *
79
+ * @example
80
+ * yield* buildLegs.pipe(InterpolatorRegistry.withKeyRules([Variables.values(element)]))
81
+ */
82
+ // #55.
83
+ export const variableValues = (element) => ({
84
+ name: "variable values",
85
+ blend: (key, from, to, _resolve, next) => {
86
+ // Per key, each leg (#460): a statement.
87
+ if (!isVariableValue(from) && !isVariableValue(to))
88
+ return Option.none();
89
+ return Option.map(Option.all([endOf(element, from), endOf(element, to)]), ([a, b]) => Effect.map(next(key, a, b), (blend) => landOn(blend, to)));
90
+ },
91
+ });
92
+ //# sourceMappingURL=variables.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"variables.js","sourceRoot":"","sources":["../../src/internal/variables.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,67 @@
1
1
  {
2
2
  "name": "@wardic/dom",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "1.0.0-rc.2",
4
+ "description": "The browser environment for Wardic: its clock, renderer, input, probe and projection system, as Effect Layers.",
5
+ "keywords": [
6
+ "animation",
7
+ "motion",
8
+ "dom",
9
+ "effect"
10
+ ],
11
+ "homepage": "https://wardic.dev",
12
+ "bugs": "https://github.com/wardiclabs/wardic/issues",
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "git+https://github.com/wardiclabs/wardic.git",
16
+ "directory": "packages/dom"
17
+ },
18
+ "license": "MIT",
19
+ "author": {
20
+ "name": "The Wardic contributors",
21
+ "email": "hello@wardic.dev",
22
+ "url": "https://wardic.dev"
23
+ },
24
+ "files": [
25
+ "dist/**/*.js",
26
+ "dist/**/*.d.ts",
27
+ "dist/**/*.map",
28
+ "src",
29
+ "README.md",
30
+ "LICENSE",
31
+ "THIRD_PARTY_NOTICES.md"
32
+ ],
33
+ "type": "module",
34
+ "sideEffects": false,
35
+ "publishConfig": {
36
+ "access": "public"
37
+ },
38
+ "exports": {
39
+ "./package.json": "./package.json",
40
+ ".": {
41
+ "@wardic/source": "./src/index.ts",
42
+ "types": "./dist/index.d.ts",
43
+ "default": "./dist/index.js"
44
+ },
45
+ "./*": {
46
+ "@wardic/source": "./src/*.ts",
47
+ "types": "./dist/*.d.ts",
48
+ "default": "./dist/*.js"
49
+ },
50
+ "./internal/*": null
51
+ },
52
+ "scripts": {
53
+ "build": "../../node_modules/typescript-7/bin/tsc --build",
54
+ "typecheck": "../../node_modules/typescript-7/bin/tsc --build",
55
+ "typecheck:tests": "../../node_modules/typescript-7/bin/tsc -p tsconfig.test.json"
56
+ },
57
+ "dependencies": {
58
+ "@wardic/core": "1.0.0-rc.2",
59
+ "culori": "^4.0.2"
60
+ },
61
+ "peerDependencies": {
62
+ "effect": "^4.1.1"
63
+ },
64
+ "devDependencies": {
65
+ "@wardic/test": "1.0.0-rc.2"
66
+ }
67
+ }
package/src/Appear.ts ADDED
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Appear animations: a mount animation a server renders as CSS, played from the first paint, before any
3
+ * code runs, which the engine takes over at mount from where it has got to. The DOM's half, for any
4
+ * binding:
5
+ * - **On a server:** `keyframes` samples an element's spec, its mount animation built with core's
6
+ * machines, into one `@keyframes` rule, cached across requests. A render's `sheet` gives each element a
7
+ * slot, whose `animation` goes in its inline style, and writes the head's `<style>` once every slot's
8
+ * timing is defined.
9
+ * - **At mount:** `find` the element's animation, check it `matches` the client's own spec, start the run
10
+ * `elapsedOf` it in (`Machine.startAt`), and `release` the element in the task that writes the engine's
11
+ * first frame.
12
+ *
13
+ * @example
14
+ * import * as Appear from "@wardic/dom/Appear"
15
+ *
16
+ * // On a server, a sheet a render:
17
+ * const render = Appear.sheet()
18
+ * const slot = render.slot()
19
+ * slot.define({ spec, delay: 0 }) // `slot.animation` goes in the element's style, `render.css()` in the head
20
+ * // At mount:
21
+ * const elapsed = Option.map(Appear.find(element), Appear.elapsedOf)
22
+ */
23
+ // #48, ADR-0044: the **Handoff**. `@wardic/dom/Appear` (ADR-0041).
24
+ export {
25
+ adoptChunks,
26
+ animationOf,
27
+ CHUNK_ATTRIBUTE,
28
+ chunkStyle,
29
+ delayOf,
30
+ elapsedOf,
31
+ find,
32
+ keyframes,
33
+ type Keyframes,
34
+ matches,
35
+ MAX_SECONDS,
36
+ nameOf,
37
+ pending,
38
+ type Play,
39
+ PREFIX,
40
+ release,
41
+ sheet,
42
+ type Sheet,
43
+ type Slot,
44
+ type Spec,
45
+ } from "./internal/appear.ts"
package/src/Color.ts ADDED
@@ -0,0 +1,24 @@
1
+ /**
2
+ * CSS colours: `parse` reads a colour string, `format` writes one, `interpolator` blends two in a colour
3
+ * space, and `TOKEN` finds a colour inside a longer value, a shadow's say. A hex, `rgb()`, `hsl()` and the
4
+ * named colours are colours from the start; `registerSpaces` adds every other CSS colour space, so
5
+ * `oklch()` and `lab()` are colours too, and `interpolator("oklch")` can blend in it.
6
+ *
7
+ * @example
8
+ * import * as Color from "@wardic/dom/Color"
9
+ *
10
+ * Color.parse("#bf616a") // Some({ mode: "rgb", r: 0.749, g: 0.38, b: 0.416 })
11
+ * Color.format({ mode: "rgb", r: 1, g: 0.5, b: 0 }) // "rgb(255, 128, 0)"
12
+ */
13
+ // `@wardic/dom/Color` (#132, ADR-0041): a colour Interpolator in a culori mode, the DOM's own (`css`,
14
+ // sRGB), its `parse` and `format`, and its token (ADR-0024, ADR-0026); `registerSpaces` (#511).
15
+ export {
16
+ color as interpolator,
17
+ cssColor as css,
18
+ type Color,
19
+ formatColor as format,
20
+ parseColor as parse,
21
+ COLOR_TOKEN as TOKEN,
22
+ registerSpaces,
23
+ spacesRegistered,
24
+ } from "./internal/colors.ts"
@@ -0,0 +1,22 @@
1
+ /**
2
+ * The DOM's Announcer: a shared live region, an element a screen reader watches and reads out as its
3
+ * text changes, and the helpers a binding uses to describe a Reorder group's items to one. `layer` is
4
+ * what `DomLive` provides; `prepare` and `announceIn` work on any document.
5
+ *
6
+ * @example
7
+ * import * as DomAnnouncer from "@wardic/dom/DomAnnouncer"
8
+ *
9
+ * DomAnnouncer.prepare(document) // its live region, before the first announcement
10
+ * DomAnnouncer.announceIn(document, "Picked up Milk, position 2 of 5.")
11
+ */
12
+ // `@wardic/dom/DomAnnouncer` (#132, ADR-0041): a shared assertive live region (ADR-0037).
13
+ export {
14
+ AnnouncerDomLive as layer,
15
+ ANNOUNCER_ATTRIBUTE as ATTRIBUTE,
16
+ documentOf,
17
+ instructionsId,
18
+ instructionsIdOf,
19
+ showInstructions,
20
+ prepareAnnouncer as prepare,
21
+ announceIn,
22
+ } from "./internal/announcer.ts"
@@ -0,0 +1,13 @@
1
+ /**
2
+ * The DOM's Clock: core's Clock and its Refresh frame source over the browser's `requestAnimationFrame`,
3
+ * as one Layer that needs nothing. `DomLive` provides it.
4
+ *
5
+ * @example
6
+ * import * as DomClock from "@wardic/dom/DomClock"
7
+ *
8
+ * const now = Effect.map(Clock.Clock, (clock) => clock.now()).pipe(Effect.provide(DomClock.layer))
9
+ */
10
+ // `@wardic/dom/DomClock` (#132, ADR-0041): rAF-driven (ADR-0031).
11
+ export {
12
+ ClockDomLive as layer,
13
+ } from "./internal/clock.ts"
@@ -0,0 +1,16 @@
1
+ /**
2
+ * The DOM's Default transition, Motion's by value: a spring for the transforms, a 0.3 s ease for the
3
+ * rest, and a 0.8 s tween through more than two keyframes. `layer` is what `DomLive` provides.
4
+ *
5
+ * @example
6
+ * import * as DomDefaultTransition from "@wardic/dom/DomDefaultTransition"
7
+ *
8
+ * DomDefaultTransition.transitionFor("x", 100) // { type: "spring", stiffness: 500, damping: 25, restSpeed: 10 }
9
+ * DomDefaultTransition.transitionFor("opacity", 1) // a 0.3 s tween
10
+ */
11
+ // `@wardic/dom/DomDefaultTransition` (#132, ADR-0041): ADR-0051, #357; keyframes #429.
12
+ export {
13
+ DefaultTransitionDomLive as layer,
14
+ keyframes,
15
+ transitionFor,
16
+ } from "./internal/default-transition.ts"
@@ -0,0 +1,22 @@
1
+ /**
2
+ * The DOM's InputSource: pointer, keyboard and focus events as core's own, mapped from the DOM's names by
3
+ * `toPointer`, `keyOf`, `kindOf` and `buttonOf`. It isn't in `DomLive`: a binding builds `layer` with the
4
+ * first gesture an app uses, so an app with none ships no input code.
5
+ *
6
+ * @example
7
+ * import * as DomInput from "@wardic/dom/DomInput"
8
+ *
9
+ * DomInput.keyOf("ArrowLeft") // "left"
10
+ * DomInput.buttonOf(2) // "secondary"
11
+ */
12
+ // `@wardic/dom/DomInput` (#132, ADR-0041): ADR-0019, ADR-0036 *Amendment (#189)*, ADR-0037. Not in
13
+ // `DomLive`: #511, ADR-0067 decision 14.
14
+ export {
15
+ InputDomLive as layer,
16
+ keyOf,
17
+ kindOf,
18
+ makeFocusable,
19
+ buttonOf,
20
+ toPointer,
21
+ type Where,
22
+ } from "./internal/input.ts"
@@ -0,0 +1,16 @@
1
+ /**
2
+ * The DOM's InterpolatorRegistry: core's value kinds with the DOM's colours and complex values, and the
3
+ * DOM's Key rules. `layer` is what `DomLive` provides; `all` is its kinds, in the order they're tried.
4
+ *
5
+ * @example
6
+ * import * as DomInterpolators from "@wardic/dom/DomInterpolators"
7
+ *
8
+ * const registry = yield* InterpolatorRegistry.make(DomInterpolators.all, DomKeyRules.all)
9
+ * const blend = yield* registry.resolve("#bf616a", "#a3be8c")
10
+ * blend(0.5) // the colour halfway
11
+ */
12
+ // `@wardic/dom/DomInterpolators` (#132, ADR-0041): ADR-0024, ADR-0035, ADR-0036.
13
+ export {
14
+ InterpolatorRegistryDomLive as layer,
15
+ interpolators as all,
16
+ } from "./internal/interpolators.ts"
@@ -0,0 +1,17 @@
1
+ /**
2
+ * The DOM's Key rules, for the keys it blends by name. `visibility` keeps `display` and `visibility` at
3
+ * their start until an animation's last frame when they're hiding the element, and `animatableNone`
4
+ * grows a shadow, a filter or a fill from nothing when one end is empty. `all` is both, in the order
5
+ * they're asked.
6
+ *
7
+ * @example
8
+ * import * as DomKeyRules from "@wardic/dom/DomKeyRules"
9
+ *
10
+ * const registry = yield* InterpolatorRegistry.make(DomInterpolators.all, [DomKeyRules.visibility])
11
+ */
12
+ // `@wardic/dom/DomKeyRules` (#132, ADR-0041): ADR-0015, ADR-0035.
13
+ export {
14
+ keyRules as all,
15
+ visibility,
16
+ animatableNone,
17
+ } from "./internal/key-rules.ts"
@@ -0,0 +1,16 @@
1
+ /**
2
+ * The DOM's Positional keys, the keys reduced motion lands at once rather than animating: the
3
+ * transforms, and the keys that place and size an element's box, `top`, `width` and the rest. `layer`
4
+ * is what `DomLive` provides.
5
+ *
6
+ * @example
7
+ * import * as DomPositionalKeys from "@wardic/dom/DomPositionalKeys"
8
+ *
9
+ * DomPositionalKeys.isPositional("width") // true: it lands at once
10
+ * DomPositionalKeys.isPositional("opacity") // false: it still fades
11
+ */
12
+ // `@wardic/dom/DomPositionalKeys` (#132, ADR-0041): ADR-0029, ADR-0036.
13
+ export {
14
+ PositionalKeysDomLive as layer,
15
+ isPositional,
16
+ } from "./internal/positional-keys.ts"
@@ -0,0 +1,15 @@
1
+ /**
2
+ * The DOM's Probe: boxes from `getBoundingClientRect`, sizes and visibility from the observers, the
3
+ * viewport, the reduced-motion preference from `matchMedia`, whether the page is shown, and a container's
4
+ * scroll. `layer` needs the Environment's `AtomRegistry`, which it writes its live values through;
5
+ * `DomLive` provides both.
6
+ *
7
+ * @example
8
+ * import * as DomProbe from "@wardic/dom/DomProbe"
9
+ *
10
+ * const probe = DomProbe.layer.pipe(Layer.provide(AtomRegistry.layer))
11
+ */
12
+ // `@wardic/dom/DomProbe` (#132, ADR-0041).
13
+ export {
14
+ ProbeDomLive as layer,
15
+ } from "./internal/probe.ts"
@@ -0,0 +1,44 @@
1
+ /**
2
+ * The DOM's Projection system: `layer` builds it, writing through the Environment's
3
+ * `FlushGate`, and `make` builds it over any sink, for a binding that wires it itself. Only a binding's
4
+ * layout feature imports it, so a page that never lays out ships none of it. Closing its Scope stops the
5
+ * engine: its run, its observers and listeners, and what it forked. Built after the gate, it ends before
6
+ * it.
7
+ *
8
+ * @example
9
+ * import * as DomProjectionSystem from "@wardic/dom/DomProjectionSystem"
10
+ *
11
+ * const layout = DomProjectionSystem.layer().pipe(Layer.provide(FlushGate.layer({ batch: (apply) => apply() })))
12
+ */
13
+ // The DOM's **Projection system** engine (#548, ADR-0041's `Dom` implementations), apart from
14
+ // `ProjectionSystem`'s key and types (ADR-0067, *Amendment (#548)*). Its members are plain functions.
15
+ import * as Context from "effect/Context"
16
+ import * as Effect from "effect/Effect"
17
+ import * as Layer from "effect/Layer"
18
+ import type * as Scope from "effect/Scope"
19
+ import * as FlushGate from "./FlushGate.ts"
20
+ import { PassEnds } from "./internal/pass-ends.ts"
21
+ import * as internal from "./internal/projection.ts"
22
+ import { makeRunner } from "./internal/runner.ts"
23
+ import { ProjectionSystem, type Options, type Services, type Shape, type Sink } from "./ProjectionSystem.ts"
24
+
25
+ /**
26
+ * Build the engine over `sink`, the context's Frame loop and Renderer, in the current Scope: what
27
+ * it forks runs in that Scope, and closing it ends the engine. It's the `ProjectionSystem` in the
28
+ * context it gives, beside what a Reorder controller over it needs.
29
+ */
30
+ // The context holds the internal `PassEnds` too (internal/pass-ends.ts, #618), the engine's own, so a
31
+ // ProjectionSystem a binding wraps or replaces in its context still has its Reorder controller hear
32
+ // each Measure pass. Its runner forks on Effect's default scheduler, whatever call built the Layer
33
+ // (`internal/runner.ts`).
34
+ export const make: (sink: Sink, options?: Options) => Effect.Effect<Context.Context<ProjectionSystem | PassEnds>, never, Services | Scope.Scope> =
35
+ /*#__PURE__*/ Effect.fnUntraced(function* (sink: Sink, options: Options = {}) {
36
+ // Typed without `dispose` and `onPassEnd`: the Scope ends it, and `PassEnds` hands the other out.
37
+ const system = internal.makeProjectionSystem(yield* makeRunner<Services>(), sink, options)
38
+ yield* Effect.addFinalizer(() => Effect.sync(system.dispose))
39
+ return Context.make(ProjectionSystem, system as Shape).pipe(Context.add(PassEnds, { onPassEnd: system.onPassEnd }))
40
+ })
41
+
42
+ /** The engine as a Layer, writing through the Environment's `FlushGate`: built by `make`, ended by the Layer's Scope. */
43
+ export const layer = (options: Options = {}): Layer.Layer<ProjectionSystem | PassEnds, never, FlushGate.FlushGate | Services> =>
44
+ Layer.effectContext(Effect.flatMap(Effect.service(FlushGate.FlushGate), (gate) => make(gate, options)))
@@ -0,0 +1,26 @@
1
+ /**
2
+ * The DOM's Renderer: `project` turns a Frame's values into a style patch, grouping the transform keys
3
+ * into one `transform` and drawing a bare number on a length in `px`, and its `commit` writes the patch
4
+ * onto an element. The rest is for a binding's layout projection: an element's own move, scale, rotation
5
+ * and opacity, read from its values, and its transform template.
6
+ *
7
+ * @example
8
+ * import * as DomRenderer from "@wardic/dom/DomRenderer"
9
+ *
10
+ * DomRenderer.project({ x: 100, opacity: 0.5 }) // { transform: "translateX(100px)", opacity: 0.5 }
11
+ */
12
+ // `@wardic/dom/DomRenderer` (#132, ADR-0041): ADR-0006, ADR-0034; the **Transform template** (#443);
13
+ // `LENGTH_KEYS` (#522).
14
+ export {
15
+ RendererDomLive as layer,
16
+ project,
17
+ ownScaleOf,
18
+ ownTranslateOf,
19
+ ownRotateOf,
20
+ ownOpacityOf,
21
+ TEMPLATE_KEY,
22
+ type TransformTemplate,
23
+ heldTransformOf,
24
+ LENGTH_KEYS,
25
+ type LengthKey,
26
+ } from "./internal/renderer.ts"
@@ -0,0 +1,81 @@
1
+ /**
2
+ * The Flush gate: where a binding writes each element's animated values, drawn onto the elements once a
3
+ * frame. A binding registers each element with its target, writes values as its animations step, and the
4
+ * gate draws them together, at the end of the frame's animation tick, through the Environment's renderer;
5
+ * a write made outside a tick, as a drag's move is, asks for a frame of its own. A server render gets
6
+ * `inert`, which does nothing.
7
+ *
8
+ * @example
9
+ * import * as FlushGate from "@wardic/dom/FlushGate"
10
+ *
11
+ * const gate = yield* FlushGate.FlushGate
12
+ * const unregister = gate.register("card", { target: card })
13
+ * gate.write("card", { opacity: 0.5 }) // drawn at the next frame
14
+ */
15
+ // The **Flush gate** (ADR-0006, ADR-0031, ADR-0033, ADR-0034). `@wardic/dom/FlushGate` (#132, ADR-0041). A
16
+ // service built by a Layer (`layer`) and ended by that Layer's Scope: closing it takes the gate's hook off
17
+ // the Frame loop, cancels a pending frame and clears what it held. Its members are plain functions, called
18
+ // per element and per frame. `make` is the scoped constructor, for a binding that wires it itself. `inert`
19
+ // (ADR-0021, decision 9): a value for a binding whose server builds no runtime, or `layerInert` for one
20
+ // whose server runs an Effect program.
21
+ import * as Context from "effect/Context"
22
+ import * as Effect from "effect/Effect"
23
+ import * as Layer from "effect/Layer"
24
+ import { Atom } from "effect/reactivity"
25
+ import type * as Scope from "effect/Scope"
26
+ import * as internal from "./internal/gate.ts"
27
+ import { makeRunner } from "./internal/runner.ts"
28
+
29
+ /** The gate: what a binding registers its elements with and writes their values into. */
30
+ export type Shape = Omit<internal.FlushGate, "dispose">
31
+
32
+ /** An element's commit target and hooks, given to `register`. */
33
+ export type Sink = internal.FlushSink
34
+
35
+ /** What a binding hands its gate: the `batch` a frame's Starting-style switches run in. */
36
+ export type Options = internal.FlushGateOptions
37
+
38
+ /** The services a gate needs from its Environment. */
39
+ export type Services = internal.FlushGateServices
40
+
41
+ /** The Environment's Flush gate. */
42
+ export class FlushGate extends Context.Service<FlushGate, Shape>()("@wardic/dom/FlushGate") {}
43
+
44
+ /**
45
+ * Build a gate over the context's Renderer, Frame loop and Refresh frame source, in the current
46
+ * Scope: what it forks runs in that Scope, and closing it ends the gate.
47
+ */
48
+ export const make: (options: Options) => Effect.Effect<Shape, never, Services | Scope.Scope> = Effect.fnUntraced(
49
+ function* (options: Options) {
50
+ // The gate itself, typed without `dispose`: the Scope ends it. Its runner forks on Effect's
51
+ // default scheduler, whatever call built the Layer (`internal/runner.ts`).
52
+ const gate = internal.makeFlushGate(yield* makeRunner<Services>(), options)
53
+ yield* Effect.addFinalizer(() => Effect.sync(gate.dispose))
54
+ return gate
55
+ })
56
+
57
+ /** The gate as a Layer: built by `make`, ended by the Layer's Scope. */
58
+ export const layer = (options: Options): Layer.Layer<FlushGate, never, Services> => Layer.effect(FlushGate)(make(options))
59
+
60
+ const noop = (): void => {}
61
+
62
+ /** What `inert`'s `valueOf` gives: an Atom that stays `undefined`, since nothing is committed on a server. */
63
+ const NO_VALUE: Atom.Atom<unknown> = Atom.make<unknown>(undefined)
64
+
65
+ /**
66
+ * The gate a server render gets: it flushes nothing, so `register` returns an unregister that does
67
+ * nothing, and the rest do nothing, `afterFlush` included, since no flush comes. Code that takes the gate
68
+ * at setup and uses it after mount keeps working on a server.
69
+ */
70
+ // ADR-0021, decision 9.
71
+ export const inert: Shape = Object.freeze({
72
+ register: () => noop,
73
+ write: noop,
74
+ flushPass: noop,
75
+ release: noop,
76
+ valueOf: () => NO_VALUE,
77
+ afterFlush: noop,
78
+ })
79
+
80
+ /** `inert` as a Layer, for a binding whose server render runs an Effect program. */
81
+ export const layerInert: Layer.Layer<FlushGate> = Layer.succeed(FlushGate, inert)
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Measured pairs: a key that places or sizes the box, whose two ends are lengths of different types,
3
+ * `"auto"` against px, `"50%"` against a number, a `calc()`, can't blend as written. Both ends are
4
+ * measured in px at the end of the task that asks, as Motion's are, so the animation runs between them
5
+ * and lands on its target as given.
6
+ *
7
+ * @example
8
+ * import * as MeasuredPair from "@wardic/dom/MeasuredPair"
9
+ *
10
+ * MeasuredPair.needs("width", "auto", 200) // true
11
+ * MeasuredPair.needs("opacity", 0, 1) // false
12
+ */
13
+ // **Measured pairs** (#430, CONTEXT.md, Motion's `DOMKeyframesResolver`). `@wardic/dom/MeasuredPair`: for
14
+ // binding authors.
15
+ export { measure, measured, type Measured, needs, type Requested } from "./internal/measured-pairs.ts"
@@ -0,0 +1,19 @@
1
+ /**
2
+ * An element's own values: what its style or its computed style says for a key, read once, the value an
3
+ * animation starts from, and returns to when nothing else sets it. `valueLike` reads a raw value in the
4
+ * shape of the key's target.
5
+ *
6
+ * @example
7
+ * import * as OwnValues from "@wardic/dom/OwnValues"
8
+ *
9
+ * const own = OwnValues.of(element)
10
+ * own("opacity") // Some("1"), from its computed style
11
+ * OwnValues.valueLike("10px", 0) // Some(10)
12
+ */
13
+ // `@wardic/dom/OwnValues` (#132, ADR-0041): its Base values (ADR-0022).
14
+ export {
15
+ ownValues as of,
16
+ styleValueOf,
17
+ valueLike,
18
+ type OwnValue,
19
+ } from "./internal/own-values.ts"