@kgdiff/renderer 0.0.0-stage → 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 (143) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +53 -2
  3. package/dist/atlas.d.ts +55 -0
  4. package/dist/atlas.d.ts.map +1 -0
  5. package/dist/atlas.js +132 -0
  6. package/dist/atlas.js.map +1 -0
  7. package/dist/camera.d.ts +116 -0
  8. package/dist/camera.d.ts.map +1 -0
  9. package/dist/camera.js +368 -0
  10. package/dist/camera.js.map +1 -0
  11. package/dist/color.d.ts +12 -0
  12. package/dist/color.d.ts.map +1 -0
  13. package/dist/color.js +51 -0
  14. package/dist/color.js.map +1 -0
  15. package/dist/ctx.d.ts +57 -0
  16. package/dist/ctx.d.ts.map +1 -0
  17. package/dist/ctx.js +28 -0
  18. package/dist/ctx.js.map +1 -0
  19. package/dist/draw/background.d.ts +33 -0
  20. package/dist/draw/background.d.ts.map +1 -0
  21. package/dist/draw/background.js +105 -0
  22. package/dist/draw/background.js.map +1 -0
  23. package/dist/draw/badges.d.ts +26 -0
  24. package/dist/draw/badges.d.ts.map +1 -0
  25. package/dist/draw/badges.js +82 -0
  26. package/dist/draw/badges.js.map +1 -0
  27. package/dist/draw/collapsed.d.ts +15 -0
  28. package/dist/draw/collapsed.d.ts.map +1 -0
  29. package/dist/draw/collapsed.js +67 -0
  30. package/dist/draw/collapsed.js.map +1 -0
  31. package/dist/draw/edges.d.ts +14 -0
  32. package/dist/draw/edges.d.ts.map +1 -0
  33. package/dist/draw/edges.js +115 -0
  34. package/dist/draw/edges.js.map +1 -0
  35. package/dist/draw/glyphs.d.ts +31 -0
  36. package/dist/draw/glyphs.d.ts.map +1 -0
  37. package/dist/draw/glyphs.js +114 -0
  38. package/dist/draw/glyphs.js.map +1 -0
  39. package/dist/draw/halos.d.ts +19 -0
  40. package/dist/draw/halos.d.ts.map +1 -0
  41. package/dist/draw/halos.js +91 -0
  42. package/dist/draw/halos.js.map +1 -0
  43. package/dist/draw/labels.d.ts +55 -0
  44. package/dist/draw/labels.d.ts.map +1 -0
  45. package/dist/draw/labels.js +300 -0
  46. package/dist/draw/labels.js.map +1 -0
  47. package/dist/draw/link.d.ts +25 -0
  48. package/dist/draw/link.d.ts.map +1 -0
  49. package/dist/draw/link.js +122 -0
  50. package/dist/draw/link.js.map +1 -0
  51. package/dist/draw/nodes.d.ts +13 -0
  52. package/dist/draw/nodes.d.ts.map +1 -0
  53. package/dist/draw/nodes.js +165 -0
  54. package/dist/draw/nodes.js.map +1 -0
  55. package/dist/draw/shapes.d.ts +7 -0
  56. package/dist/draw/shapes.d.ts.map +1 -0
  57. package/dist/draw/shapes.js +26 -0
  58. package/dist/draw/shapes.js.map +1 -0
  59. package/dist/draw/view.d.ts +36 -0
  60. package/dist/draw/view.d.ts.map +1 -0
  61. package/dist/draw/view.js +16 -0
  62. package/dist/draw/view.js.map +1 -0
  63. package/dist/frame-cache.d.ts +103 -0
  64. package/dist/frame-cache.d.ts.map +1 -0
  65. package/dist/frame-cache.js +349 -0
  66. package/dist/frame-cache.js.map +1 -0
  67. package/dist/index.d.ts +162 -0
  68. package/dist/index.d.ts.map +1 -0
  69. package/dist/index.js +19 -0
  70. package/dist/index.js.map +1 -0
  71. package/dist/input.d.ts +81 -0
  72. package/dist/input.d.ts.map +1 -0
  73. package/dist/input.js +329 -0
  74. package/dist/input.js.map +1 -0
  75. package/dist/labels.d.ts +103 -0
  76. package/dist/labels.d.ts.map +1 -0
  77. package/dist/labels.js +203 -0
  78. package/dist/labels.js.map +1 -0
  79. package/dist/math.d.ts +33 -0
  80. package/dist/math.d.ts.map +1 -0
  81. package/dist/math.js +138 -0
  82. package/dist/math.js.map +1 -0
  83. package/dist/minimap.d.ts +56 -0
  84. package/dist/minimap.d.ts.map +1 -0
  85. package/dist/minimap.js +501 -0
  86. package/dist/minimap.js.map +1 -0
  87. package/dist/paint-stats.d.ts +17 -0
  88. package/dist/paint-stats.d.ts.map +1 -0
  89. package/dist/paint-stats.js +23 -0
  90. package/dist/paint-stats.js.map +1 -0
  91. package/dist/paint.d.ts +64 -0
  92. package/dist/paint.d.ts.map +1 -0
  93. package/dist/paint.js +197 -0
  94. package/dist/paint.js.map +1 -0
  95. package/dist/pick.d.ts +26 -0
  96. package/dist/pick.d.ts.map +1 -0
  97. package/dist/pick.js +125 -0
  98. package/dist/pick.js.map +1 -0
  99. package/dist/renderer.d.ts +28 -0
  100. package/dist/renderer.d.ts.map +1 -0
  101. package/dist/renderer.js +470 -0
  102. package/dist/renderer.js.map +1 -0
  103. package/dist/smooth-zoom.d.ts +21 -0
  104. package/dist/smooth-zoom.d.ts.map +1 -0
  105. package/dist/smooth-zoom.js +52 -0
  106. package/dist/smooth-zoom.js.map +1 -0
  107. package/dist/spatial.d.ts +26 -0
  108. package/dist/spatial.d.ts.map +1 -0
  109. package/dist/spatial.js +103 -0
  110. package/dist/spatial.js.map +1 -0
  111. package/dist/text.d.ts +36 -0
  112. package/dist/text.d.ts.map +1 -0
  113. package/dist/text.js +123 -0
  114. package/dist/text.js.map +1 -0
  115. package/package.json +47 -3
  116. package/src/atlas.ts +171 -0
  117. package/src/camera.ts +482 -0
  118. package/src/color.ts +58 -0
  119. package/src/ctx.ts +102 -0
  120. package/src/draw/background.ts +139 -0
  121. package/src/draw/badges.ts +93 -0
  122. package/src/draw/collapsed.ts +86 -0
  123. package/src/draw/edges.ts +135 -0
  124. package/src/draw/glyphs.ts +168 -0
  125. package/src/draw/halos.ts +101 -0
  126. package/src/draw/labels.ts +399 -0
  127. package/src/draw/link.ts +157 -0
  128. package/src/draw/nodes.ts +184 -0
  129. package/src/draw/shapes.ts +36 -0
  130. package/src/draw/view.ts +37 -0
  131. package/src/frame-cache.ts +382 -0
  132. package/src/index.ts +161 -0
  133. package/src/input.ts +370 -0
  134. package/src/labels.ts +269 -0
  135. package/src/math.ts +185 -0
  136. package/src/minimap.ts +545 -0
  137. package/src/paint-stats.ts +38 -0
  138. package/src/paint.ts +235 -0
  139. package/src/pick.ts +173 -0
  140. package/src/renderer.ts +539 -0
  141. package/src/smooth-zoom.ts +65 -0
  142. package/src/spatial.ts +94 -0
  143. package/src/text.ts +130 -0
package/dist/camera.js ADDED
@@ -0,0 +1,368 @@
1
+ import { clamp, easeInOutCubic } from './math.js';
2
+ import { smoothZoom } from './smooth-zoom.js';
3
+ export const NO_INSETS = Object.freeze({ top: 0, right: 0, bottom: 0, left: 0 });
4
+ /** Default fit padding (px). */
5
+ export const DEFAULT_PADDING = 48;
6
+ /** `flyTo` / `fit` never zoom in beyond this unless `maxZoom` says otherwise. */
7
+ export const DEFAULT_FLY_MAX_ZOOM = 2.5;
8
+ /** van Wijk–Nuij ρ (docs/visual-language.md §Replay). */
9
+ export const FLY_RHO = Math.SQRT2;
10
+ /** Time constant (ms) of the exponential approach used by animated wheel / button zoom. */
11
+ export const ZOOM_TAU = 80;
12
+ /** Time constant (ms) of the inertial glide after a drag. */
13
+ export const GLIDE_TAU = 325;
14
+ /** Glide stops below this speed (px/ms). */
15
+ export const GLIDE_MIN_SPEED = 0.02;
16
+ // ─── Pure math ───────────────────────────────────────────────────────────────
17
+ export function worldToScreen(s, size, p) {
18
+ return { x: (p.x - s.x) * s.k + size.width / 2, y: (p.y - s.y) * s.k + size.height / 2 };
19
+ }
20
+ export function screenToWorld(s, size, p) {
21
+ return { x: (p.x - size.width / 2) / s.k + s.x, y: (p.y - size.height / 2) / s.k + s.y };
22
+ }
23
+ export function viewportRect(s, size) {
24
+ const w = size.width / s.k;
25
+ const h = size.height / s.k;
26
+ return { x: s.x - w / 2, y: s.y - h / 2, width: w, height: h };
27
+ }
28
+ /** The state at zoom `k` that keeps the world point under screen point (sx, sy) in place. */
29
+ export function zoomAround(s, size, k, sx, sy) {
30
+ const wx = (sx - size.width / 2) / s.k + s.x;
31
+ const wy = (sy - size.height / 2) / s.k + s.y;
32
+ return { x: wx - (sx - size.width / 2) / k, y: wy - (sy - size.height / 2) / k, k };
33
+ }
34
+ export function resolvePadding(padding) {
35
+ if (padding === undefined) {
36
+ return {
37
+ top: DEFAULT_PADDING,
38
+ right: DEFAULT_PADDING,
39
+ bottom: DEFAULT_PADDING,
40
+ left: DEFAULT_PADDING,
41
+ };
42
+ }
43
+ if (typeof padding === 'number') {
44
+ const p = Number.isFinite(padding) ? Math.max(0, padding) : DEFAULT_PADDING;
45
+ return { top: p, right: p, bottom: p, left: p };
46
+ }
47
+ return padding;
48
+ }
49
+ /**
50
+ * Camera state that shows `bounds` inside the viewport minus `safe` (floating chrome) and
51
+ * `padding`, centred in that free region. Degenerate bounds (a single point) zoom to `maxK`.
52
+ * When insets leave no room they are dropped (safe area first, then padding).
53
+ */
54
+ export function fitState(bounds, size, padding, safe, minK, maxK) {
55
+ const attempts = [
56
+ [safe, padding],
57
+ [NO_INSETS, padding],
58
+ [NO_INSETS, NO_INSETS],
59
+ ];
60
+ let left = 0;
61
+ let top = 0;
62
+ let availW = size.width;
63
+ let availH = size.height;
64
+ for (const [s, p] of attempts) {
65
+ left = s.left + p.left;
66
+ top = s.top + p.top;
67
+ availW = size.width - left - s.right - p.right;
68
+ availH = size.height - top - s.bottom - p.bottom;
69
+ if (availW >= 8 && availH >= 8)
70
+ break;
71
+ }
72
+ availW = Math.max(availW, 1);
73
+ availH = Math.max(availH, 1);
74
+ const bw = Math.max(bounds.width, 0);
75
+ const bh = Math.max(bounds.height, 0);
76
+ let k = Math.min(bw > 0 ? availW / bw : Number.POSITIVE_INFINITY, bh > 0 ? availH / bh : Number.POSITIVE_INFINITY);
77
+ if (!Number.isFinite(k))
78
+ k = maxK;
79
+ k = clamp(k, minK, maxK);
80
+ const cx = bounds.x + bw / 2;
81
+ const cy = bounds.y + bh / 2;
82
+ const sx = left + availW / 2;
83
+ const sy = top + availH / 2;
84
+ return { x: cx - (sx - size.width / 2) / k, y: cy - (sy - size.height / 2) / k, k };
85
+ }
86
+ /** Flight duration: `clamp(S · 620 ms, 350, 1100)`. */
87
+ export function flyDuration(S) {
88
+ return clamp(Math.abs(S) * 620, 350, 1100);
89
+ }
90
+ /** Exponential velocity decay over `dt` ms. */
91
+ export function decay(v, dt, tau = GLIDE_TAU) {
92
+ return v * Math.exp(-dt / tau);
93
+ }
94
+ function validRect(r) {
95
+ return (Number.isFinite(r.x) &&
96
+ Number.isFinite(r.y) &&
97
+ Number.isFinite(r.width) &&
98
+ Number.isFinite(r.height) &&
99
+ r.width >= 0 &&
100
+ r.height >= 0);
101
+ }
102
+ /** The renderer's camera. Public methods implement `Camera`; the rest is driven by input. */
103
+ export class CameraController {
104
+ host;
105
+ minK;
106
+ maxK;
107
+ x = 0;
108
+ y = 0;
109
+ k = 1;
110
+ /** Set by any explicit camera call or user input; disables the automatic first fit. */
111
+ touched = false;
112
+ motion = null;
113
+ pending = null;
114
+ /** A user-driven change happened since the last `takeSource`. */
115
+ userChanged = false;
116
+ constructor(host, minK, maxK) {
117
+ this.host = host;
118
+ this.minK = minK;
119
+ this.maxK = maxK;
120
+ }
121
+ get() {
122
+ return { x: this.x, y: this.y, k: this.k };
123
+ }
124
+ set(state, source = 'program') {
125
+ this.touched = true;
126
+ this.stop();
127
+ this.apply(state.x, state.y, state.k, source);
128
+ }
129
+ flyTo(bounds, options = {}) {
130
+ this.touched = true;
131
+ this.stop();
132
+ if (!validRect(bounds))
133
+ return Promise.resolve();
134
+ const size = this.host.size();
135
+ if (size.width <= 0 || size.height <= 0) {
136
+ // Not laid out yet: apply (as a jump) on the first real size.
137
+ return new Promise((resolve) => {
138
+ this.pending = { bounds, options, resolve };
139
+ });
140
+ }
141
+ const target = this.targetFor(bounds, options, size);
142
+ const animate = (options.animate ?? true) && !this.host.reducedMotion();
143
+ const ref = Math.max(size.width, size.height);
144
+ const path = smoothZoom({ x: this.x, y: this.y, w: ref / this.k }, { x: target.x, y: target.y, w: ref / target.k }, FLY_RHO);
145
+ const duration = options.duration ?? flyDuration(path.S);
146
+ const still = Math.abs(target.k / this.k - 1) < 1e-6 &&
147
+ Math.hypot(target.x - this.x, target.y - this.y) * this.k < 0.5;
148
+ if (!animate || !(duration > 0) || still) {
149
+ this.apply(target.x, target.y, target.k, 'program');
150
+ return Promise.resolve();
151
+ }
152
+ return new Promise((resolve) => {
153
+ this.motion = { type: 'fly', path, ref, duration, start: -1, target, resolve };
154
+ this.host.invalidate();
155
+ });
156
+ }
157
+ fit(bounds, options) {
158
+ const b = bounds ?? this.host.contentBounds();
159
+ if (!b) {
160
+ this.touched = true;
161
+ this.stop();
162
+ return Promise.resolve();
163
+ }
164
+ return this.flyTo(b, options);
165
+ }
166
+ zoomBy(factor, around, options) {
167
+ this.touched = true;
168
+ if (!(factor > 0) || !Number.isFinite(factor))
169
+ return;
170
+ const size = this.host.size();
171
+ const ax = around?.x ?? size.width / 2;
172
+ const ay = around?.y ?? size.height / 2;
173
+ const animate = (options?.animate ?? true) && !this.host.reducedMotion();
174
+ if (animate)
175
+ this.zoomSmooth(factor, ax, ay, 'program');
176
+ else {
177
+ this.stop();
178
+ this.zoomNow(factor, ax, ay, 'program');
179
+ }
180
+ }
181
+ panBy(dx, dy) {
182
+ this.touched = true;
183
+ this.stop();
184
+ this.panNow(dx, dy, 'program');
185
+ }
186
+ worldToScreen(p) {
187
+ return worldToScreen(this, this.host.size(), p);
188
+ }
189
+ screenToWorld(p) {
190
+ return screenToWorld(this, this.host.size(), p);
191
+ }
192
+ viewport() {
193
+ return viewportRect(this, this.host.size());
194
+ }
195
+ // ─── Internal API (renderer, input) ───────────────────────────────────────
196
+ /** Whether a motion is running (the frame loop must keep ticking). */
197
+ get animating() {
198
+ return this.motion !== null;
199
+ }
200
+ /** User input started: stop every motion (resolving a pending flight). */
201
+ interrupt() {
202
+ this.touched = true;
203
+ this.stop();
204
+ }
205
+ /** Jump without marking the camera as touched (automatic first fit). */
206
+ jump(state) {
207
+ this.stop();
208
+ this.apply(state.x, state.y, state.k, 'program');
209
+ }
210
+ /** The state `fit` would end in (no motion). */
211
+ targetFor(bounds, options, size) {
212
+ const maxK = Math.min(this.maxK, options.maxZoom ?? DEFAULT_FLY_MAX_ZOOM);
213
+ return fitState(bounds, size, resolvePadding(options.padding), this.host.safeArea(), this.minK, Math.max(this.minK, maxK));
214
+ }
215
+ /** Move the content by (dx, dy) screen px immediately (input unless told otherwise). */
216
+ panNow(dx, dy, source = 'user') {
217
+ if (!Number.isFinite(dx) || !Number.isFinite(dy))
218
+ return;
219
+ this.apply(this.x - dx / this.k, this.y - dy / this.k, this.k, source);
220
+ }
221
+ /** Zoom by `factor` around screen point (ax, ay) immediately (pinch). */
222
+ zoomNow(factor, ax, ay, source = 'user') {
223
+ if (!(factor > 0) || !Number.isFinite(factor))
224
+ return;
225
+ if (this.motion?.type === 'zoom')
226
+ this.motion = null;
227
+ const k = clamp(this.k * factor, this.minK, this.maxK);
228
+ const s = zoomAround(this, this.host.size(), k, ax, ay);
229
+ this.apply(s.x, s.y, s.k, source);
230
+ }
231
+ /** Animated zoom toward `factor ×` the current target, anchored at (ax, ay) (wheel notches). */
232
+ zoomSmooth(factor, ax, ay, source = 'user') {
233
+ if (!(factor > 0) || !Number.isFinite(factor))
234
+ return;
235
+ const size = this.host.size();
236
+ const wx = (ax - size.width / 2) / this.k + this.x;
237
+ const wy = (ay - size.height / 2) / this.k + this.y;
238
+ const m = this.motion;
239
+ if (m?.type === 'zoom') {
240
+ m.kTarget = clamp(m.kTarget * factor, this.minK, this.maxK);
241
+ m.source = source;
242
+ m.ax = ax;
243
+ m.ay = ay;
244
+ m.wx = wx;
245
+ m.wy = wy;
246
+ }
247
+ else {
248
+ this.stop();
249
+ this.motion = {
250
+ type: 'zoom',
251
+ source,
252
+ ax,
253
+ ay,
254
+ wx,
255
+ wy,
256
+ kTarget: clamp(this.k * factor, this.minK, this.maxK),
257
+ last: -1,
258
+ };
259
+ }
260
+ this.host.invalidate();
261
+ }
262
+ /** Inertial glide with initial velocity (px/ms, content direction). */
263
+ glide(vx, vy) {
264
+ this.stop();
265
+ if (!(Math.hypot(vx, vy) > GLIDE_MIN_SPEED))
266
+ return;
267
+ this.motion = { type: 'glide', vx, vy, last: -1 };
268
+ this.host.invalidate();
269
+ }
270
+ /** The viewport size became valid: run a flight requested before layout (as a jump). */
271
+ resized() {
272
+ const p = this.pending;
273
+ if (!p)
274
+ return;
275
+ const size = this.host.size();
276
+ if (size.width <= 0 || size.height <= 0)
277
+ return;
278
+ this.pending = null;
279
+ const t = this.targetFor(p.bounds, p.options, size);
280
+ this.apply(t.x, t.y, t.k, 'program');
281
+ p.resolve();
282
+ }
283
+ /** Advance the running motion to time `now` (ms). Returns whether it is still running. */
284
+ tick(now) {
285
+ const m = this.motion;
286
+ if (!m)
287
+ return false;
288
+ switch (m.type) {
289
+ case 'fly': {
290
+ if (m.start < 0)
291
+ m.start = now;
292
+ const t = clamp((now - m.start) / m.duration, 0, 1);
293
+ if (t >= 1) {
294
+ this.motion = null;
295
+ this.apply(m.target.x, m.target.y, m.target.k, 'program');
296
+ m.resolve();
297
+ return false;
298
+ }
299
+ const v = m.path.at(easeInOutCubic(t));
300
+ this.apply(v.x, v.y, m.ref / v.w, 'program');
301
+ return true;
302
+ }
303
+ case 'zoom': {
304
+ const dt = m.last < 0 ? 16 : clamp(now - m.last, 0, 64);
305
+ m.last = now;
306
+ const lk = Math.log(this.k);
307
+ const lt = Math.log(m.kTarget);
308
+ const done = Math.abs(lt - lk) < 1e-3;
309
+ const k = done ? m.kTarget : Math.exp(lk + (lt - lk) * (1 - Math.exp(-dt / ZOOM_TAU)));
310
+ const size = this.host.size();
311
+ const kk = clamp(k, this.minK, this.maxK);
312
+ this.apply(m.wx - (m.ax - size.width / 2) / kk, m.wy - (m.ay - size.height / 2) / kk, kk, m.source);
313
+ if (done)
314
+ this.motion = null;
315
+ return !done;
316
+ }
317
+ case 'glide': {
318
+ const dt = m.last < 0 ? 16 : clamp(now - m.last, 0, 64);
319
+ m.last = now;
320
+ this.panNow(m.vx * dt, m.vy * dt, 'user');
321
+ m.vx = decay(m.vx, dt);
322
+ m.vy = decay(m.vy, dt);
323
+ if (Math.hypot(m.vx, m.vy) < GLIDE_MIN_SPEED) {
324
+ this.motion = null;
325
+ return false;
326
+ }
327
+ return true;
328
+ }
329
+ default: {
330
+ const never = m;
331
+ return never;
332
+ }
333
+ }
334
+ }
335
+ /** Stop the running motion and any pending flight, resolving their promises. */
336
+ stop() {
337
+ const m = this.motion;
338
+ this.motion = null;
339
+ if (m?.type === 'fly')
340
+ m.resolve();
341
+ const p = this.pending;
342
+ this.pending = null;
343
+ p?.resolve();
344
+ }
345
+ /**
346
+ * Source of the changes since the last call: 'user' if any of them came from input. The
347
+ * renderer reads it once per `camera` event (events are coalesced per frame).
348
+ */
349
+ takeSource() {
350
+ const source = this.userChanged ? 'user' : 'program';
351
+ this.userChanged = false;
352
+ return source;
353
+ }
354
+ apply(x, y, k, source) {
355
+ if (!Number.isFinite(x) || !Number.isFinite(y) || !Number.isFinite(k) || k <= 0)
356
+ return;
357
+ const kk = clamp(k, this.minK, this.maxK);
358
+ if (x === this.x && y === this.y && kk === this.k)
359
+ return;
360
+ this.x = x;
361
+ this.y = y;
362
+ this.k = kk;
363
+ if (source === 'user')
364
+ this.userChanged = true;
365
+ this.host.invalidate();
366
+ }
367
+ }
368
+ //# sourceMappingURL=camera.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"camera.js","sourceRoot":"","sources":["../src/camera.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ export interface Rgba {
2
+ readonly r: number;
3
+ readonly g: number;
4
+ readonly b: number;
5
+ /** [0, 1] */
6
+ readonly a: number;
7
+ }
8
+ /** Parse `#rgb`, `#rgba`, `#rrggbb`, `#rrggbbaa`, `rgb()` and `rgba()`; null for anything else. */
9
+ export declare function parseColor(input: string): Rgba | null;
10
+ /** `rgba()` string of `color` with its alpha multiplied by `alpha`. */
11
+ export declare function rgbaString(color: Rgba, alpha: number): string;
12
+ //# sourceMappingURL=color.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"color.d.ts","sourceRoot":"","sources":["../src/color.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,IAAI;IACnB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa;IACb,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;CACpB;AAID,mGAAmG;AACnG,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAOrD;AAgCD,uEAAuE;AACvE,wBAAgB,UAAU,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAG7D"}
package/dist/color.js ADDED
@@ -0,0 +1,51 @@
1
+ /** Minimal CSS color parsing for alpha ramps (halo sprites). Hex and rgb()/rgba() only. */
2
+ import { clamp } from './math.js';
3
+ const cache = new Map();
4
+ /** Parse `#rgb`, `#rgba`, `#rrggbb`, `#rrggbbaa`, `rgb()` and `rgba()`; null for anything else. */
5
+ export function parseColor(input) {
6
+ const hit = cache.get(input);
7
+ if (hit !== undefined)
8
+ return hit;
9
+ const parsed = parse(input.trim().toLowerCase());
10
+ if (cache.size > 512)
11
+ cache.clear();
12
+ cache.set(input, parsed);
13
+ return parsed;
14
+ }
15
+ function parse(s) {
16
+ if (s.startsWith('#')) {
17
+ const hex = s.slice(1);
18
+ if (!/^[0-9a-f]+$/.test(hex))
19
+ return null;
20
+ if (hex.length === 3 || hex.length === 4) {
21
+ const v = (i) => Number.parseInt(hex.charAt(i) + hex.charAt(i), 16);
22
+ return { r: v(0), g: v(1), b: v(2), a: hex.length === 4 ? v(3) / 255 : 1 };
23
+ }
24
+ if (hex.length === 6 || hex.length === 8) {
25
+ const v = (i) => Number.parseInt(hex.slice(i, i + 2), 16);
26
+ return { r: v(0), g: v(2), b: v(4), a: hex.length === 8 ? v(6) / 255 : 1 };
27
+ }
28
+ return null;
29
+ }
30
+ const m = /^rgba?\(([^)]*)\)$/.exec(s);
31
+ if (!m)
32
+ return null;
33
+ const parts = (m[1] ?? '').split(/[\s,/]+/).filter((p) => p.length > 0);
34
+ if (parts.length < 3 || parts.length > 4)
35
+ return null;
36
+ const channel = (p) => p.endsWith('%') ? Number.parseFloat(p) * 2.55 : Number.parseFloat(p);
37
+ const alpha = (p) => p === undefined ? 1 : p.endsWith('%') ? Number.parseFloat(p) / 100 : Number.parseFloat(p);
38
+ const r = channel(parts[0] ?? '');
39
+ const g = channel(parts[1] ?? '');
40
+ const b = channel(parts[2] ?? '');
41
+ const a = alpha(parts[3]);
42
+ if (![r, g, b, a].every(Number.isFinite))
43
+ return null;
44
+ return { r: clamp(r, 0, 255), g: clamp(g, 0, 255), b: clamp(b, 0, 255), a: clamp(a, 0, 1) };
45
+ }
46
+ /** `rgba()` string of `color` with its alpha multiplied by `alpha`. */
47
+ export function rgbaString(color, alpha) {
48
+ const a = Math.round(clamp(color.a * alpha, 0, 1) * 1000) / 1000;
49
+ return `rgba(${Math.round(color.r)}, ${Math.round(color.g)}, ${Math.round(color.b)}, ${a})`;
50
+ }
51
+ //# sourceMappingURL=color.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"color.js","sourceRoot":"","sources":["../src/color.ts"],"names":[],"mappings":"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"}
package/dist/ctx.d.ts ADDED
@@ -0,0 +1,57 @@
1
+ /**
2
+ * The slice of `CanvasRenderingContext2D` the renderer draws through.
3
+ *
4
+ * Every pass talks to this interface only, so drawing is testable with a recording mock
5
+ * (happy-dom has no 2D context) and works unchanged on `OffscreenCanvasRenderingContext2D`.
6
+ */
7
+ export interface Ctx2D {
8
+ globalAlpha: number;
9
+ fillStyle: string | CanvasGradient | CanvasPattern;
10
+ strokeStyle: string | CanvasGradient | CanvasPattern;
11
+ lineWidth: number;
12
+ lineCap: CanvasLineCap;
13
+ lineJoin: CanvasLineJoin;
14
+ miterLimit: number;
15
+ lineDashOffset: number;
16
+ font: string;
17
+ textAlign: CanvasTextAlign;
18
+ textBaseline: CanvasTextBaseline;
19
+ imageSmoothingEnabled: boolean;
20
+ save(): void;
21
+ restore(): void;
22
+ setTransform(a: number, b: number, c: number, d: number, e: number, f: number): void;
23
+ setLineDash(segments: readonly number[]): void;
24
+ beginPath(): void;
25
+ closePath(): void;
26
+ moveTo(x: number, y: number): void;
27
+ lineTo(x: number, y: number): void;
28
+ quadraticCurveTo(cpx: number, cpy: number, x: number, y: number): void;
29
+ arc(x: number, y: number, radius: number, startAngle: number, endAngle: number, counterclockwise?: boolean): void;
30
+ rect(x: number, y: number, w: number, h: number): void;
31
+ fill(): void;
32
+ stroke(): void;
33
+ clip(): void;
34
+ fillRect(x: number, y: number, w: number, h: number): void;
35
+ clearRect(x: number, y: number, w: number, h: number): void;
36
+ fillText(text: string, x: number, y: number): void;
37
+ strokeText(text: string, x: number, y: number): void;
38
+ measureText(text: string): {
39
+ readonly width: number;
40
+ };
41
+ drawImage(image: CanvasImageSource, dx: number, dy: number, dw: number, dh: number): void;
42
+ drawImage(image: CanvasImageSource, sx: number, sy: number, sw: number, sh: number, dx: number, dy: number, dw: number, dh: number): void;
43
+ createRadialGradient(x0: number, y0: number, r0: number, x1: number, y1: number, r1: number): CanvasGradient;
44
+ createPattern(image: CanvasImageSource, repetition: string | null): CanvasPattern | null;
45
+ }
46
+ /** An offscreen drawing surface (sprites, label atlas, grid tiles, exports). */
47
+ export interface Surface {
48
+ readonly canvas: HTMLCanvasElement | OffscreenCanvas;
49
+ readonly ctx: Ctx2D;
50
+ }
51
+ /** Creates offscreen surfaces; returns null where 2D canvases are unavailable. */
52
+ export type SurfaceFactory = (width: number, height: number) => Surface | null;
53
+ /** OffscreenCanvas when it works, else a detached `<canvas>`, else null. */
54
+ export declare const domSurfaceFactory: SurfaceFactory;
55
+ /** Shared empty dash pattern (solid line) so passes never allocate one. */
56
+ export declare const NO_DASH: readonly number[];
57
+ //# sourceMappingURL=ctx.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ctx.d.ts","sourceRoot":"","sources":["../src/ctx.ts"],"names":[],"mappings":"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"}
package/dist/ctx.js ADDED
@@ -0,0 +1,28 @@
1
+ /** OffscreenCanvas when it works, else a detached `<canvas>`, else null. */
2
+ export const domSurfaceFactory = (width, height) => {
3
+ const w = Math.max(1, Math.ceil(width));
4
+ const h = Math.max(1, Math.ceil(height));
5
+ if (typeof OffscreenCanvas === 'function') {
6
+ try {
7
+ const canvas = new OffscreenCanvas(w, h);
8
+ const ctx = canvas.getContext('2d');
9
+ if (ctx)
10
+ return { canvas, ctx };
11
+ }
12
+ catch {
13
+ // Fall through to a DOM canvas.
14
+ }
15
+ }
16
+ if (typeof document !== 'undefined') {
17
+ const canvas = document.createElement('canvas');
18
+ canvas.width = w;
19
+ canvas.height = h;
20
+ const ctx = canvas.getContext('2d');
21
+ if (ctx)
22
+ return { canvas, ctx };
23
+ }
24
+ return null;
25
+ };
26
+ /** Shared empty dash pattern (solid line) so passes never allocate one. */
27
+ export const NO_DASH = Object.freeze([]);
28
+ //# sourceMappingURL=ctx.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ctx.js","sourceRoot":"","sources":["../src/ctx.ts"],"names":[],"mappings":"AA6EA,4EAA4E;AAC5E,MAAM,CAAC,MAAM,iBAAiB,GAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE;IACjE,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IACxC,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;IACzC,IAAI,OAAO,eAAe,KAAK,UAAU,EAAE,CAAC;QAC1C,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YACzC,MAAM,GAAG,GAAG,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;YACpC,IAAI,GAAG;gBAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;QAClC,CAAC;QAAC,MAAM,CAAC;YACP,gCAAgC;QAClC,CAAC;IACH,CAAC;IACD,IAAI,OAAO,QAAQ,KAAK,WAAW,EAAE,CAAC;QACpC,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QAChD,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC;QACjB,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;QAClB,MAAM,GAAG,GAAG,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QACpC,IAAI,GAAG;YAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;IAClC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAEF,2EAA2E;AAC3E,MAAM,CAAC,MAAM,OAAO,GAAsB,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Background and dot grid.
3
+ *
4
+ * Dots (1.2 px) sit every 24 world units. When their screen spacing drops below 14.4 px they
5
+ * fade out (gone at 9.6 px, i.e. zoom 0.4) while the 4× coarser level stays, recursively, so the
6
+ * grid never moirés at any zoom. Each level is ONE `fillRect` with a repeating pattern whose
7
+ * tile is rasterized at the exact device-pixel spacing (cost independent of dot count).
8
+ */
9
+ import type { Theme } from '@kgdiff/scene';
10
+ import type { Ctx2D, SurfaceFactory } from '../ctx.js';
11
+ import type { View } from './view.js';
12
+ export declare const GRID_SPACING = 24;
13
+ export declare const GRID_DOT = 1.2;
14
+ /** Levels to draw at zoom `k`: [spacing (world), alpha, omit every 4th dot] pairs, coarse first. */
15
+ export declare function gridLevels(k: number): {
16
+ spacing: number;
17
+ alpha: number;
18
+ nested: boolean;
19
+ }[];
20
+ /** Pattern tiles per grid level, re-rasterized only when the device spacing changes. */
21
+ export declare class GridTiles {
22
+ private readonly factory;
23
+ private readonly tiles;
24
+ constructor(factory: SurfaceFactory);
25
+ clear(): void;
26
+ /**
27
+ * Pattern for a tile `size` device px wide holding `m × m` dots (the first omitted when
28
+ * `nested`, as the coarser level draws it).
29
+ */
30
+ pattern(ctx: Ctx2D, slot: number, size: number, m: number, nested: boolean, color: string, dotR: number): CanvasPattern | null;
31
+ }
32
+ export declare function drawBackground(ctx: Ctx2D, v: View, theme: Theme, tiles: GridTiles | null, spotlight: number): void;
33
+ //# sourceMappingURL=background.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"background.d.ts","sourceRoot":"","sources":["../../src/draw/background.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,KAAK,EAAE,KAAK,EAAW,cAAc,EAAE,MAAM,WAAW,CAAC;AAEhE,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEtC,eAAO,MAAM,YAAY,KAAK,CAAC;AAC/B,eAAO,MAAM,QAAQ,MAAM,CAAC;AAI5B,oGAAoG;AACpG,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,EAAE,CAU3F;AAQD,wFAAwF;AACxF,qBAAa,SAAS;IAGR,OAAO,CAAC,QAAQ,CAAC,OAAO;IAFpC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAiC;IAEvD,YAA6B,OAAO,EAAE,cAAc,EAAI;IAExD,KAAK,IAAI,IAAI,CAGZ;IAED;;;OAGG;IACH,OAAO,CACL,GAAG,EAAE,KAAK,EACV,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,CAAC,EAAE,MAAM,EACT,MAAM,EAAE,OAAO,EACf,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,GACX,aAAa,GAAG,IAAI,CA+BtB;CACF;AAED,wBAAgB,cAAc,CAC5B,GAAG,EAAE,KAAK,EACV,CAAC,EAAE,IAAI,EACP,KAAK,EAAE,KAAK,EACZ,KAAK,EAAE,SAAS,GAAG,IAAI,EACvB,SAAS,EAAE,MAAM,GAChB,IAAI,CAsCN"}