bireactive 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (225) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +81 -0
  3. package/dist/animation/anim.d.ts +57 -0
  4. package/dist/animation/anim.js +318 -0
  5. package/dist/animation/combinators.d.ts +39 -0
  6. package/dist/animation/combinators.js +113 -0
  7. package/dist/animation/easings.d.ts +5 -0
  8. package/dist/animation/easings.js +5 -0
  9. package/dist/animation/index.d.ts +3 -0
  10. package/dist/animation/index.js +3 -0
  11. package/dist/assert/algebra.d.ts +20 -0
  12. package/dist/assert/algebra.js +79 -0
  13. package/dist/assert/claim.d.ts +40 -0
  14. package/dist/assert/claim.js +129 -0
  15. package/dist/assert/index.d.ts +7 -0
  16. package/dist/assert/index.js +19 -0
  17. package/dist/assert/predicates.d.ts +18 -0
  18. package/dist/assert/predicates.js +43 -0
  19. package/dist/assert/record.d.ts +20 -0
  20. package/dist/assert/record.js +78 -0
  21. package/dist/assert/scope.d.ts +42 -0
  22. package/dist/assert/scope.js +233 -0
  23. package/dist/assert/span.d.ts +37 -0
  24. package/dist/assert/span.js +68 -0
  25. package/dist/assert/tree.d.ts +22 -0
  26. package/dist/assert/tree.js +65 -0
  27. package/dist/code/code.d.ts +70 -0
  28. package/dist/code/code.js +361 -0
  29. package/dist/code/index.d.ts +2 -0
  30. package/dist/code/index.js +9 -0
  31. package/dist/code/morph.d.ts +5 -0
  32. package/dist/code/morph.js +194 -0
  33. package/dist/code/tokenize.d.ts +8 -0
  34. package/dist/code/tokenize.js +51 -0
  35. package/dist/constraints/cluster.d.ts +83 -0
  36. package/dist/constraints/cluster.js +213 -0
  37. package/dist/constraints/drivers.d.ts +15 -0
  38. package/dist/constraints/drivers.js +40 -0
  39. package/dist/constraints/factories.d.ts +73 -0
  40. package/dist/constraints/factories.js +248 -0
  41. package/dist/constraints/index.d.ts +11 -0
  42. package/dist/constraints/index.js +39 -0
  43. package/dist/constraints/interaction.d.ts +21 -0
  44. package/dist/constraints/interaction.js +148 -0
  45. package/dist/constraints/linalg.d.ts +18 -0
  46. package/dist/constraints/linalg.js +141 -0
  47. package/dist/constraints/phases.d.ts +21 -0
  48. package/dist/constraints/phases.js +60 -0
  49. package/dist/constraints/physics.d.ts +34 -0
  50. package/dist/constraints/physics.js +128 -0
  51. package/dist/constraints/rigid.d.ts +210 -0
  52. package/dist/constraints/rigid.js +835 -0
  53. package/dist/constraints/solver.d.ts +107 -0
  54. package/dist/constraints/solver.js +510 -0
  55. package/dist/constraints/term.d.ts +50 -0
  56. package/dist/constraints/term.js +80 -0
  57. package/dist/constraints/terms.d.ts +80 -0
  58. package/dist/constraints/terms.js +302 -0
  59. package/dist/constraints/world.d.ts +31 -0
  60. package/dist/constraints/world.js +245 -0
  61. package/dist/core/aggregates.d.ts +64 -0
  62. package/dist/core/aggregates.js +198 -0
  63. package/dist/core/anim.d.ts +84 -0
  64. package/dist/core/anim.js +301 -0
  65. package/dist/core/index.d.ts +38 -0
  66. package/dist/core/index.js +38 -0
  67. package/dist/core/introspect.d.ts +5 -0
  68. package/dist/core/introspect.js +31 -0
  69. package/dist/core/lenses/closed-form-policies.d.ts +64 -0
  70. package/dist/core/lenses/closed-form-policies.js +452 -0
  71. package/dist/core/lenses/domain-aggregates.d.ts +54 -0
  72. package/dist/core/lenses/domain-aggregates.js +259 -0
  73. package/dist/core/lenses/factor-lens.d.ts +42 -0
  74. package/dist/core/lenses/factor-lens.js +419 -0
  75. package/dist/core/lenses/index.d.ts +5 -0
  76. package/dist/core/lenses/index.js +16 -0
  77. package/dist/core/lenses/memory.d.ts +47 -0
  78. package/dist/core/lenses/memory.js +102 -0
  79. package/dist/core/lenses/typed-factor.d.ts +45 -0
  80. package/dist/core/lenses/typed-factor.js +376 -0
  81. package/dist/core/network-utils.d.ts +14 -0
  82. package/dist/core/network-utils.js +62 -0
  83. package/dist/core/new-primitives.d.ts +33 -0
  84. package/dist/core/new-primitives.js +113 -0
  85. package/dist/core/signal.d.ts +254 -0
  86. package/dist/core/signal.js +1349 -0
  87. package/dist/core/traits.d.ts +61 -0
  88. package/dist/core/traits.js +56 -0
  89. package/dist/core/tree.d.ts +23 -0
  90. package/dist/core/tree.js +62 -0
  91. package/dist/core/values/anchor.d.ts +23 -0
  92. package/dist/core/values/anchor.js +23 -0
  93. package/dist/core/values/audio.d.ts +33 -0
  94. package/dist/core/values/audio.js +107 -0
  95. package/dist/core/values/bool.d.ts +37 -0
  96. package/dist/core/values/bool.js +75 -0
  97. package/dist/core/values/box.d.ts +77 -0
  98. package/dist/core/values/box.js +211 -0
  99. package/dist/core/values/canvas.d.ts +71 -0
  100. package/dist/core/values/canvas.js +495 -0
  101. package/dist/core/values/color.d.ts +49 -0
  102. package/dist/core/values/color.js +106 -0
  103. package/dist/core/values/flags.d.ts +18 -0
  104. package/dist/core/values/flags.js +50 -0
  105. package/dist/core/values/gpu.d.ts +74 -0
  106. package/dist/core/values/gpu.js +426 -0
  107. package/dist/core/values/matrix.d.ts +53 -0
  108. package/dist/core/values/matrix.js +140 -0
  109. package/dist/core/values/num.d.ts +62 -0
  110. package/dist/core/values/num.js +166 -0
  111. package/dist/core/values/pose.d.ts +31 -0
  112. package/dist/core/values/pose.js +83 -0
  113. package/dist/core/values/range.d.ts +83 -0
  114. package/dist/core/values/range.js +167 -0
  115. package/dist/core/values/str.d.ts +76 -0
  116. package/dist/core/values/str.js +346 -0
  117. package/dist/core/values/template.d.ts +49 -0
  118. package/dist/core/values/template.js +148 -0
  119. package/dist/core/values/transform.d.ts +49 -0
  120. package/dist/core/values/transform.js +115 -0
  121. package/dist/core/values/tri.d.ts +31 -0
  122. package/dist/core/values/tri.js +95 -0
  123. package/dist/core/values/vec.d.ts +72 -0
  124. package/dist/core/values/vec.js +219 -0
  125. package/dist/core/writable.d.ts +15 -0
  126. package/dist/core/writable.js +29 -0
  127. package/dist/ext/events.d.ts +10 -0
  128. package/dist/ext/events.js +31 -0
  129. package/dist/ext/index.d.ts +4 -0
  130. package/dist/ext/index.js +4 -0
  131. package/dist/ext/snapshot.d.ts +8 -0
  132. package/dist/ext/snapshot.js +29 -0
  133. package/dist/ext/timeline.d.ts +56 -0
  134. package/dist/ext/timeline.js +94 -0
  135. package/dist/ext/waapi.d.ts +25 -0
  136. package/dist/ext/waapi.js +198 -0
  137. package/dist/index.d.ts +8 -0
  138. package/dist/index.js +10 -0
  139. package/dist/propagators/index.d.ts +6 -0
  140. package/dist/propagators/index.js +6 -0
  141. package/dist/propagators/layout.d.ts +68 -0
  142. package/dist/propagators/layout.js +336 -0
  143. package/dist/propagators/network.d.ts +52 -0
  144. package/dist/propagators/network.js +185 -0
  145. package/dist/propagators/propagator.d.ts +12 -0
  146. package/dist/propagators/propagator.js +16 -0
  147. package/dist/propagators/range.d.ts +45 -0
  148. package/dist/propagators/range.js +147 -0
  149. package/dist/propagators/relations.d.ts +60 -0
  150. package/dist/propagators/relations.js +343 -0
  151. package/dist/shapes/annular-sector.d.ts +15 -0
  152. package/dist/shapes/annular-sector.js +64 -0
  153. package/dist/shapes/button.d.ts +14 -0
  154. package/dist/shapes/button.js +31 -0
  155. package/dist/shapes/choreographers.d.ts +22 -0
  156. package/dist/shapes/choreographers.js +69 -0
  157. package/dist/shapes/circle.d.ts +17 -0
  158. package/dist/shapes/circle.js +57 -0
  159. package/dist/shapes/clip.d.ts +5 -0
  160. package/dist/shapes/clip.js +31 -0
  161. package/dist/shapes/connect.d.ts +16 -0
  162. package/dist/shapes/connect.js +70 -0
  163. package/dist/shapes/curve.d.ts +60 -0
  164. package/dist/shapes/curve.js +285 -0
  165. package/dist/shapes/dashed.d.ts +16 -0
  166. package/dist/shapes/dashed.js +142 -0
  167. package/dist/shapes/debug.d.ts +43 -0
  168. package/dist/shapes/debug.js +97 -0
  169. package/dist/shapes/group.d.ts +5 -0
  170. package/dist/shapes/group.js +10 -0
  171. package/dist/shapes/handle.d.ts +32 -0
  172. package/dist/shapes/handle.js +88 -0
  173. package/dist/shapes/index.d.ts +23 -0
  174. package/dist/shapes/index.js +23 -0
  175. package/dist/shapes/interaction.d.ts +32 -0
  176. package/dist/shapes/interaction.js +187 -0
  177. package/dist/shapes/label.d.ts +20 -0
  178. package/dist/shapes/label.js +42 -0
  179. package/dist/shapes/layout.d.ts +29 -0
  180. package/dist/shapes/layout.js +74 -0
  181. package/dist/shapes/line.d.ts +21 -0
  182. package/dist/shapes/line.js +79 -0
  183. package/dist/shapes/list.d.ts +18 -0
  184. package/dist/shapes/list.js +51 -0
  185. package/dist/shapes/mount.d.ts +7 -0
  186. package/dist/shapes/mount.js +10 -0
  187. package/dist/shapes/path.d.ts +77 -0
  188. package/dist/shapes/path.js +227 -0
  189. package/dist/shapes/rect.d.ts +30 -0
  190. package/dist/shapes/rect.js +131 -0
  191. package/dist/shapes/shape.d.ts +132 -0
  192. package/dist/shapes/shape.js +306 -0
  193. package/dist/shapes/text.d.ts +24 -0
  194. package/dist/shapes/text.js +53 -0
  195. package/dist/shapes/tokens.d.ts +28 -0
  196. package/dist/shapes/tokens.js +27 -0
  197. package/dist/shapes/transitions.d.ts +23 -0
  198. package/dist/shapes/transitions.js +62 -0
  199. package/dist/tex/decorations.d.ts +26 -0
  200. package/dist/tex/decorations.js +116 -0
  201. package/dist/tex/index.d.ts +5 -0
  202. package/dist/tex/index.js +5 -0
  203. package/dist/tex/marker.d.ts +17 -0
  204. package/dist/tex/marker.js +63 -0
  205. package/dist/tex/motion.d.ts +43 -0
  206. package/dist/tex/motion.js +290 -0
  207. package/dist/tex/parts.d.ts +65 -0
  208. package/dist/tex/parts.js +149 -0
  209. package/dist/tex/tex.d.ts +45 -0
  210. package/dist/tex/tex.js +244 -0
  211. package/dist/web/attr.d.ts +16 -0
  212. package/dist/web/attr.js +98 -0
  213. package/dist/web/diagram.d.ts +49 -0
  214. package/dist/web/diagram.js +260 -0
  215. package/dist/web/index.d.ts +6 -0
  216. package/dist/web/index.js +6 -0
  217. package/dist/web/md-marker.d.ts +6 -0
  218. package/dist/web/md-marker.js +39 -0
  219. package/dist/web/md-tex.d.ts +6 -0
  220. package/dist/web/md-tex.js +61 -0
  221. package/dist/web/raf.d.ts +6 -0
  222. package/dist/web/raf.js +24 -0
  223. package/dist/web/viewport.d.ts +7 -0
  224. package/dist/web/viewport.js +13 -0
  225. package/package.json +87 -0
@@ -0,0 +1,211 @@
1
+ // box.ts — reactive axis-aligned rectangle.
2
+ //
3
+ // Invertibles (`add`, `sub`, `scale`, `expand`) return `: this` and ride
4
+ // on `Cell#lens(fwd, bwd)`. Chained calls compose into a lens chain.
5
+ import { tween } from "../anim.js";
6
+ import { Cell, isComputed, lazy, reader, readNow, } from "../signal.js";
7
+ import { derived, field } from "../writable.js";
8
+ import { Bool } from "./bool.js";
9
+ import { Num, num } from "./num.js";
10
+ import { Vec } from "./vec.js";
11
+ export const add = (a, b) => ({ x: a.x + b.x, y: a.y + b.y, w: a.w + b.w, h: a.h + b.h });
12
+ export const sub = (a, b) => ({ x: a.x - b.x, y: a.y - b.y, w: a.w - b.w, h: a.h - b.h });
13
+ export const scale = (a, k) => ({ x: a.x * k, y: a.y * k, w: a.w * k, h: a.h * k });
14
+ export const lerp = (a, b, t) => ({
15
+ x: a.x + (b.x - a.x) * t,
16
+ y: a.y + (b.y - a.y) * t,
17
+ w: a.w + (b.w - a.w) * t,
18
+ h: a.h + (b.h - a.h) * t,
19
+ });
20
+ export const equals = (a, b) => a === b || (a.x === b.x && a.y === b.y && a.w === b.w && a.h === b.h);
21
+ /** L2 distance over the flat (x, y, w, h) representation. */
22
+ export const metric = (a, b) => Math.hypot(a.x - b.x, a.y - b.y, a.w - b.w, a.h - b.h);
23
+ export const expand = (b, n) => ({
24
+ x: b.x - n,
25
+ y: b.y - n,
26
+ w: b.w + 2 * n,
27
+ h: b.h + 2 * n,
28
+ });
29
+ export const contains = (b, p) => p.x >= b.x && p.x <= b.x + b.w && p.y >= b.y && p.y <= b.y + b.h;
30
+ /** Closest point inside `b` to `p`. Already-inside is identity; outside
31
+ * snaps to the nearest boundary point. `Box#contains`'s true-side bwd. */
32
+ export const clampToBox = (p, b) => ({
33
+ x: Math.max(b.x, Math.min(b.x + b.w, p.x)),
34
+ y: Math.max(b.y, Math.min(b.y + b.h, p.y)),
35
+ });
36
+ /** Closest point strictly outside `b` to `p`, displaced past the nearest
37
+ * edge by `eps`. Already-outside is identity. `Box#contains`'s
38
+ * false-side bwd. */
39
+ export const ejectFromBox = (p, b, eps = 1e-6) => {
40
+ if (!contains(b, p))
41
+ return p;
42
+ const dLeft = p.x - b.x;
43
+ const dRight = b.x + b.w - p.x;
44
+ const dTop = p.y - b.y;
45
+ const dBot = b.y + b.h - p.y;
46
+ const min = Math.min(dLeft, dRight, dTop, dBot);
47
+ if (min === dLeft)
48
+ return { x: b.x - eps, y: p.y };
49
+ if (min === dRight)
50
+ return { x: b.x + b.w + eps, y: p.y };
51
+ if (min === dTop)
52
+ return { x: p.x, y: b.y - eps };
53
+ return { x: p.x, y: b.y + b.h + eps };
54
+ };
55
+ /** Bounding box around a set of boxes. */
56
+ export function union(...bs) {
57
+ if (bs.length === 0)
58
+ return { x: 0, y: 0, w: 0, h: 0 };
59
+ let xMin = bs[0].x, yMin = bs[0].y;
60
+ let xMax = xMin + bs[0].w, yMax = yMin + bs[0].h;
61
+ for (let i = 1; i < bs.length; i++) {
62
+ const o = bs[i];
63
+ if (o.x < xMin)
64
+ xMin = o.x;
65
+ if (o.y < yMin)
66
+ yMin = o.y;
67
+ if (o.x + o.w > xMax)
68
+ xMax = o.x + o.w;
69
+ if (o.y + o.h > yMax)
70
+ yMax = o.y + o.h;
71
+ }
72
+ return { x: xMin, y: yMin, w: xMax - xMin, h: yMax - yMin };
73
+ }
74
+ /** Perimeter point on a Box facing `toward`. Default `Shape.boundary`. */
75
+ export function edgeFrom(b, toward) {
76
+ const cx = b.x + b.w / 2;
77
+ const cy = b.y + b.h / 2;
78
+ const dx = toward.x - cx;
79
+ const dy = toward.y - cy;
80
+ if (dx === 0 && dy === 0)
81
+ return { x: cx, y: cy };
82
+ const k = Math.min(dx === 0 ? Number.POSITIVE_INFINITY : b.w / 2 / Math.abs(dx), dy === 0 ? Number.POSITIVE_INFINITY : b.h / 2 / Math.abs(dy));
83
+ return { x: cx + dx * k, y: cy + dy * k };
84
+ }
85
+ const linearImpl = { add, sub, scale };
86
+ const packImpl = {
87
+ dim: 4,
88
+ read: (v, a, o) => {
89
+ a[o] = v.x;
90
+ a[o + 1] = v.y;
91
+ a[o + 2] = v.w;
92
+ a[o + 3] = v.h;
93
+ },
94
+ write: (a, o) => ({ x: a[o], y: a[o + 1], w: a[o + 2], h: a[o + 3] }),
95
+ };
96
+ export class Box extends Cell {
97
+ static traits = {
98
+ linear: linearImpl,
99
+ lerp,
100
+ metric,
101
+ equals,
102
+ pack: packImpl,
103
+ };
104
+ constructor(v = { x: 0, y: 0, w: 0, h: 0 }) {
105
+ super(v, { equals });
106
+ }
107
+ add(b) {
108
+ const bf = reader(b);
109
+ return this.lens(v => add(v, bf()), n => sub(n, bf()));
110
+ }
111
+ sub(b) {
112
+ const bf = reader(b);
113
+ return this.lens(v => sub(v, bf()), n => add(n, bf()));
114
+ }
115
+ scale(k) {
116
+ const kf = reader(k);
117
+ return this.lens(v => scale(v, kf()), n => scale(n, 1 / kf()));
118
+ }
119
+ expand(n) {
120
+ const nf = reader(n);
121
+ return this.lens(v => expand(v, nf()), o => expand(o, -nf()));
122
+ }
123
+ lerp(b, t) {
124
+ return Box.derive(() => lerp(this.value, readNow(b), readNow(t)));
125
+ }
126
+ /** Membership predicate. Conditional return type: a writable `Vec`
127
+ * yields `Writable<Bool>` and flipping the view moves the source —
128
+ * `true` clamps to the nearest in-box point, `false` ejects past the
129
+ * nearest edge by `eps`. Literal / RO inputs yield a bare RO `Bool`. */
130
+ contains(p) {
131
+ if (p instanceof Vec) {
132
+ // A computed Vec has no backward path → RO branch; sources and
133
+ // writable lenses accept write-back.
134
+ if (!isComputed(p)) {
135
+ // `.bind(Bool)` + cast steps past the generic overloads, whose
136
+ // mapped-tuple inference over the full class types otherwise blows
137
+ // the instantiation depth.
138
+ const mk = Bool.lens.bind(Bool);
139
+ return mk([this, p], vals => contains(vals[0], vals[1]), (target, vals) => {
140
+ const [b, v] = vals;
141
+ if (contains(b, v) === target)
142
+ return [undefined, undefined];
143
+ return [undefined, target ? clampToBox(v, b) : ejectFromBox(v, b)];
144
+ });
145
+ }
146
+ }
147
+ return Bool.derive(() => contains(this.value, readNow(p)));
148
+ }
149
+ get x() {
150
+ return field(this, "x", Num);
151
+ }
152
+ get y() {
153
+ return field(this, "y", Num);
154
+ }
155
+ get w() {
156
+ return field(this, "w", Num);
157
+ }
158
+ get h() {
159
+ return field(this, "h", Num);
160
+ }
161
+ get area() {
162
+ return derived(this, "area", Num, b => b.w * b.h);
163
+ }
164
+ /** Vec at parametric (u, v) within `[0,1]²`. Not memoised (arbitrary
165
+ * pairs would leak a cache entry each) — use the named edge getters
166
+ * (`.center`, `.top`, …) for stable identity. */
167
+ at(u, v) {
168
+ return Vec.derive(this, b => ({ x: b.x + u * b.w, y: b.y + v * b.h }));
169
+ }
170
+ // Named edges — RO views over `at(u, v)`, memoised under stable keys
171
+ // so subscribers always see the same Vec. `lazy()` directly since
172
+ // `at()` already returns a Vec.
173
+ get center() {
174
+ return lazy(this, "center", () => this.at(0.5, 0.5));
175
+ }
176
+ get top() {
177
+ return lazy(this, "top", () => this.at(0.5, 0));
178
+ }
179
+ get bottom() {
180
+ return lazy(this, "bottom", () => this.at(0.5, 1));
181
+ }
182
+ get left() {
183
+ return lazy(this, "left", () => this.at(0, 0.5));
184
+ }
185
+ get right() {
186
+ return lazy(this, "right", () => this.at(1, 0.5));
187
+ }
188
+ /** Tween-builder, implied by the lerp trait. */
189
+ to(target, dur, ease) {
190
+ return tween(this, target, dur, ease);
191
+ }
192
+ }
193
+ /** Writable `Box` at `(x, y, w, h)`. Each component is a literal `number`
194
+ * (lifted to a fresh seed) or an existing `Writable<Num>` (identity
195
+ * passthrough). RO sources are rejected at the type level — use
196
+ * `Box.derive(...)` for reactive RO tracking, or `cell.value` to
197
+ * snapshot. Lock a component with `Num.pin(c)`. */
198
+ export function box(x = 0, y = 0, w = 0, h = 0) {
199
+ if (typeof x === "number" &&
200
+ typeof y === "number" &&
201
+ typeof w === "number" &&
202
+ typeof h === "number") {
203
+ return new Box({ x, y, w, h });
204
+ }
205
+ const xN = num(x);
206
+ const yN = num(y);
207
+ const wN = num(w);
208
+ const hN = num(h);
209
+ // The view fully reconstructs all 4 axes (1-arg bwd ⇒ no source read).
210
+ return Box.lens([xN, yN, wN, hN], ([bx, by, bw, bh]) => ({ x: bx, y: by, w: bw, h: bh }), v => [v.x, v.y, v.w, v.h]);
211
+ }
@@ -0,0 +1,71 @@
1
+ import { Cell, type Val, type Writable } from "../signal.js";
2
+ import { Bool } from "./bool.js";
3
+ import { Color } from "./color.js";
4
+ import { Spring, type SpringOpts } from "./gpu.js";
5
+ import { Vec } from "./vec.js";
6
+ /** Raster header. The graph compares `epoch`; `tex` is an RGBA32F texture in
7
+ * the shared GL context (channels 0–1, may overshoot mid-deconvolution). */
8
+ export interface Raster {
9
+ readonly tex: WebGLTexture;
10
+ readonly w: number;
11
+ readonly h: number;
12
+ readonly epoch: number;
13
+ }
14
+ type V = Raster;
15
+ /** Stamp a texture with a fresh epoch — the only way to mint a value. */
16
+ export declare const stamp: (tex: WebGLTexture, w: number, h: number) => V;
17
+ export declare const equals: (a: V, b: V) => boolean;
18
+ export declare class Canvas extends Cell<V> {
19
+ static traits: {
20
+ equals: (a: V, b: V) => boolean;
21
+ };
22
+ readonly _t: typeof Canvas.traits;
23
+ constructor(v?: V);
24
+ /** Per-channel invert (alpha preserved). Involution. */
25
+ invert(): this;
26
+ /** Horizontal flip. Involution. */
27
+ flipH(): this;
28
+ /** Multiply RGB by reactive `k` (alpha preserved). Invertible while
29
+ * k ≠ 0. */
30
+ brightness(k: Val<number>): this;
31
+ /** Grayscale (Rec.601 luma) view; complement is the per-pixel chroma
32
+ * residual `(r−Y, g−Y, b−Y)`, so editing the gray view recolours the
33
+ * source. The raster analog of `str.lowercase()`. */
34
+ grayscale(): Writable<Canvas>;
35
+ /** Chroma view (the dual of `grayscale`): `(r−Y, g−Y, b−Y)` on a mid-grey
36
+ * base, complement is the luma `Y`. Editing the colour re-lights nothing —
37
+ * it rewrites hue while keeping the original brightness. */
38
+ chroma(): Writable<Canvas>;
39
+ /** Sub-rectangle view (reactive `x,y,w,h`). Editing the crop composites
40
+ * back into the source; the surround reads straight from the parent. */
41
+ crop(x: Val<number>, y: Val<number>, w: Val<number>, h: Val<number>): Writable<Canvas>;
42
+ /** Box-downsampled thumbnail (integer `factor`). Complement is the
43
+ * Laplacian residual `source − up(down(source))`; editing the thumbnail
44
+ * reconstructs full-res detail on top of the edit. */
45
+ downsample(factor: number): Writable<Canvas>;
46
+ /** Gaussian blur (reactive `radius`). Writable: the backward direction
47
+ * runs an iterated Richardson–Lucy deconvolution seeded from the source.
48
+ * Each step is `x ← x · H(target / H(x))`, non-negative and multiplicative,
49
+ * so untouched regions stay fixed (their ratio is 1) while a stroke
50
+ * back-solves to a sharp pre-image with far less ringing than an additive
51
+ * solve. PutGet, not exact GetPut — the residual is the honest signature
52
+ * of an ill-posed inverse. */
53
+ blur(radius: Val<number>): this;
54
+ /** Mean colour (0–1) as a writable `Color`; the GPU reduces, the write
55
+ * shifts every pixel by the delta (a rigid translate in RGB). */
56
+ meanColor(): Writable<Color>;
57
+ /** Mean luma ≥ reactive `threshold` (0–1) as a writable `Bool`; flipping
58
+ * the bit auto-exposes — iterate the gain (clipping caps a single step)
59
+ * until the mean crosses the line. */
60
+ brighterThan(threshold: Val<number>): Writable<Bool>;
61
+ /** Dimensions `(w, h)` as a read-only `Vec`. */
62
+ get dimensions(): Vec;
63
+ /** A GPU per-pixel spring driver seeded from this value's texture. The
64
+ * host steps it and writes `current()` back into a root cell each frame;
65
+ * settle is the GPU energy reduction. */
66
+ spring(opts?: SpringOpts): Spring;
67
+ }
68
+ /** Writable `Canvas` of size `w×h`. `painter` fills it pixel-by-pixel
69
+ * (RGBA, 0–255); omit for transparent black. Uploaded once to a texture. */
70
+ export declare function canvas(w: number, h: number, painter?: (x: number, y: number) => readonly [number, number, number, number]): Writable<Canvas>;
71
+ export {};