@lancercomet/zoom-pan 0.1.0 → 0.1.1

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.
package/dist/index.mjs ADDED
@@ -0,0 +1,812 @@
1
+ const t = async (t2, s2) => new Promise((i2, h2) => {
2
+ const e2 = new Image();
3
+ "string" == typeof t2 ? (void 0 !== s2 && (e2.crossOrigin = s2), e2.src = t2) : e2.src = URL.createObjectURL(t2), e2.onload = () => {
4
+ i2(e2);
5
+ }, e2.onerror = () => {
6
+ h2(new Error("Image load failed"));
7
+ };
8
+ }), s = (t2, s2, i2) => Math.min(Math.max(t2, s2), i2);
9
+ class i {
10
+ canvas;
11
+ context;
12
+ contentCanvas;
13
+ contentContext;
14
+ topScreenCanvas;
15
+ topScreenContext;
16
+ t;
17
+ i;
18
+ h;
19
+ o = [];
20
+ l = /* @__PURE__ */ new Map();
21
+ u = false;
22
+ M = false;
23
+ m;
24
+ p = true;
25
+ _ = 0;
26
+ v = performance.now();
27
+ L = 0;
28
+ R = 0;
29
+ S = 0;
30
+ C = 0;
31
+ A = Math.log(1);
32
+ T = Math.log(1);
33
+ LOG_MIN;
34
+ LOG_MAX;
35
+ P = /* @__PURE__ */ new Set();
36
+ B = /* @__PURE__ */ new Set();
37
+ I = /* @__PURE__ */ new Set();
38
+ get zoom() {
39
+ return Math.exp(this.A);
40
+ }
41
+ get minZoom() {
42
+ return this.i.minZoom;
43
+ }
44
+ get maxZoom() {
45
+ return this.i.maxZoom;
46
+ }
47
+ D = Math.max(1, window.devicePixelRatio || 1);
48
+ get dpr() {
49
+ return this.D;
50
+ }
51
+ use(t2) {
52
+ return this.l.has(t2.name) || (this.l.set(t2.name, t2), t2.install(this)), t2;
53
+ }
54
+ unuse(t2) {
55
+ const s2 = this.l.get(t2);
56
+ s2 && (s2.destroy(), this.l.delete(t2));
57
+ }
58
+ getPlugin(t2) {
59
+ return this.l.get(t2);
60
+ }
61
+ onUpdate(t2) {
62
+ this.P.add(t2);
63
+ }
64
+ offUpdate(t2) {
65
+ this.P.delete(t2);
66
+ }
67
+ onBeforeRender(t2) {
68
+ this.B.add(t2);
69
+ }
70
+ offBeforeRender(t2) {
71
+ this.B.delete(t2);
72
+ }
73
+ onAfterRender(t2) {
74
+ this.I.add(t2);
75
+ }
76
+ offAfterRender(t2) {
77
+ this.I.delete(t2);
78
+ }
79
+ requestRender() {
80
+ this.p = true;
81
+ }
82
+ F(t2) {
83
+ return s(t2, this.LOG_MIN, this.LOG_MAX);
84
+ }
85
+ k(t2, s2, i2) {
86
+ Number.isFinite(i2) && (this.S = t2, this.C = s2, this.T = this.F(i2), this.p = true);
87
+ }
88
+ zoomToAtScreen(t2, s2, i2) {
89
+ this.k(t2, s2, Math.log(i2));
90
+ }
91
+ zoomToAtScreenRaw(t2, i2, h2) {
92
+ if (!Number.isFinite(h2)) return;
93
+ const e2 = Math.max(1e-8, this.i.minZoom), n2 = this.i.maxZoom, r2 = s(h2, e2, n2), o2 = Math.exp(this.A), a2 = r2;
94
+ if (!Number.isFinite(o2) || o2 <= 0) return;
95
+ if (Math.abs(a2 - o2) < 1e-12) return;
96
+ const c2 = Math.log(r2);
97
+ this.A = c2, this.T = c2;
98
+ const l2 = a2 / o2;
99
+ this.L = t2 - (t2 - this.L) * l2, this.R = i2 - (i2 - this.R) * l2, this.p = true;
100
+ }
101
+ zoomToAtWorld(t2, s2, i2) {
102
+ const { x: h2, y: e2 } = this.toScreen(t2, s2);
103
+ this.zoomToAtScreen(h2, e2, i2);
104
+ }
105
+ zoomByFactorAtScreen(t2, s2, i2) {
106
+ if (i2 <= 0 || !Number.isFinite(i2)) return;
107
+ const h2 = Math.log(i2);
108
+ this.k(t2, s2, this.T + h2);
109
+ }
110
+ zoomByLogAtScreen(t2, s2, i2) {
111
+ this.k(t2, s2, this.T + i2);
112
+ }
113
+ zoomByFactorAtWorld(t2, s2, i2) {
114
+ const { x: h2, y: e2 } = this.toScreen(t2, s2);
115
+ this.zoomByFactorAtScreen(h2, e2, i2);
116
+ }
117
+ zoomInAtCenter() {
118
+ const t2 = this.canvas.getBoundingClientRect(), s2 = t2.width / 2, i2 = t2.height / 2;
119
+ this.zoomByFactorAtScreen(s2, i2, 1.2);
120
+ }
121
+ zoomOutAtCenter() {
122
+ const t2 = this.canvas.getBoundingClientRect(), s2 = t2.width / 2, i2 = t2.height / 2;
123
+ this.zoomByFactorAtScreen(s2, i2, 1 / 1.2);
124
+ }
125
+ panBy(t2, s2) {
126
+ this.L += t2, this.R += s2, this.p = true;
127
+ }
128
+ setPan(t2, s2) {
129
+ this.L = t2, this.R = s2, this.p = true;
130
+ }
131
+ setTransform(t2, i2, h2) {
132
+ const e2 = s(t2, this.i.minZoom, this.i.maxZoom);
133
+ this.A = Math.log(e2), this.T = this.A, this.L = i2, this.R = h2, this.p = true;
134
+ }
135
+ Z(t2, s2) {
136
+ t2.width === s2.width && t2.height === s2.height || (t2.width = s2.width, t2.height = s2.height);
137
+ }
138
+ U() {
139
+ if (this.M) return void (this._ = requestAnimationFrame(() => this.U()));
140
+ const t2 = performance.now(), s2 = Math.max(1, t2 - this.v);
141
+ this.v = t2;
142
+ const { approachKZoom: i2 } = this.i, h2 = Math.exp(this.A), e2 = this.T - this.A, n2 = Math.abs(e2) > 1e-6;
143
+ if (n2) {
144
+ const t3 = 1 - Math.exp(-i2 * s2);
145
+ this.A += e2 * t3;
146
+ }
147
+ const r2 = Math.exp(this.A);
148
+ if (r2 !== h2) {
149
+ const t3 = this.S, s3 = this.C, i3 = r2 / h2;
150
+ this.L = t3 - (t3 - this.L) * i3, this.R = s3 - (s3 - this.R) * i3;
151
+ }
152
+ if (this.u) {
153
+ const t3 = 1 - Math.exp(-this.i.approachKPan * s2);
154
+ this.L += (0 - this.L) * t3, this.R += (0 - this.R) * t3;
155
+ const i3 = Math.abs(this.A) < 1e-3 && Math.abs(this.T) < 1e-6, h3 = Math.abs(this.L) < 0.5 && Math.abs(this.R) < 0.5;
156
+ i3 && h3 && (this.A = 0, this.T = 0, this.L = 0, this.R = 0, this.u = false);
157
+ }
158
+ for (const t3 of this.P) t3(s2);
159
+ if (!(this.p || n2 || this.u)) return void (this._ = requestAnimationFrame(() => this.U()));
160
+ this.p = false;
161
+ const o2 = this.contentCanvas, a2 = this.contentContext, c2 = this.topScreenCanvas, l2 = this.topScreenContext, u2 = this.canvas, d2 = this.context;
162
+ this.Z(o2, u2), this.Z(c2, u2), a2.setTransform(1, 0, 0, 1, 0, 0), l2.setTransform(1, 0, 0, 1, 0, 0), d2.setTransform(1, 0, 0, 1, 0, 0);
163
+ const f2 = this.i.background;
164
+ "string" == typeof f2 && "" !== f2.trim() && "transparent" !== f2.toLowerCase() ? (d2.fillStyle = f2, d2.fillRect(0, 0, u2.width, u2.height)) : d2.clearRect(0, 0, u2.width, u2.height), a2.clearRect(0, 0, o2.width, o2.height), l2.clearRect(0, 0, c2.width, c2.height), a2.setTransform(this.D * r2, 0, 0, this.D * r2, this.D * this.L, this.D * this.R);
165
+ for (const t3 of this.B) t3(a2);
166
+ this.t(this);
167
+ for (const t3 of this.I) t3(a2);
168
+ d2.drawImage(o2, 0, 0), d2.drawImage(c2, 0, 0), this._ = requestAnimationFrame(() => this.U());
169
+ }
170
+ applyWorldTransform(t2) {
171
+ const s2 = Math.exp(this.A);
172
+ t2.setTransform(this.D * s2, 0, 0, this.D * s2, this.D * this.L, this.D * this.R);
173
+ }
174
+ applyScreenTransform(t2) {
175
+ t2.setTransform(this.D, 0, 0, this.D, 0, 0);
176
+ }
177
+ getPixelColorAtScreen(t2, s2) {
178
+ const i2 = Math.floor(t2 * this.D), h2 = Math.floor(s2 * this.D);
179
+ if (i2 < 0 || h2 < 0 || i2 >= this.canvas.width || h2 >= this.canvas.height) return { r: 0, g: 0, b: 0, a: 0, rgba: "rgba(0,0,0,0)", hex: "#000000" };
180
+ const e2 = this.contentContext.getImageData(i2, h2, 1, 1).data, n2 = e2[0], r2 = e2[1], o2 = e2[2], a2 = e2[3] / 255, c2 = (t3) => t3.toString(16).padStart(2, "0"), l2 = `#${c2(n2)}${c2(r2)}${c2(o2)}`;
181
+ return { r: n2, g: r2, b: o2, a: a2, rgba: `rgba(${n2},${r2},${o2},${a2.toFixed(3)})`, hex: l2 };
182
+ }
183
+ getPixelColorAtWorld(t2, s2) {
184
+ const { x: i2, y: h2 } = this.toScreen(t2, s2);
185
+ return this.getPixelColorAtScreen(i2, h2);
186
+ }
187
+ registerLayerManager(t2) {
188
+ t2 && (this.o.includes(t2) || (this.o.push(t2), this.p = true));
189
+ }
190
+ unregisterLayerManager(t2) {
191
+ const s2 = this.o.indexOf(t2);
192
+ s2 >= 0 && (this.o.splice(s2, 1), this.p = true);
193
+ }
194
+ getLayerManagers() {
195
+ return [...this.o];
196
+ }
197
+ resetSmooth() {
198
+ this.u = true, this.T = 0, this.p = true;
199
+ }
200
+ resetInstant() {
201
+ this.A = 0, this.T = 0, this.L = 0, this.R = 0, this.p = true;
202
+ }
203
+ toWorld(t2, s2) {
204
+ const i2 = Math.exp(this.A);
205
+ return { wx: (t2 - this.L) / i2, wy: (s2 - this.R) / i2 };
206
+ }
207
+ toScreen(t2, s2) {
208
+ const i2 = Math.exp(this.A);
209
+ return { x: t2 * i2 + this.L, y: s2 * i2 + this.R };
210
+ }
211
+ getTransform() {
212
+ return { zoom: Math.exp(this.A), tx: this.L, ty: this.R };
213
+ }
214
+ getViewportBounds() {
215
+ const t2 = Math.exp(this.A), s2 = this.canvas.width / this.D, i2 = this.canvas.height / this.D, h2 = -this.L / t2, e2 = -this.R / t2, n2 = (s2 - this.L) / t2, r2 = (i2 - this.R) / t2;
216
+ return { left: h2, top: e2, right: n2, bottom: r2, width: n2 - h2, height: r2 - e2 };
217
+ }
218
+ setZoomRange(t2, s2) {
219
+ this.i.minZoom = t2, this.i.maxZoom = s2, this.LOG_MIN = Math.log(t2), this.LOG_MAX = Math.log(s2), this.T = Math.min(this.LOG_MAX, Math.max(this.LOG_MIN, this.T));
220
+ }
221
+ resizeToParent() {
222
+ this.M = true;
223
+ const t2 = (this.canvas.parentElement || this.canvas).getBoundingClientRect();
224
+ this.D = Math.max(1, window.devicePixelRatio || 1);
225
+ const s2 = Math.max(1, Math.round(t2.width)), i2 = Math.max(1, Math.round(t2.height));
226
+ this.canvas.width = Math.round(s2 * this.D), this.canvas.height = Math.round(i2 * this.D), this.canvas.style.width = `${s2}px`, this.canvas.style.height = `${i2}px`, this.Z(this.contentCanvas, this.canvas), this.Z(this.topScreenCanvas, this.canvas), clearTimeout(this.m), this.m = window.setTimeout(() => {
227
+ this.M = false;
228
+ }, 50);
229
+ }
230
+ destroy() {
231
+ cancelAnimationFrame(this._);
232
+ for (const t2 of this.l.values()) t2.destroy();
233
+ this.l.clear(), this.h && this.h.disconnect(), this.o = [], this.P.clear(), this.B.clear(), this.I.clear();
234
+ }
235
+ constructor(t2, s2, i2) {
236
+ const h2 = t2.getContext("2d", { willReadFrequently: true, alpha: true });
237
+ if (!h2) throw new Error("2D context not available");
238
+ this.canvas = t2, this.context = h2, this.t = s2, this.contentCanvas = document.createElement("canvas"), this.contentCanvas.width = t2.width, this.contentCanvas.height = t2.height, this.contentContext = this.contentCanvas.getContext("2d", { alpha: true, willReadFrequently: true }), this.topScreenCanvas = document.createElement("canvas"), this.topScreenCanvas.width = t2.width, this.topScreenCanvas.height = t2.height, this.topScreenContext = this.topScreenCanvas.getContext("2d", { alpha: true }), this.i = { minZoom: 0.5, maxZoom: 10, approachKZoom: 0.022, approachKPan: 0.022, autoResize: true, background: "#fff", ...i2 }, this.LOG_MIN = Math.log(this.i.minZoom), this.LOG_MAX = Math.log(this.i.maxZoom), this.i.autoResize && (this.h = new ResizeObserver(() => this.resizeToParent()), this.h.observe(this.canvas.parentElement || this.canvas)), this.resizeToParent(), this.v = performance.now(), this._ = requestAnimationFrame(() => this.U());
239
+ }
240
+ }
241
+ let h = 0;
242
+ class e {
243
+ id;
244
+ type;
245
+ name;
246
+ space = "world";
247
+ visible = true;
248
+ opacity = 1;
249
+ blend = "source-over";
250
+ constructor(t2, s2, i2 = "world") {
251
+ this.name = t2, this.id = `layer_${s2}_${++h}`, this.type = s2, this.space = i2;
252
+ }
253
+ }
254
+ class n extends e {
255
+ W;
256
+ canvas;
257
+ context;
258
+ x = 0;
259
+ y = 0;
260
+ scale = 1;
261
+ rotation = 0;
262
+ anchor = "topLeft";
263
+ $ = false;
264
+ q = 0;
265
+ O = 0;
266
+ beginStroke(t2, s2) {
267
+ const { lx: i2, ly: h2 } = this.toLocalPoint(t2, s2);
268
+ this.q = i2, this.O = h2, this.$ = true;
269
+ }
270
+ stroke(t2, s2, i2, h2, e2 = 1, n2 = "brush") {
271
+ if (!this.$) return;
272
+ const { lx: r2, ly: o2 } = this.toLocalPoint(t2, s2);
273
+ this.context.beginPath(), this.context.moveTo(this.q, this.O), this.context.lineTo(r2, o2), "eraser" === n2 ? (this.context.globalCompositeOperation = "destination-out", this.context.strokeStyle = "rgba(0, 0, 0, 1)") : (this.context.globalCompositeOperation = "source-over", this.context.strokeStyle = i2), this.context.lineWidth = h2 * e2, this.context.lineCap = "round", this.context.lineJoin = "round", this.context.stroke(), this.context.closePath(), this.q = r2, this.O = o2;
274
+ }
275
+ endStroke() {
276
+ this.$ = false;
277
+ }
278
+ isDrawing() {
279
+ return this.$;
280
+ }
281
+ captureSnapshot(t2) {
282
+ try {
283
+ if (t2) {
284
+ const { x: s2, y: i2, width: h2, height: e2 } = t2, n2 = Math.max(0, Math.floor(s2)), r2 = Math.max(0, Math.floor(i2)), o2 = Math.min(this.canvas.width - n2, Math.ceil(h2)), a2 = Math.min(this.canvas.height - r2, Math.ceil(e2));
285
+ return o2 <= 0 || a2 <= 0 ? null : this.context.getImageData(n2, r2, o2, a2);
286
+ }
287
+ return this.context.getImageData(0, 0, this.canvas.width, this.canvas.height);
288
+ } catch {
289
+ return null;
290
+ }
291
+ }
292
+ restoreSnapshot(t2, s2) {
293
+ const i2 = s2?.x ?? 0, h2 = s2?.y ?? 0;
294
+ this.context.putImageData(t2, i2, h2);
295
+ }
296
+ clearRegion(t2) {
297
+ t2 ? this.context.clearRect(t2.x, t2.y, t2.width, t2.height) : this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
298
+ }
299
+ requestRedraw() {
300
+ this.W?.(this.context, this.canvas);
301
+ }
302
+ drawImage(t2, s2, i2, h2, e2) {
303
+ this.context.drawImage(t2, s2, i2, h2 ?? t2.width, e2 ?? t2.height);
304
+ }
305
+ hitTest(t2, s2) {
306
+ const { lx: i2, ly: h2 } = this.toLocalPoint(t2, s2);
307
+ return i2 >= 0 && i2 <= this.canvas.width && h2 >= 0 && h2 <= this.canvas.height;
308
+ }
309
+ toLocalPoint(t2, s2) {
310
+ const i2 = t2 - this.x, h2 = s2 - this.y, e2 = Math.cos(-this.rotation), n2 = Math.sin(-this.rotation), r2 = i2 * n2 + h2 * e2, o2 = (i2 * e2 - h2 * n2) / this.scale, a2 = r2 / this.scale;
311
+ return { lx: o2 + ("center" === this.anchor ? this.canvas.width / 2 : 0), ly: a2 + ("center" === this.anchor ? this.canvas.height / 2 : 0) };
312
+ }
313
+ render(t2, s2) {
314
+ if (!this.visible) return;
315
+ const i2 = this.canvas.width * this.scale, h2 = this.canvas.height * this.scale, e2 = "center" === this.anchor ? -i2 / 2 : 0, n2 = "center" === this.anchor ? -h2 / 2 : 0;
316
+ t2.save(), t2.globalAlpha = this.opacity, t2.globalCompositeOperation = this.blend, t2.translate(this.x, this.y), t2.rotate(this.rotation), t2.drawImage(this.canvas, e2, n2, i2, h2), t2.restore();
317
+ }
318
+ cropTo(t2) {
319
+ const s2 = Math.max(1, Math.floor(t2.width)), i2 = Math.max(1, Math.floor(t2.height));
320
+ if (s2 === this.canvas.width && i2 === this.canvas.height) return;
321
+ const h2 = this.N(), e2 = Math.min(h2.width, s2), n2 = Math.min(h2.height, i2);
322
+ this.V(s2, i2), e2 > 0 && n2 > 0 && this.context.drawImage(h2, 0, 0, e2, n2, 0, 0, e2, n2);
323
+ }
324
+ resizeTo(t2) {
325
+ const s2 = Math.max(1, Math.floor(t2.width)), i2 = Math.max(1, Math.floor(t2.height));
326
+ if (s2 === this.canvas.width && i2 === this.canvas.height) return;
327
+ const h2 = this.N();
328
+ this.V(s2, i2), h2.width > 0 && h2.height > 0 && this.context.drawImage(h2, 0, 0, h2.width, h2.height, 0, 0, s2, i2);
329
+ }
330
+ N() {
331
+ const t2 = document.createElement("canvas");
332
+ if (t2.width = this.canvas.width, t2.height = this.canvas.height, 0 === t2.width || 0 === t2.height) return t2;
333
+ const s2 = t2.getContext("2d");
334
+ if (!s2) throw new Error("Offscreen 2D context unavailable");
335
+ return s2.drawImage(this.canvas, 0, 0), t2;
336
+ }
337
+ V(t2, s2) {
338
+ this.canvas.width = t2, this.canvas.height = s2, this.context.setTransform(1, 0, 0, 1, 0, 0), this.context.clearRect(0, 0, t2, s2);
339
+ }
340
+ destroy() {
341
+ this.canvas.width = 0, this.canvas.height = 0;
342
+ }
343
+ constructor(t2) {
344
+ super(t2.name || "", "canvas", t2.space ?? "world"), this.canvas = document.createElement("canvas"), this.canvas.width = t2.width, this.canvas.height = t2.height;
345
+ const s2 = this.canvas.getContext("2d", { willReadFrequently: true });
346
+ if (!s2) throw new Error("Offscreen 2D context unavailable");
347
+ this.context = s2, this.x = t2.x || 0, this.y = t2.y || 0, this.scale = t2.scale ?? 1, this.rotation = t2.rotation || 0, t2.anchor && (this.anchor = t2.anchor), this.W = t2.redraw, this.W && this.W(this.context, this.canvas);
348
+ }
349
+ }
350
+ class r extends n {
351
+ #t = null;
352
+ static async fromImage(s2) {
353
+ const i2 = await t(s2.src, s2.crossOrigin), h2 = s2.width ?? i2.naturalWidth, e2 = s2.height ?? i2.naturalHeight, n2 = new r({ name: s2.name, space: s2.space ?? "world", x: s2.x ?? 0, y: s2.y ?? 0, scale: s2.scale ?? 1, rotation: s2.rotation ?? 0, anchor: s2.anchor ?? "topLeft", width: h2, height: e2 });
354
+ return n2.context.clearRect(0, 0, n2.canvas.width, n2.canvas.height), n2.context.drawImage(i2, 0, 0, h2, e2), "string" != typeof s2.src && (n2.#t = i2.src.startsWith("blob:") ? i2.src : null), n2;
355
+ }
356
+ async setSource(s2, i2) {
357
+ const h2 = await t(s2, i2);
358
+ if (this.canvas.width = h2.naturalWidth, this.canvas.height = h2.naturalHeight, this.context.setTransform(1, 0, 0, 1, 0, 0), this.context.clearRect(0, 0, this.canvas.width, this.canvas.height), this.context.drawImage(h2, 0, 0), this.#t) {
359
+ try {
360
+ URL.revokeObjectURL(this.#t);
361
+ } catch {
362
+ }
363
+ this.#t = null;
364
+ }
365
+ "string" != typeof s2 && (this.#t = h2.src.startsWith("blob:") ? h2.src : null);
366
+ }
367
+ paint(t2) {
368
+ t2(this.context, this.canvas);
369
+ }
370
+ getImageData(t2 = 0, s2 = 0, i2 = this.canvas.width, h2 = this.canvas.height) {
371
+ return this.context.getImageData(t2, s2, i2, h2);
372
+ }
373
+ putImageData(t2, s2 = 0, i2 = 0) {
374
+ this.context.putImageData(t2, s2, i2);
375
+ }
376
+ toDataURL(t2 = "image/png", s2) {
377
+ return this.canvas.toDataURL(t2, s2);
378
+ }
379
+ toImageBitmap(t2) {
380
+ return createImageBitmap(this.canvas, t2 ?? {});
381
+ }
382
+ destroy() {
383
+ if (super.destroy?.(), this.#t) {
384
+ try {
385
+ URL.revokeObjectURL(this.#t);
386
+ } catch {
387
+ }
388
+ this.#t = null;
389
+ }
390
+ }
391
+ constructor(t2) {
392
+ super({ name: t2.name, space: t2.space ?? "world", x: t2.x, y: t2.y, scale: t2.scale, rotation: t2.rotation, anchor: t2.anchor ?? "topLeft", width: t2.width, height: t2.height }), this.type = "bitmap";
393
+ }
394
+ }
395
+ class o {
396
+ H = [];
397
+ X = [];
398
+ K(t2, s2) {
399
+ s2.save(), t2.applyWorldTransform(s2);
400
+ for (const i2 of this.H) !i2.visible || i2.opacity <= 0 || (s2.save(), i2.render(s2, t2), s2.restore());
401
+ s2.restore(), s2.save(), t2.applyScreenTransform(s2);
402
+ for (const i2 of this.X) !i2.visible || i2.opacity <= 0 || (s2.save(), i2.render(s2, t2), s2.restore());
403
+ s2.restore();
404
+ }
405
+ addLayer(t2, s2) {
406
+ const i2 = "world" === t2.space ? this.H : this.X;
407
+ return "number" == typeof s2 && s2 >= 0 && s2 < i2.length ? (i2.splice(s2, 0, t2), t2.id) : (i2.push(t2), t2.id);
408
+ }
409
+ async createImageLayer(t2) {
410
+ const s2 = await r.fromImage(t2);
411
+ return this.addLayer(s2), s2;
412
+ }
413
+ createCanvasLayer(t2) {
414
+ const s2 = new n(t2);
415
+ return this.addLayer(s2), s2;
416
+ }
417
+ removeLayer(t2) {
418
+ const s2 = this.H.findIndex((s3) => s3.id === t2);
419
+ if (s2 >= 0) return this.H[s2].destroy?.(), void this.H.splice(s2, 1);
420
+ const i2 = this.X.findIndex((s3) => s3.id === t2);
421
+ i2 >= 0 && (this.X[i2].destroy?.(), this.X.splice(i2, 1));
422
+ }
423
+ moveLayer(t2, s2) {
424
+ const i2 = this.H.findIndex((s3) => s3.id === t2);
425
+ if (i2 >= 0) {
426
+ const [t3] = this.H.splice(i2, 1), h3 = Math.max(0, Math.min(s2, this.H.length));
427
+ return void this.H.splice(h3, 0, t3);
428
+ }
429
+ const h2 = this.X.findIndex((s3) => s3.id === t2);
430
+ if (h2 >= 0) {
431
+ const [t3] = this.X.splice(h2, 1), i3 = Math.max(0, Math.min(s2, this.X.length));
432
+ this.X.splice(i3, 0, t3);
433
+ }
434
+ }
435
+ getLayer(t2) {
436
+ return this.H.find((s2) => s2.id === t2) || this.X.find((s2) => s2.id === t2);
437
+ }
438
+ getAllLayers(t2) {
439
+ return t2 ? ("world" === t2 ? this.H : this.X).slice() : [...this.H, ...this.X];
440
+ }
441
+ hitTest(t2, s2, i2 = "world") {
442
+ const h2 = this.getAllLayers(i2);
443
+ for (let i3 = h2.length - 1; i3 >= 0; i3--) {
444
+ const e2 = h2[i3];
445
+ if (e2.hitTest && e2.hitTest(t2, s2)) return e2;
446
+ }
447
+ }
448
+ destroy() {
449
+ for (const t2 of [...this.H, ...this.X]) t2.destroy?.();
450
+ this.H = [], this.X = [];
451
+ }
452
+ }
453
+ class a extends o {
454
+ Y = null;
455
+ G = null;
456
+ j = true;
457
+ J = 0;
458
+ tt = 0;
459
+ st = 0;
460
+ it = 0;
461
+ markDirty() {
462
+ this.j = true;
463
+ }
464
+ addLayer(t2, s2) {
465
+ return this.j = true, super.addLayer(t2, s2);
466
+ }
467
+ removeLayer(t2) {
468
+ this.j = true, super.removeLayer(t2);
469
+ }
470
+ moveLayer(t2, s2) {
471
+ this.j = true, super.moveLayer(t2, s2);
472
+ }
473
+ renderAllLayersIn(t2) {
474
+ const s2 = t2.contentContext, i2 = this.H;
475
+ 0 !== i2.length && (this.j && this.ht(i2), this.Y && this.G && s2.drawImage(this.Y, this.st, this.it));
476
+ }
477
+ ht(t2) {
478
+ let s2 = 0, i2 = 0, h2 = 0, e2 = 0, n2 = false;
479
+ for (const r3 of t2) {
480
+ const t3 = r3, o3 = t3.canvas.width * t3.scale, a3 = t3.canvas.height * t3.scale, c2 = "center" === t3.anchor ? -o3 / 2 : 0, l2 = "center" === t3.anchor ? -a3 / 2 : 0, u2 = Math.cos(t3.rotation), d2 = Math.sin(t3.rotation), f2 = [{ x: c2, y: l2 }, { x: c2 + o3, y: l2 }, { x: c2, y: l2 + a3 }, { x: c2 + o3, y: l2 + a3 }];
481
+ let M2 = 1 / 0, m2 = 1 / 0, p2 = -1 / 0, g = -1 / 0;
482
+ for (const s3 of f2) {
483
+ const i3 = s3.x * u2 - s3.y * d2 + t3.x, h3 = s3.x * d2 + s3.y * u2 + t3.y;
484
+ M2 = Math.min(M2, i3), m2 = Math.min(m2, h3), p2 = Math.max(p2, i3), g = Math.max(g, h3);
485
+ }
486
+ n2 ? (s2 = Math.min(s2, M2), i2 = Math.min(i2, m2), h2 = Math.max(h2, p2), e2 = Math.max(e2, g)) : (s2 = M2, i2 = m2, h2 = p2, e2 = g, n2 = true);
487
+ }
488
+ if (!n2) return void (this.j = false);
489
+ const r2 = Math.ceil(h2 - s2), o2 = Math.ceil(e2 - i2);
490
+ this.Y || (this.Y = document.createElement("canvas"), this.G = this.Y.getContext("2d", { alpha: true })), this.J === r2 && this.tt === o2 || (this.Y.width = r2, this.Y.height = o2, this.J = r2, this.tt = o2), this.st = s2, this.it = i2;
491
+ const a2 = this.G;
492
+ a2.clearRect(0, 0, r2, o2), a2.save(), a2.translate(-s2, -i2);
493
+ for (const s3 of t2) !s3.visible || s3.opacity <= 0 || (a2.save(), s3.render(a2), a2.restore());
494
+ a2.restore(), this.j = false;
495
+ }
496
+ destroy() {
497
+ super.destroy(), this.Y = null, this.G = null;
498
+ }
499
+ }
500
+ class c extends o {
501
+ renderAllLayersIn(t2) {
502
+ const s2 = t2.topScreenContext;
503
+ this.K(t2, s2);
504
+ }
505
+ }
506
+ class l {
507
+ name = "interaction";
508
+ et = null;
509
+ i;
510
+ nt;
511
+ rt;
512
+ ot = false;
513
+ ct = 0;
514
+ lt = 0;
515
+ ut = 0;
516
+ dt = null;
517
+ ft = (t2) => this.Mt(t2);
518
+ gt = (t2) => this._t(t2);
519
+ yt = () => this.wt();
520
+ xt = (t2) => this.bt(t2);
521
+ constructor(t2) {
522
+ this.i = { panEnabled: true, zoomEnabled: true, friction: 0.92, stopSpeed: 0.02, emaAlpha: 0.25, idleNoInertiaMs: 120, wheelSensitivity: 15e-4, ...t2 }, this.nt = this.i.panEnabled, this.rt = this.i.zoomEnabled;
523
+ }
524
+ install(t2) {
525
+ this.et = t2;
526
+ const s2 = t2.canvas;
527
+ s2.addEventListener("wheel", this.xt, { passive: false }), s2.addEventListener("pointerdown", this.ft), window.addEventListener("pointermove", this.gt), window.addEventListener("pointerup", this.yt), t2.onUpdate(this.vt);
528
+ }
529
+ destroy() {
530
+ if (!this.et) return;
531
+ const t2 = this.et.canvas;
532
+ t2.removeEventListener("wheel", this.xt), t2.removeEventListener("pointerdown", this.ft), window.removeEventListener("pointermove", this.gt), window.removeEventListener("pointerup", this.yt), this.et.offUpdate(this.vt), this.et = null;
533
+ }
534
+ isPanEnabled() {
535
+ return this.nt;
536
+ }
537
+ isZoomEnabled() {
538
+ return this.rt;
539
+ }
540
+ setPanEnabled(t2) {
541
+ this.nt !== t2 && (this.nt = t2, t2 || (this.ot = false, this.ct = 0, this.lt = 0));
542
+ }
543
+ setZoomEnabled(t2) {
544
+ this.rt = t2;
545
+ }
546
+ setWheelSensitivity(t2) {
547
+ this.i.wheelSensitivity = t2;
548
+ }
549
+ isDragging() {
550
+ return this.ot;
551
+ }
552
+ vt = (t2) => {
553
+ if (!this.et) return;
554
+ const { friction: s2, stopSpeed: i2 } = this.i, h2 = Math.hypot(this.ct, this.lt) >= i2;
555
+ if (!this.ot && this.nt && h2) {
556
+ const h3 = this.ct * t2, e2 = this.lt * t2;
557
+ this.et.panBy(h3, e2), this.ct *= s2, this.lt *= s2, Math.hypot(this.ct, this.lt) < i2 && (this.ct = 0, this.lt = 0);
558
+ } else this.nt || (this.ct = 0, this.lt = 0);
559
+ };
560
+ Mt(t2) {
561
+ if (0 === t2.button && this.nt) {
562
+ this.ot = true, this.ct = 0, this.lt = 0, this.ut = performance.now(), this.dt = t2.pointerId;
563
+ try {
564
+ this.et?.canvas.setPointerCapture(t2.pointerId);
565
+ } catch {
566
+ }
567
+ }
568
+ }
569
+ _t(t2) {
570
+ if (!this.ot || !this.nt || !this.et) return;
571
+ const s2 = performance.now(), i2 = Math.max(1, s2 - (this.ut || s2 - 16));
572
+ this.ut = s2;
573
+ const h2 = t2.movementX, e2 = t2.movementY;
574
+ this.et.panBy(h2, e2);
575
+ const n2 = this.i.emaAlpha, r2 = h2 / i2, o2 = e2 / i2;
576
+ this.ct = (1 - n2) * this.ct + n2 * r2, this.lt = (1 - n2) * this.lt + n2 * o2;
577
+ }
578
+ wt() {
579
+ if (!this.ot) return;
580
+ this.ot = false;
581
+ const t2 = performance.now(), s2 = this.ut ? t2 - this.ut : 1 / 0;
582
+ if (null != this.dt && this.et) {
583
+ try {
584
+ this.et.canvas.releasePointerCapture(this.dt);
585
+ } catch {
586
+ }
587
+ this.dt = null;
588
+ }
589
+ if (s2 >= this.i.idleNoInertiaMs) this.ct = 0, this.lt = 0;
590
+ else {
591
+ const t3 = Math.pow(this.i.friction, s2 / 16);
592
+ this.ct *= t3, this.lt *= t3;
593
+ }
594
+ Math.hypot(this.ct, this.lt) < this.i.stopSpeed && (this.ct = 0, this.lt = 0);
595
+ }
596
+ Lt() {
597
+ if (!this.et) return 16;
598
+ const t2 = getComputedStyle(this.et.canvas).lineHeight;
599
+ if (!t2 || "normal" === t2) return 16;
600
+ const s2 = parseFloat(t2);
601
+ return Number.isFinite(s2) ? s2 : 16;
602
+ }
603
+ Rt(t2) {
604
+ if (!this.et) return 0;
605
+ let s2 = t2.deltaY;
606
+ return 1 === t2.deltaMode ? s2 *= this.Lt() : 2 === t2.deltaMode && (s2 *= this.et.canvas.clientHeight || window.innerHeight || 800), s2;
607
+ }
608
+ bt(t2) {
609
+ if (!this.rt || !this.et) return;
610
+ t2.preventDefault(), t2.stopPropagation();
611
+ const s2 = this.Rt(t2), i2 = this.et.canvas.getBoundingClientRect(), h2 = t2.clientX - i2.left, e2 = t2.clientY - i2.top;
612
+ let n2 = -s2 * this.i.wheelSensitivity;
613
+ t2.ctrlKey || t2.metaKey ? n2 *= 1.6 : t2.shiftKey && (n2 *= 0.6), this.et.zoomByLogAtScreen(h2, e2, n2);
614
+ }
615
+ }
616
+ function u(t2) {
617
+ return new l(t2);
618
+ }
619
+ class d {
620
+ name = "document";
621
+ et = null;
622
+ i;
623
+ St = false;
624
+ zt = 0;
625
+ Ct = 0;
626
+ At = 0;
627
+ Tt = 0;
628
+ Pt = 0;
629
+ Bt = 0;
630
+ It = 0;
631
+ Dt = 0;
632
+ Et = "minVisible";
633
+ constructor(t2) {
634
+ this.i = { rect: { x: 0, y: 0, width: 0, height: 0 }, margins: {}, drawBorder: false, minVisiblePx: 30, panClampMode: "minVisible", ...t2 }, t2?.rect && (this.St = true, this.zt = t2.rect.x, this.Ct = t2.rect.y, this.At = t2.rect.width, this.Tt = t2.rect.height), t2?.margins && (this.Pt = t2.margins.left ?? 0, this.Bt = t2.margins.right ?? 0, this.It = t2.margins.top ?? 0, this.Dt = t2.margins.bottom ?? 0), this.Et = this.i.panClampMode;
635
+ }
636
+ install(t2) {
637
+ this.et = t2, t2.onUpdate(this.vt), t2.onBeforeRender(this.Ft), t2.onAfterRender(this.kt);
638
+ }
639
+ destroy() {
640
+ this.et && (this.et.offUpdate(this.vt), this.et.offBeforeRender(this.Ft), this.et.offAfterRender(this.kt), this.et = null);
641
+ }
642
+ isEnabled() {
643
+ return this.St;
644
+ }
645
+ getRect() {
646
+ return { x: this.zt, y: this.Ct, width: this.At, height: this.Tt };
647
+ }
648
+ setRect(t2, s2, i2, h2) {
649
+ this.St = true, this.zt = t2, this.Ct = s2, this.At = i2, this.Tt = h2;
650
+ }
651
+ clearRect() {
652
+ this.St = false;
653
+ }
654
+ setMargins(t2) {
655
+ this.Pt = t2.left ?? this.Pt, this.Bt = t2.right ?? this.Bt, this.It = t2.top ?? this.It, this.Dt = t2.bottom ?? this.Dt;
656
+ }
657
+ getMargins() {
658
+ return { left: this.Pt, right: this.Bt, top: this.It, bottom: this.Dt };
659
+ }
660
+ setPanClampMode(t2) {
661
+ this.Et = t2;
662
+ }
663
+ getPanClampMode() {
664
+ return this.Et;
665
+ }
666
+ cropTo(t2) {
667
+ this.Zt("crop", t2);
668
+ }
669
+ resizeTo(t2) {
670
+ this.Zt("resize", t2);
671
+ }
672
+ zoomToFit(t2 = "contain") {
673
+ if (!this.St || !this.et) return;
674
+ const s2 = this.et.dpr, i2 = this.et.canvas.width / s2, h2 = this.et.canvas.height / s2, e2 = Math.max(1, i2 - (this.Pt + this.Bt)), n2 = Math.max(1, h2 - (this.It + this.Dt));
675
+ let r2;
676
+ const o2 = e2 / this.At, a2 = n2 / this.Tt;
677
+ r2 = "contain" === t2 ? Math.min(o2, a2) : "cover" === t2 ? Math.max(o2, a2) : "fitWidth" === t2 ? o2 : a2, r2 = Math.min(this.et.maxZoom, Math.max(this.et.minZoom, r2));
678
+ const c2 = this.Pt + (e2 - r2 * this.At) / 2, l2 = this.It + (n2 - r2 * this.Tt) / 2, u2 = c2 - r2 * this.zt, d2 = l2 - r2 * this.Ct;
679
+ this.et.setTransform(r2, u2, d2);
680
+ }
681
+ isPointInDocument(t2, s2) {
682
+ return !this.St || t2 >= this.zt && t2 <= this.zt + this.At && s2 >= this.Ct && s2 <= this.Ct + this.Tt;
683
+ }
684
+ vt = () => {
685
+ this.St && this.et && this.Ut();
686
+ };
687
+ Ft = (t2) => {
688
+ this.St && this.et && (t2.save(), t2.beginPath(), t2.rect(this.zt, this.Ct, this.At, this.Tt), t2.clip());
689
+ };
690
+ kt = (t2) => {
691
+ if (this.St && this.et && (t2.restore(), this.i.drawBorder)) {
692
+ const s2 = this.et.zoom;
693
+ t2.save(), t2.lineWidth = 1 / s2, t2.strokeStyle = "#cfcfcf", t2.strokeRect(this.zt, this.Ct, this.At, this.Tt), t2.restore();
694
+ }
695
+ };
696
+ Ut() {
697
+ if (!this.et) return;
698
+ const { zoom: t2, tx: s2, ty: i2 } = this.et.getTransform(), h2 = t2, e2 = this.et.dpr, n2 = this.et.canvas.width / e2, r2 = this.et.canvas.height / e2, o2 = this.zt, a2 = this.Ct, c2 = this.zt + this.At, l2 = this.Ct + this.Tt;
699
+ let u2 = s2, d2 = i2;
700
+ if ("margin" === this.Et) {
701
+ const t3 = this.Pt - h2 * o2, e3 = n2 - this.Bt - h2 * c2, f2 = this.It - h2 * a2, M2 = r2 - this.Dt - h2 * l2, m2 = Math.max(1, n2 - (this.Pt + this.Bt)), p2 = Math.max(1, r2 - (this.It + this.Dt));
702
+ u2 = h2 * this.At <= m2 ? this.Pt + (m2 - h2 * this.At) / 2 - h2 * this.zt : Math.min(t3, Math.max(e3, s2)), d2 = h2 * this.Tt <= p2 ? this.It + (p2 - h2 * this.Tt) / 2 - h2 * this.Ct : Math.min(f2, Math.max(M2, i2));
703
+ } else if ("minVisible" === this.Et) {
704
+ const t3 = h2 * this.At, e3 = h2 * this.Tt, f2 = Math.min(this.i.minVisiblePx, t3), M2 = Math.min(this.i.minVisiblePx, e3), m2 = n2 - f2 - h2 * o2, p2 = f2 - h2 * c2, g = r2 - M2 - h2 * a2, _ = M2 - h2 * l2;
705
+ u2 = p2 <= m2 ? Math.min(m2, Math.max(p2, s2)) : (p2 + m2) / 2, d2 = _ <= g ? Math.min(g, Math.max(_, i2)) : (_ + g) / 2;
706
+ }
707
+ u2 === s2 && d2 === i2 || this.et.setPan(u2, d2);
708
+ }
709
+ Zt(t2, s2) {
710
+ if (!this.et) return;
711
+ const i2 = Math.max(1, Math.floor(s2.width)), h2 = Math.max(1, Math.floor(s2.height)), e2 = { width: i2, height: h2 }, n2 = this.et.getLayerManagers();
712
+ for (const s3 of n2) {
713
+ const i3 = s3.getAllLayers("world");
714
+ for (const s4 of i3) {
715
+ const i4 = s4;
716
+ "function" == typeof i4.cropTo && "function" == typeof i4.resizeTo && ("crop" === t2 ? i4.cropTo(e2) : i4.resizeTo(e2));
717
+ }
718
+ }
719
+ this.At = i2, this.Tt = h2, this.St && this.Ut();
720
+ }
721
+ }
722
+ function f(t2) {
723
+ return new d(t2);
724
+ }
725
+ class M {
726
+ type = "snapshot";
727
+ Wt;
728
+ $t;
729
+ qt;
730
+ Ot;
731
+ Nt = true;
732
+ constructor(t2, s2, i2, h2) {
733
+ this.Wt = t2, this.$t = s2, this.qt = i2, this.Ot = h2?.region;
734
+ }
735
+ execute() {
736
+ if (this.Nt) return;
737
+ const t2 = this.Ot ? { x: this.Ot.x, y: this.Ot.y } : void 0;
738
+ this.Wt.restoreSnapshot(this.qt, t2), this.Nt = true;
739
+ }
740
+ undo() {
741
+ if (!this.Nt) return;
742
+ const t2 = this.Ot ? { x: this.Ot.x, y: this.Ot.y } : void 0;
743
+ this.Wt.restoreSnapshot(this.$t, t2), this.Nt = false;
744
+ }
745
+ canMerge() {
746
+ return false;
747
+ }
748
+ merge() {
749
+ return this;
750
+ }
751
+ }
752
+ function m(t2, s2, i2, h2) {
753
+ return s2 && i2 ? new M(t2, s2, i2, h2) : null;
754
+ }
755
+ class p {
756
+ Vt;
757
+ Ht = [];
758
+ Xt = [];
759
+ executeCommand(t2) {
760
+ t2.execute(), this.addCommand(t2);
761
+ }
762
+ addCommand(t2) {
763
+ this.Xt = [];
764
+ const s2 = this.Ht[this.Ht.length - 1];
765
+ if (s2 && s2.canMerge?.(t2) && s2.merge) {
766
+ const i2 = s2.merge(t2) ?? s2;
767
+ return void (i2 !== s2 && (this.Ht[this.Ht.length - 1] = i2));
768
+ }
769
+ this.Ht.push(t2), this.Ht.length > this.Vt && this.Ht.shift();
770
+ }
771
+ undo() {
772
+ if (0 === this.Ht.length) return null;
773
+ const t2 = this.Ht.pop();
774
+ return t2.undo(), this.Xt.push(t2), t2;
775
+ }
776
+ redo() {
777
+ if (0 === this.Xt.length) return null;
778
+ const t2 = this.Xt.pop();
779
+ return t2.execute(), this.Ht.push(t2), t2;
780
+ }
781
+ canUndo() {
782
+ return this.Ht.length > 0;
783
+ }
784
+ canRedo() {
785
+ return this.Xt.length > 0;
786
+ }
787
+ clear() {
788
+ this.Ht = [], this.Xt = [];
789
+ }
790
+ setMaxHistorySize(t2) {
791
+ this.Vt = Math.max(1, t2), this.Ht.length > this.Vt && (this.Ht = this.Ht.slice(-this.Vt));
792
+ }
793
+ constructor(t2) {
794
+ this.Vt = t2?.maxHistorySize ?? 50, this.Ht = t2?.undoStack ?? [], this.Xt = t2?.redoStack ?? [];
795
+ }
796
+ }
797
+ export {
798
+ r as BitmapLayer,
799
+ n as CanvasLayer,
800
+ a as ContentLayerManager,
801
+ d as DocumentPlugin,
802
+ p as HistoryManager,
803
+ l as InteractionPlugin,
804
+ e as LayerBase,
805
+ o as LayerManagerBase,
806
+ M as SnapshotCommand,
807
+ c as TopScreenLayerManager,
808
+ i as ViewManager,
809
+ f as createDocumentPlugin,
810
+ u as createInteractionPlugin,
811
+ m as createSnapshotCommand
812
+ };