@reffy/infinite-canvas 0.0.11 → 0.0.12

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.js DELETED
@@ -1,4114 +0,0 @@
1
- var se = (s) => {
2
- throw TypeError(s);
3
- };
4
- var re = (s, t, e) => t.has(s) || se("Cannot " + e);
5
- var f = (s, t, e) => (re(s, t, "read from private field"), e ? e.call(s) : t.get(s)), O = (s, t, e) => t.has(s) ? se("Cannot add the same private member more than once") : t instanceof WeakSet ? t.add(s) : t.set(s, e), I = (s, t, e, i) => (re(s, t, "write to private field"), i ? i.call(s, e) : t.set(s, e), e);
6
- import { makeObservable as Ee, computed as nt, action as b, observable as B, reaction as Je } from "mobx";
7
- import { css as ti, LitElement as ei } from "lit";
8
- import Y from "dexie";
9
- import { v4 as ii } from "uuid";
10
- import si from "eventemitter3";
11
- import ri from "stats.js";
12
- const yt = ["TOP", "BOTTOM", "LEFT", "RIGHT"], Et = ["TOPLEFT", "TOPRIGHT", "BOTTOMLEFT", "BOTTOMRIGHT"], ne = {
13
- TOPLEFT: "TOPRIGHT",
14
- TOPRIGHT: "TOPLEFT",
15
- BOTTOMLEFT: "BOTTOMRIGHT",
16
- BOTTOMRIGHT: "BOTTOMLEFT"
17
- };
18
- function ae(s) {
19
- return ne[s] ? ne[s] : s;
20
- }
21
- const Te = 8, Kt = 2, E = {
22
- identity: function() {
23
- return [1, 0, 0, 0, 1, 0, 0, 0, 1];
24
- },
25
- translation: function(s, t) {
26
- return [1, 0, 0, 0, 1, 0, s, t, 1];
27
- },
28
- rotation: function(s) {
29
- var t = Math.cos(s), e = Math.sin(s);
30
- return [t, -e, 0, e, t, 0, 0, 0, 1];
31
- },
32
- scaling: function(s, t) {
33
- return [s, 0, 0, 0, t, 0, 0, 0, 1];
34
- },
35
- multiply: function(s, t) {
36
- var e = s[0], i = s[1], r = s[2], n = s[3], a = s[4], o = s[5], h = s[6], c = s[7], l = s[8], u = t[0], g = t[1], m = t[2], w = t[3], x = t[4], C = t[5], v = t[6], A = t[7], T = t[8];
37
- return [
38
- u * e + g * n + m * h,
39
- u * i + g * a + m * c,
40
- u * r + g * o + m * l,
41
- w * e + x * n + C * h,
42
- w * i + x * a + C * c,
43
- w * r + x * o + C * l,
44
- v * e + A * n + T * h,
45
- v * i + A * a + T * c,
46
- v * r + A * o + T * l
47
- ];
48
- },
49
- inverse(s) {
50
- const t = [9], e = s[0], i = s[1], r = s[2], n = s[3], a = s[4], o = s[5], h = s[6], c = s[7], l = s[8], u = l * a - o * c, g = -l * n + o * h, m = c * n - a * h, x = 1 / (e * u + i * g + r * m);
51
- return t[0] = u * x, t[1] = (-l * i + r * c) * x, t[2] = (o * i - r * a) * x, t[3] = g * x, t[4] = (l * e - r * h) * x, t[5] = (-o * e + r * n) * x, t[6] = m * x, t[7] = (-c * e + i * h) * x, t[8] = (a * e - i * n) * x, t;
52
- },
53
- projection(s, t) {
54
- const e = [9];
55
- return e[0] = 2 / s, e[1] = 0, e[2] = 0, e[3] = 0, e[4] = -2 / t, e[5] = 0, e[6] = -1, e[7] = 1, e[8] = 1, e;
56
- },
57
- transformPoint(s, t) {
58
- var e = t[0], i = t[1], r = e * s[2] + i * s[5] + s[8];
59
- return [
60
- (e * s[0] + i * s[3] + s[6]) / r,
61
- (e * s[1] + i * s[4] + s[7]) / r
62
- ];
63
- }
64
- };
65
- function Ht(s, t, e) {
66
- const i = oe(s, s.VERTEX_SHADER, t), r = oe(s, s.FRAGMENT_SHADER, e), n = s.createProgram();
67
- if (s.attachShader(n, i), s.attachShader(n, r), s.linkProgram(n), !s.getProgramParameter(n, s.LINK_STATUS))
68
- throw s.deleteProgram(n), s.deleteShader(i), s.deleteShader(r), new Error(
69
- "Program was not created or the link to shaders was not successful."
70
- );
71
- return s.detachShader(n, i), s.detachShader(n, r), n;
72
- }
73
- function oe(s, t, e) {
74
- const i = s.createShader(t);
75
- if (s.shaderSource(i, e), s.compileShader(i), s.getShaderParameter(i, s.COMPILE_STATUS))
76
- return i;
77
- throw s.deleteShader(i), new Error("Shader was not created.");
78
- }
79
- function ni(s, t, e, i, r, n) {
80
- const a = r.getBoundingClientRect(), o = window.devicePixelRatio || 1, h = (s - a.left) * o, c = (t - a.top) * o, l = h / e * 2 - 1, u = c / i * -2 + 1, g = E.projection(e, i), m = E.multiply(g, n), w = E.inverse(m), [x, C] = E.transformPoint(w, [l, u]);
81
- return [x, C];
82
- }
83
- function K(s, t, e) {
84
- const { gl: i, canvas: r } = e;
85
- return ni(
86
- s,
87
- t,
88
- i.canvas.width,
89
- i.canvas.height,
90
- r,
91
- e.worldMatrix
92
- );
93
- }
94
- function U(s, t, e) {
95
- const i = t ?? 0, r = e ?? 0;
96
- return [
97
- s[0] * i + s[3] * r + s[6],
98
- s[1] * i + s[4] * r + s[7]
99
- ];
100
- }
101
- function ai(s) {
102
- return Math.hypot(s[0], s[1]);
103
- }
104
- function oi(s) {
105
- return Math.hypot(s[3], s[4]);
106
- }
107
- function tt(s) {
108
- return [ai(s), oi(s)];
109
- }
110
- function he(s) {
111
- return s / Math.abs(s);
112
- }
113
- function Tt(s) {
114
- return [he(s[0]), he(s[4])];
115
- }
116
- const Dt = (s, t) => Math.abs(s) < t ? 0 : Math.sign(s), Bt = (s, t, e) => {
117
- const i = s * t;
118
- return Dt(s, e) !== Dt(i, e);
119
- };
120
- async function hi(s) {
121
- return new Promise((t, e) => {
122
- let i = new FileReader();
123
- i.onload = (r) => {
124
- t(r.target.result);
125
- }, i.onerror = e, i.readAsDataURL(s);
126
- });
127
- }
128
- const ci = [
129
- "image/webp",
130
- "image/png",
131
- "image/jpeg",
132
- "image/jpg",
133
- "image/svg+xml",
134
- "image/avif",
135
- "image/gif",
136
- // will be rendered as a still image
137
- "image/apng"
138
- // will be rendered as a still image
139
- ];
140
- function di(s) {
141
- return ci.includes(s);
142
- }
143
- async function Qt(s) {
144
- const e = new TextEncoder().encode(s), i = await crypto.subtle.digest("SHA-256", e);
145
- return Array.from(new Uint8Array(i)).map((n) => n.toString(16).padStart(2, "0")).join("");
146
- }
147
- function li(s) {
148
- const t = /^data:([^;]+);base64,/.exec(s);
149
- return t ? t[1] : void 0;
150
- }
151
- async function ui(s, t) {
152
- const e = [];
153
- if (s.length > 0)
154
- for (let i = 0; i < s.length; i++) {
155
- const r = s[i];
156
- if (di(r.type))
157
- try {
158
- const n = await hi(r);
159
- typeof n == "string" ? e.push(await t(n)) : console.error("Image not added");
160
- } catch {
161
- console.error("Failed to copy image.");
162
- }
163
- }
164
- return e;
165
- }
166
- function fi(s, t) {
167
- const e = JSON.stringify(t, null, 2), i = new Blob([e], { type: "application/json" }), r = URL.createObjectURL(i), n = document.createElement("a");
168
- n.href = r, n.download = s, document.body.appendChild(n), n.click(), n.remove(), URL.revokeObjectURL(r);
169
- }
170
- async function mi(s) {
171
- const t = await s.text();
172
- return JSON.parse(t);
173
- }
174
- function _e(s, t = 1) {
175
- return new Promise((e, i) => {
176
- const r = new Image();
177
- r.onload = () => {
178
- const n = document.createElement("canvas");
179
- n.width = r.width, n.height = r.height;
180
- const a = n.getContext("2d");
181
- a.clearRect(0, 0, n.width, n.height), a.drawImage(r, 0, 0);
182
- const o = n.toDataURL("image/png", t);
183
- e(o);
184
- }, r.onerror = i, r.src = s;
185
- });
186
- }
187
- const ot = [0.33, 0.6, 0.95, 1], Ct = [
188
- 0.33,
189
- 0.6,
190
- 0.95,
191
- 0.6
192
- ], gi = [
193
- 0.33,
194
- 0.6,
195
- 0.95,
196
- 0.4
197
- ];
198
- function zt(s, t, e = "Add Child") {
199
- return {
200
- label: e,
201
- do() {
202
- for (const i of t)
203
- s.appendChild(i);
204
- },
205
- undo() {
206
- for (const i of t)
207
- s.removeChild(i);
208
- }
209
- };
210
- }
211
- function pi(s, t, e = "Remove Child") {
212
- let i = -1;
213
- return {
214
- label: e,
215
- do() {
216
- i = s.children.indexOf(t), i >= 0 && s.children.splice(i, 1);
217
- },
218
- undo() {
219
- if (i < 0) {
220
- s.children.push(t);
221
- return;
222
- }
223
- s.children.splice(i, 0, t);
224
- }
225
- };
226
- }
227
- function xi(s, t, e = "Remove Children") {
228
- let i = [];
229
- return {
230
- label: e,
231
- do() {
232
- const r = new Set(t);
233
- i = [], s.children.forEach((n, a) => {
234
- r.has(n) && i.push({ child: n, idx: a });
235
- }), i.slice().sort((n, a) => a.idx - n.idx).forEach(({ child: n }) => {
236
- s.removeChild(n);
237
- });
238
- },
239
- undo() {
240
- i.slice().sort((r, n) => r.idx - n.idx).forEach(({ child: r, idx: n }) => {
241
- s.children.includes(r) || (s.children.splice(
242
- Math.min(n, s.children.length),
243
- 0,
244
- r
245
- ), r.addParent(s));
246
- }), s.markOrderDirty();
247
- }
248
- };
249
- }
250
- const yi = ["image/", "text/plain"], wi = () => "clipboard" in navigator && "writeText" in navigator.clipboard;
251
- async function Re(s, t) {
252
- const e = {
253
- type: "infinite_canvas",
254
- elements: s.map((n) => ({
255
- src: n.src,
256
- x: n.x,
257
- y: n.y,
258
- sx: n.sx,
259
- sy: n.sy
260
- }))
261
- }, i = JSON.stringify(e), r = new ClipboardItem({
262
- "text/plain": new Blob([i], { type: "text/plain" })
263
- });
264
- if (wi())
265
- try {
266
- await navigator.clipboard.write([r]);
267
- return;
268
- } catch (n) {
269
- console.error(n);
270
- }
271
- if (!vi(i))
272
- throw new Error("Error copying to clipboard.");
273
- }
274
- function vi(s) {
275
- s || (s = " ");
276
- const t = document.documentElement.getAttribute("dir") === "rtl", e = document.createElement("textarea");
277
- e.style.border = "0", e.style.padding = "0", e.style.margin = "0", e.style.position = "absolute", e.style[t ? "right" : "left"] = "-9999px";
278
- const i = window.pageYOffset || document.documentElement.scrollTop;
279
- e.style.top = `${i}px`, e.style.fontSize = "12pt", e.setAttribute("readonly", ""), e.value = s, document.body.appendChild(e);
280
- let r = !1;
281
- try {
282
- e.select(), e.setSelectionRange(0, e.value.length), r = document.execCommand("copy");
283
- } catch (n) {
284
- console.error(n);
285
- }
286
- return e.remove(), r;
287
- }
288
- async function Ie(s, t, e, i, r = !0) {
289
- const n = await navigator.clipboard.read(), a = n[0].types, [o, h] = r ? [s, t] : K(s, t, e);
290
- for (const c of a) {
291
- if (!yi.find(
292
- (m) => m.endsWith("/") ? c.startsWith(m) : c === m
293
- )) continue;
294
- const u = await n[0].getType(c);
295
- try {
296
- if (c === "text/plain") {
297
- const m = JSON.parse(await u.text());
298
- if (m.elements.length === 0) return;
299
- let w = 1 / 0, x = 1 / 0;
300
- for (const v of m.elements)
301
- v.x < w && (w = v.x), v.y < x && (x = v.y);
302
- const C = await Promise.all(
303
- m.elements.map(
304
- (v) => e.addImageToCanvas(
305
- v.src,
306
- o + v.x - w,
307
- h + v.y - x,
308
- v.sx,
309
- v.sy
310
- )
311
- )
312
- );
313
- i.push(zt(e, C));
314
- return;
315
- }
316
- } catch (m) {
317
- console.error("Failed to parse clipboard data", m);
318
- continue;
319
- }
320
- let g;
321
- if (c.startsWith("image/svg"))
322
- try {
323
- const m = await u.text();
324
- g = await _e(
325
- `data:image/svg+xml;base64,${btoa(m)}`
326
- );
327
- } catch (m) {
328
- console.error("SVG conversion failed", m);
329
- continue;
330
- }
331
- else
332
- try {
333
- g = await new Promise((m, w) => {
334
- const x = new FileReader();
335
- x.onloadend = () => m(x.result), x.onerror = w, x.readAsDataURL(u);
336
- });
337
- } catch (m) {
338
- console.error("Image read failed", m);
339
- continue;
340
- }
341
- try {
342
- const m = await e.addImageToCanvas(g, o, h);
343
- i.push(zt(e, [m]));
344
- return;
345
- } catch (m) {
346
- console.error("Failed to add image to canvas", m);
347
- continue;
348
- }
349
- }
350
- }
351
- const H = {
352
- Open: "opencontextmenu",
353
- Close: "closecontextmenu"
354
- }, N = {
355
- Save: "save",
356
- Change: "statechange"
357
- }, it = {
358
- start: "startloading",
359
- done: "completeloading"
360
- }, st = {
361
- Save: "save",
362
- SaveCompleted: "savecompleted",
363
- SaveFailed: "savefailed"
364
- }, bi = `
365
- attribute vec2 a_position;
366
-
367
- uniform vec2 u_resolution;
368
- uniform mat3 u_matrix;
369
- uniform float u_z;
370
-
371
- // all shaders have a main function
372
- void main() {
373
- vec2 position = (u_matrix * vec3(a_position, 1)).xy;
374
-
375
- vec2 zeroToOne = position / u_resolution;
376
- vec2 zeroToTwo = zeroToOne * 2.0;
377
- vec2 clipSpace = zeroToTwo - 1.0;
378
- float z = mix(1.0, -1.0, u_z);
379
-
380
- gl_Position = vec4(clipSpace * vec2(1, -1), z, 1);
381
- }
382
- `, Ci = `
383
- precision mediump float;
384
- uniform vec4 u_color;
385
-
386
- void main() {
387
- gl_FragColor = u_color;
388
- }
389
- `, Si = (
390
- /* glsl */
391
- `
392
- #extension GL_OES_standard_derivatives : enable
393
- #ifdef GL_FRAGMENT_PRECISION_HIGH
394
- precision highp float;
395
- precision highp int;
396
- #else
397
- precision mediump float;
398
- precision mediump int;
399
- #endif
400
-
401
- uniform mat3 u_ViewProjectionInvMatrix;
402
- uniform float u_ZoomScale;
403
- uniform float u_CheckboardStyle;
404
- uniform float u_z;
405
-
406
- attribute vec2 a_Position;
407
-
408
- varying vec2 v_Position;
409
-
410
- vec2 project_clipspace_to_world(vec2 p) {
411
- return (u_ViewProjectionInvMatrix * vec3(p, 1.0)).xy;
412
- }
413
-
414
- void main() {
415
- v_Position = project_clipspace_to_world(a_Position);
416
- float z = mix(1.0, -1.0, u_z);
417
- gl_Position = vec4(a_Position, z, 1.0);
418
- }
419
- `
420
- ), Mi = (
421
- /* glsl */
422
- `
423
- #extension GL_OES_standard_derivatives : enable
424
- #ifdef GL_FRAGMENT_PRECISION_HIGH
425
- precision highp float;
426
- precision highp int;
427
- #else
428
- precision mediump float;
429
- precision mediump int;
430
- #endif
431
-
432
- uniform mat3 u_ViewProjectionInvMatrix;
433
- uniform float u_ZoomScale;
434
- uniform float u_CheckboardStyle;
435
-
436
- varying vec2 v_Position;
437
-
438
- const vec4 GRID_COLOR = vec4(0.87, 0.87, 0.87, 1.0);
439
- const vec4 PAGE_COLOR = vec4(0.986, 0.986, 0.986, 1.0);
440
- const int CHECKERBOARD_STYLE_NONE = 0;
441
- const int CHECKERBOARD_STYLE_GRID = 1;
442
- const int CHECKERBOARD_STYLE_DOTS = 2;
443
- const float BASE_GRID_PIXEL_SIZE = 100.0;
444
-
445
- vec2 scale_grid_size(float zoom) {
446
- if (zoom < 0.125) return vec2(BASE_GRID_PIXEL_SIZE * 125.0, 0.125);
447
- else if (zoom < 0.25) return vec2(BASE_GRID_PIXEL_SIZE * 25.0, 0.25);
448
- else if (zoom < 0.5) return vec2(BASE_GRID_PIXEL_SIZE * 5.0, 0.5);
449
- return vec2(BASE_GRID_PIXEL_SIZE, 4.0);
450
- }
451
-
452
- vec4 render_grid_checkerboard(vec2 coord) {
453
- float alpha = 0.0;
454
-
455
- vec2 size = scale_grid_size(u_ZoomScale);
456
- float gridSize1 = size.x;
457
- float gridSize2 = gridSize1 / 10.0;
458
- float zoomStep = size.y;
459
- int checkboardStyle = int(floor(u_CheckboardStyle + 0.5));
460
-
461
- if (checkboardStyle == CHECKERBOARD_STYLE_GRID) {
462
- vec2 grid1 = abs(fract(coord / gridSize1 - 0.5) - 0.5) / fwidth(coord) * gridSize1 / 2.0;
463
- vec2 grid2 = abs(fract(coord / gridSize2 - 0.5) - 0.5) / fwidth(coord) * gridSize2;
464
- float v1 = 1.0 - min(min(grid1.x, grid1.y), 1.0);
465
- float v2 = 1.0 - min(min(grid2.x, grid2.y), 1.0);
466
-
467
- if (v1 > 0.0) {
468
- alpha = v1;
469
- } else {
470
- alpha = v2 * clamp(u_ZoomScale / zoomStep, 0.0, 1.0);
471
- }
472
- }
473
-
474
- return mix(PAGE_COLOR, GRID_COLOR, alpha);
475
- }
476
-
477
- void main() {
478
- gl_FragColor = render_grid_checkerboard(v_Position);
479
- }
480
- `
481
- ), Ei = `
482
- attribute vec2 a_position;
483
- attribute vec2 a_texCoord;
484
-
485
- uniform vec2 u_resolution;
486
- uniform mat3 u_matrix;
487
- uniform float u_z;
488
-
489
- varying vec2 v_texCoord;
490
-
491
- void main() {
492
- vec2 position = (u_matrix * vec3(a_position, 1)).xy;
493
- vec2 zeroToOne = position / u_resolution;
494
- vec2 zeroToTwo = zeroToOne * 2.0;
495
- vec2 clipSpace = zeroToTwo - 1.0;
496
- float z = mix(1.0, -1.0, u_z);
497
-
498
- gl_Position = vec4(clipSpace * vec2(1, -1), z, 1);
499
-
500
- v_texCoord = a_texCoord;
501
- }
502
- `, Ti = `
503
- #ifdef GL_FRAGMENT_PRECISION_HIGH
504
- precision highp float;
505
- #else
506
- precision mediump float;
507
- #endif
508
-
509
- uniform sampler2D u_image;
510
-
511
- varying vec2 v_texCoord;
512
-
513
- void main() {
514
- gl_FragColor = texture2D(u_image, v_texCoord);
515
- }
516
- `;
517
- var z = /* @__PURE__ */ ((s) => (s[s.ACTIVE = 0] = "ACTIVE", s[s.PASSIVE = 1] = "PASSIVE", s))(z || {});
518
- class ce {
519
- constructor(t, e) {
520
- this.sides = /* @__PURE__ */ new Map(), this.corners = /* @__PURE__ */ new Map(), this.borderSize = 0, this.boxSize = 0, this.mode = z.ACTIVE, this.target = t, this.setDimension(), this.mode = e ?? z.ACTIVE, this.borderSize = Kt, this.boxSize = Te / 2, this.addSides(), this.mode === z.ACTIVE && this.addCorners();
521
- }
522
- setDimension() {
523
- const t = this.target.getEdge();
524
- this.width = t.maxX - t.minX, this.height = t.maxY - t.minY;
525
- }
526
- getSidesInScreenSpace(t, e) {
527
- const [i, r] = e ? tt(e) : [1, 1], { width: n, height: a, borderSize: o } = this, [h, c] = U(e), [l, u] = Tt(e);
528
- return {
529
- TOP: {
530
- x: l > 0 ? h : h - n * i,
531
- y: c,
532
- width: n * i,
533
- height: o
534
- },
535
- BOTTOM: {
536
- x: l > 0 ? h : h - n * i,
537
- y: c + a * r * u,
538
- width: n * i,
539
- height: o
540
- },
541
- LEFT: {
542
- x: h,
543
- y: u > 0 ? c : c - a * r,
544
- width: o,
545
- height: a * r
546
- },
547
- RIGHT: {
548
- x: h + n * i * l,
549
- y: u > 0 ? c : c - a * r,
550
- width: o,
551
- height: a * r
552
- }
553
- }[t];
554
- }
555
- getCornersInScreenSpace(t, e) {
556
- const [i, r] = e ? tt(e) : [1, 1], { width: n, height: a, boxSize: o } = this, [h, c] = U(e), [l, u] = Tt(e);
557
- return {
558
- TOPLEFT: {
559
- x: h - o,
560
- y: c - o,
561
- width: o * 2,
562
- height: o * 2
563
- },
564
- TOPRIGHT: {
565
- x: h - o + n * i * l,
566
- y: c - o,
567
- width: o * 2,
568
- height: o * 2
569
- },
570
- BOTTOMLEFT: {
571
- x: h - o,
572
- y: c - o + a * r * u,
573
- width: o * 2,
574
- height: o * 2
575
- },
576
- BOTTOMRIGHT: {
577
- x: h - o + n * i * l,
578
- y: c - o + a * r * u,
579
- width: o * 2,
580
- height: o * 2
581
- }
582
- }[t];
583
- }
584
- setPassive() {
585
- this.mode = z.PASSIVE, this.removeCorners();
586
- }
587
- setActive() {
588
- this.mode = z.ACTIVE, this.addCorners();
589
- }
590
- getPositions() {
591
- return this.target.getPositions();
592
- }
593
- /**
594
- * x and y should be world position
595
- */
596
- hitTest(t, e, i) {
597
- if (this.mode === z.PASSIVE) return;
598
- const [r, n] = tt(this.target.worldMatrix), [a, o] = Tt(this.target.worldMatrix), [h, c] = U(i, t, e), l = 4;
599
- for (const T of Et) {
600
- const S = this.getCornersInScreenSpace(
601
- T,
602
- this.target.worldMatrix
603
- );
604
- if (h >= S.x - l && h <= S.x + S.width + l && c >= S.y - l && c <= S.y + S.height + l)
605
- return T;
606
- }
607
- for (const T of yt) {
608
- const S = this.getSidesInScreenSpace(T, this.target.worldMatrix);
609
- if (h >= S.x - l && h <= S.x + S.width + l && c >= S.y - l && c <= S.y + S.height + l)
610
- return T;
611
- }
612
- const [u, g] = U(this.target.worldMatrix), m = this.width * r * a, w = this.height * n * o, x = Math.min(u, u + m), C = Math.max(u, u + m), v = Math.min(g, g + w), A = Math.max(g, g + w);
613
- if (h >= x && h <= C && c >= v && c <= A)
614
- return "CENTER";
615
- }
616
- update() {
617
- this.updateSides(), this.updateCorners();
618
- }
619
- render(t, e) {
620
- this.update();
621
- for (const [i, r] of this.sides.entries())
622
- r.render(t, e);
623
- for (const [i, r] of this.corners.entries())
624
- r.render(t, e);
625
- }
626
- destroy() {
627
- for (const [t, e] of this.sides.entries())
628
- e.destroy();
629
- for (const [t, e] of this.corners.entries())
630
- e.destroy();
631
- }
632
- move(t, e) {
633
- this.target.updateTranslation(t, e);
634
- }
635
- resize(t, e, i) {
636
- if (this.target instanceof Z) {
637
- const r = Math.abs(this.width), n = Math.abs(this.height), a = r / n, o = this.target.sx, h = this.target.sy, c = 1e-6, l = Math.abs(r * o) < c ? c * Dt(r * o || 1, c) : r * o, u = Math.abs(n * h) < c ? c * Dt(n * h || 1, c) : n * h, g = t / l, m = e / u, w = c, x = i === "LEFT" || i === "BOTTOMLEFT" || i === "TOPLEFT" ? 1 - g : i === "RIGHT" || i === "BOTTOMRIGHT" || i === "TOPRIGHT" ? 1 + g : i === "TOP" ? 1 - m : 1 + m;
638
- if (Bt(o, x, w) || Bt(h, x, w)) return;
639
- const C = r * o * x, v = n * h * x;
640
- if (Math.abs(C) < w || Math.abs(v) < w) return;
641
- if (this.target.updateScale(x, x), i === "LEFT") {
642
- const A = n * h, T = n * this.target.sy;
643
- this.target.updateTranslation(t, (A - T) / 2);
644
- } else if (i === "RIGHT") {
645
- const A = n * h, T = n * this.target.sy;
646
- this.target.updateTranslation(0, (A - T) / 2);
647
- } else if (i === "TOP") {
648
- const A = r * o, T = r * this.target.sx;
649
- this.target.updateTranslation((A - T) / 2, e);
650
- } else if (i === "BOTTOM") {
651
- const A = r * o, T = r * this.target.sx;
652
- this.target.updateTranslation((A - T) / 2, 0);
653
- } else i === "BOTTOMLEFT" ? this.target.updateTranslation(t, 0) : i === "TOPLEFT" ? this.target.updateTranslation(
654
- t,
655
- t / a * Math.sign(this.target.sx)
656
- ) : i === "TOPRIGHT" && this.target.updateTranslation(
657
- 0,
658
- -t / a * Math.sign(this.target.sx)
659
- );
660
- }
661
- }
662
- // a reset method to reset the scale
663
- reset() {
664
- this.target.setScale(1, 1);
665
- }
666
- flip(t) {
667
- const { x: e, y: i, sx: r, sy: n } = this.target;
668
- return t === "vertical" ? this.target.flipVertical(this.height) : this.target.flipHorizontal(this.width), {
669
- ref: this.target,
670
- start: { x: e, y: i, sx: r, sy: n },
671
- end: {
672
- x: this.target.x,
673
- y: this.target.y,
674
- sx: this.target.sx,
675
- sy: this.target.sy
676
- }
677
- };
678
- }
679
- addCorners() {
680
- for (const t of Et) {
681
- const e = new Z(
682
- this.getCornersInScreenSpace(t, this.target.worldMatrix)
683
- );
684
- e.color = this.mode === z.ACTIVE ? ot : Ct, this.corners.set(t, e);
685
- }
686
- }
687
- removeCorners() {
688
- this.corners.clear();
689
- }
690
- updateCorners() {
691
- for (const t of Et) {
692
- const e = this.getCornersInScreenSpace(
693
- t,
694
- this.target.worldMatrix
695
- ), i = this.corners.get(t);
696
- i && (i.setTranslation(e.x, e.y), i.width = e.width, i.height = e.height, i.color = this.mode === z.ACTIVE ? ot : Ct);
697
- }
698
- }
699
- addSides() {
700
- for (const t of yt) {
701
- const e = new Z(
702
- this.getSidesInScreenSpace(t, this.target.worldMatrix)
703
- );
704
- e.color = this.mode === z.ACTIVE ? ot : Ct, this.sides.set(t, e);
705
- }
706
- }
707
- updateSides() {
708
- for (const t of yt) {
709
- const e = this.getSidesInScreenSpace(t, this.target.worldMatrix), i = this.sides.get(t);
710
- i && (i.setTranslation(e.x, e.y), i.width = e.width, i.height = e.height, i.color = this.mode === z.ACTIVE ? ot : Ct);
711
- }
712
- }
713
- }
714
- const Nt = [
715
- ...Et,
716
- ...yt
717
- ];
718
- class _i {
719
- constructor(t) {
720
- this.targets = [], this.handles = /* @__PURE__ */ new Map(), this.borderSize = 0, this.boxSize = 0, this.scale = [1, 1], t && t.forEach((e) => this.add(e)), this.addHandles();
721
- }
722
- add(t) {
723
- this.targets.includes(t) || this.targets.push(t);
724
- }
725
- remove(t) {
726
- const e = this.targets.indexOf(t);
727
- e != -1 && this.targets.splice(e, 1);
728
- }
729
- render(t, e) {
730
- this.update();
731
- for (const [i, r] of this.handles.entries())
732
- r.render(t, e);
733
- }
734
- update() {
735
- this.borderSize = Kt, this.boxSize = Te / 2, this.recalculateBounds(), this.updateHandles();
736
- }
737
- destroy() {
738
- for (const [t, e] of this.handles.entries())
739
- e.destroy();
740
- }
741
- move(t, e) {
742
- for (const i of this.targets)
743
- i.updateTranslation(t, e);
744
- }
745
- // dx and dy are in world units
746
- resize(t, e, i, r) {
747
- const n = this.width, a = this.height, o = i.includes("TOP"), h = i.includes("BOTTOM"), c = i.includes("LEFT"), l = i.includes("RIGHT"), u = c ? this.x + n : l ? this.x : this.x + n / 2, g = o ? this.y + a : h ? this.y : this.y + a / 2, m = 1e-6, w = Math.abs(n) < m ? n < 0 ? -m : m : n, x = Math.abs(a) < m ? a < 0 ? -m : m : a, [C, v] = tt(r), A = t * C / w, T = e * v / x, S = i.includes("LEFT") ? 1 - A : i.includes("RIGHT") ? 1 + A : i === "TOP" ? 1 - T : 1 + T;
748
- if (Bt(this.scale[0], S, m) || Bt(this.scale[1], S, m))
749
- return;
750
- const Ge = n * S, Xe = a * S;
751
- if (!(Math.abs(Ge) < m || Math.abs(Xe) < m))
752
- for (const bt of this.targets) {
753
- const He = bt.x, Ne = bt.y, [ee, ie] = U(r, He, Ne), Ye = u + (ee - u) * S, $e = g + (ie - g) * S, je = Ye - ee, Ve = $e - ie, Ze = Math.abs(C) < m ? C < 0 ? -m : m : C, qe = Math.abs(v) < m ? v < 0 ? -m : m : v, Ke = je / Ze, Qe = Ve / qe;
754
- bt.updateScale(S, S), bt.updateTranslation(Ke, Qe);
755
- }
756
- }
757
- flip(t, e, i) {
758
- tt(t);
759
- const r = [], [n, a] = i(this.x, this.y);
760
- for (const o of this.targets) {
761
- const h = {
762
- ref: o,
763
- start: { x: o.x, y: o.y, sx: o.sx, sy: o.sy }
764
- };
765
- if (e === "vertical") {
766
- const c = o.height * o.sy;
767
- o.setTranslation(o.x, -o.y - c), o.flipVertical(o.height);
768
- } else {
769
- const c = o.width * o.sx;
770
- o.setTranslation(-o.x - c, o.y), o.flipHorizontal(o.width);
771
- }
772
- h.end = {
773
- x: o.x,
774
- y: o.y,
775
- sx: o.sx,
776
- sy: o.sy
777
- }, r.push(h);
778
- }
779
- return r;
780
- }
781
- align(t) {
782
- if (this.targets.length <= 1) return;
783
- const e = [], i = [
784
- t === "top" ? 1 : t === "bottom" ? -1 : 0,
785
- t === "left" ? 1 : t === "right" ? -1 : 0
786
- ];
787
- let r = i[0] !== 0 ? 1 / 0 * i[0] : 1 / 0 * i[1];
788
- for (const [n, a] of this.targets.entries()) {
789
- const o = a.getBoundingBox();
790
- r = t === "top" || t === "left" ? Math.min(t === "top" ? o.minY : o.minX, r) : Math.max(t === "bottom" ? o.maxY : o.maxX, r);
791
- }
792
- for (const n of this.targets) {
793
- const a = {
794
- ref: n,
795
- start: { x: n.x, y: n.y, sx: n.sx, sy: n.sy }
796
- }, o = n.getBoundingBox();
797
- n.updateTranslation(
798
- t === "top" || t === "bottom" ? 0 : r - (t === "left" ? o.minX : o.maxX),
799
- t === "top" || t === "bottom" ? r - (t === "top" ? o.minY : o.maxY) : 0
800
- ), a.end = {
801
- x: n.x,
802
- y: n.y,
803
- sx: n.sx,
804
- sy: n.sy
805
- }, e.push(a);
806
- }
807
- return e;
808
- }
809
- normalize(t, e) {
810
- const i = [], r = this.targets[0], n = t === "height" ? e === "first" ? r.height * r.sy : this.targets.reduce((a, o) => a + Math.abs(o.height * o.sy), 0) / this.targets.length : t === "width" ? e === "first" ? r.width * r.sx : this.targets.reduce((a, o) => a + Math.abs(o.width * o.sx), 0) / this.targets.length : t === "scale" ? e === "first" ? r.sx : this.targets.reduce((a, o) => a + Math.abs(o.sx), 0) / this.targets.length : e === "first" ? r.width * r.height * r.sx * r.sy : this.targets.reduce(
811
- (a, o) => a + Math.abs(o.sx * o.width * o.height * o.sy),
812
- 0
813
- ) / this.targets.length;
814
- for (const a of this.targets) {
815
- const o = {
816
- ref: a,
817
- start: { x: a.x, y: a.y, sx: a.sx, sy: a.sy }
818
- }, h = [
819
- (a.x + a.width * a.sx) / 2,
820
- (a.y + a.height * a.sy) / 2
821
- ];
822
- if (t === "height") {
823
- const l = a.height * a.sy, u = Math.abs(n / l);
824
- a.updateScale(u, u);
825
- } else if (t === "width") {
826
- const l = a.width * a.sx, u = Math.abs(n / l);
827
- a.updateScale(u, u);
828
- } else if (t === "scale") {
829
- const l = Math.sign(a.sx), u = Math.sign(a.sy);
830
- a.setScale(n * l, n * u);
831
- } else if (t === "size") {
832
- const l = a.width * a.height * a.sx * a.sy, u = Math.sqrt(Math.abs(n / l));
833
- a.updateScale(u, u);
834
- }
835
- const c = [
836
- (a.x + a.width * a.sx) / 2,
837
- (a.y + a.height * a.sy) / 2
838
- ];
839
- a.updateTranslation(
840
- h[0] - c[0],
841
- h[1] - c[1]
842
- ), o.end = {
843
- x: a.x,
844
- y: a.y,
845
- sx: a.sx,
846
- sy: a.sy
847
- }, i.push(o);
848
- }
849
- return i;
850
- }
851
- getPositions() {
852
- return [
853
- this.x,
854
- this.y,
855
- // Top-left
856
- this.x + this.width,
857
- this.y,
858
- // Top-right
859
- this.x + this.width,
860
- this.y + this.height,
861
- // Bottom-right
862
- this.x,
863
- this.y + this.height
864
- // Bottom-left
865
- ];
866
- }
867
- hitTest(t, e, i) {
868
- const [r, n] = U(i, t, e), a = 4;
869
- for (const u of Nt) {
870
- const g = this.getHandleConfig(u);
871
- if (r >= g.x - a && r <= g.x + g.width + a && n >= g.y - a && n <= g.y + g.height + a)
872
- return u;
873
- }
874
- const o = Math.min(this.x, this.x + this.width), h = Math.max(this.x, this.x + this.width), c = Math.min(this.y, this.y + this.height), l = Math.max(this.y, this.y + this.height);
875
- if (r >= o && r <= h && n >= c && n <= l)
876
- return "CENTER";
877
- }
878
- getBounds() {
879
- const t = Array.from(this.targets);
880
- let e = 1 / 0, i = 1 / 0, r = -1 / 0, n = -1 / 0;
881
- for (const a of t) {
882
- const [o, h] = U(a.worldMatrix), [c, l] = U(
883
- a.worldMatrix,
884
- a.width,
885
- a.height
886
- );
887
- e = Math.min(e, a.sx < 0 ? c : o), i = Math.min(i, a.sy < 0 ? l : h), r = Math.max(r, a.sx < 0 ? o : c), n = Math.max(n, a.sy < 0 ? h : l);
888
- }
889
- return { minX: e, minY: i, maxX: r, maxY: n };
890
- }
891
- recalculateBounds() {
892
- const { minX: t, minY: e, maxX: i, maxY: r } = this.getBounds();
893
- this.x = this.scale[0] < 0 ? i : t, this.y = this.scale[1] < 0 ? r : e, this.width = this.scale[0] * (i - t), this.height = this.scale[1] * (r - e);
894
- }
895
- addHandles() {
896
- for (const t of Nt) {
897
- const e = this.getHandleConfig(t), i = new Z(e);
898
- i.color = ot, this.handles.set(t, i);
899
- }
900
- }
901
- updateHandles() {
902
- for (const t of Nt) {
903
- const e = this.handles.get(t), i = this.getHandleConfig(t);
904
- e && (e.setTranslation(i.x, i.y), e.width = i.width, e.height = i.height);
905
- }
906
- }
907
- getHandleConfig(t) {
908
- let { x: e, y: i, width: r, height: n, borderSize: a, boxSize: o } = this;
909
- return {
910
- TOP: {
911
- x: e,
912
- y: i,
913
- width: r,
914
- height: a
915
- },
916
- BOTTOM: {
917
- x: e,
918
- y: i + n,
919
- width: r,
920
- height: a
921
- },
922
- LEFT: {
923
- x: e,
924
- y: i,
925
- width: a,
926
- height: n
927
- },
928
- RIGHT: {
929
- x: e + r,
930
- y: i,
931
- width: a,
932
- height: n
933
- },
934
- TOPLEFT: {
935
- x: e - o,
936
- y: i - o,
937
- width: o * 2,
938
- height: o * 2
939
- },
940
- TOPRIGHT: {
941
- x: e - o + r,
942
- y: i - o,
943
- width: o * 2,
944
- height: o * 2
945
- },
946
- BOTTOMLEFT: {
947
- x: e - o,
948
- y: i - o + n,
949
- width: o * 2,
950
- height: o * 2
951
- },
952
- BOTTOMRIGHT: {
953
- x: e - o + r,
954
- y: i - o + n,
955
- width: o * 2,
956
- height: o * 2
957
- }
958
- }[t];
959
- }
960
- }
961
- class et {
962
- // matrix: number[];
963
- constructor(t, e, i, r) {
964
- this.minX = t, this.minY = e, this.maxX = i, this.maxY = r;
965
- }
966
- getArea() {
967
- return (this.maxY - this.minY) * (this.maxX - this.minX);
968
- }
969
- static isColliding(t, e) {
970
- return t.minX <= e.maxX && t.maxX >= e.minX && t.minY <= e.maxY && t.maxY >= e.minY;
971
- }
972
- }
973
- const de = ["CENTER", ...yt];
974
- class Ri {
975
- constructor(t, e, i) {
976
- this.width = 0, this.height = 0, this.rects = /* @__PURE__ */ new Map(), this.borderSize = 0;
977
- const [r, n] = U(i, t, e);
978
- this.x = r, this.y = n, this.addRects();
979
- }
980
- getRectConfig(t) {
981
- let { x: e, y: i, width: r, height: n, borderSize: a } = this;
982
- return {
983
- TOP: {
984
- x: e,
985
- y: i,
986
- width: r < 0 ? r : r + a,
987
- height: a
988
- },
989
- BOTTOM: {
990
- x: e,
991
- y: i + n,
992
- width: r < 0 ? r : r + a,
993
- height: a
994
- },
995
- LEFT: {
996
- x: n < 0 && r < 0 ? e - a : e,
997
- y: i,
998
- width: a,
999
- height: n < 0 && r < 0 ? n : n + a
1000
- },
1001
- RIGHT: {
1002
- x: e + r,
1003
- y: i,
1004
- width: a,
1005
- height: n < 0 ? n : n + a
1006
- },
1007
- CENTER: {
1008
- x: e,
1009
- y: i,
1010
- width: r,
1011
- height: n
1012
- }
1013
- }[t];
1014
- }
1015
- render(t, e) {
1016
- this.update();
1017
- for (const [i, r] of this.rects.entries())
1018
- r.render(t, e);
1019
- }
1020
- update() {
1021
- this.borderSize = Kt, this.updateRects();
1022
- }
1023
- destroy() {
1024
- for (const [t, e] of this.rects.entries())
1025
- e.destroy();
1026
- }
1027
- /**
1028
- * Apply bounding box in world dimension
1029
- * @returns
1030
- */
1031
- getBoundingBox(t) {
1032
- const [e, i] = t(this.x, this.y), [r, n] = t(this.x + this.width, this.y + this.height), a = Math.min(e, r), o = Math.max(e, r), h = Math.min(i, n), c = Math.max(i, n);
1033
- return new et(a, h, o, c);
1034
- }
1035
- resize(t, e, i) {
1036
- const [r, n] = tt(i);
1037
- this.width += t * r, this.height += e * n;
1038
- }
1039
- addRects() {
1040
- for (const t of de) {
1041
- const e = this.getRectConfig(t), i = new Z(e);
1042
- i.color = ot, this.rects.set(t, i);
1043
- }
1044
- }
1045
- updateRects() {
1046
- for (const t of de) {
1047
- const e = this.rects.get(t), i = this.getRectConfig(t);
1048
- e && (e.setTranslation(i.x, i.y), e.width = i.width, e.height = i.height, t === "CENTER" && (e.color = gi));
1049
- }
1050
- }
1051
- }
1052
- class Ii {
1053
- constructor(t = {}) {
1054
- const {
1055
- x: e = 0,
1056
- y: i = 0,
1057
- width: r = 0,
1058
- height: n = 0,
1059
- rotation: a = 0,
1060
- zoom: o = 1
1061
- } = t;
1062
- this.x = e, this.y = i, this.width = r, this.height = n, this.rotation = a, this.zoom = o, Ee(this, {
1063
- x: B,
1064
- y: B,
1065
- width: B,
1066
- height: B,
1067
- rotation: B,
1068
- zoom: B,
1069
- setX: b,
1070
- setY: b,
1071
- setPosition: b,
1072
- incrementPosition: b,
1073
- setWidth: b,
1074
- setHeight: b,
1075
- setSize: b,
1076
- setZoom: b,
1077
- setRotation: b,
1078
- stateVector: nt
1079
- });
1080
- }
1081
- // Actions
1082
- setX(t) {
1083
- this.x = t;
1084
- }
1085
- setY(t) {
1086
- this.y = t;
1087
- }
1088
- setPosition(t, e) {
1089
- this.x = t, this.y = e;
1090
- }
1091
- incrementPosition(t, e) {
1092
- this.x += t, this.y += e;
1093
- }
1094
- setWidth(t) {
1095
- this.width = t;
1096
- }
1097
- setHeight(t) {
1098
- this.height = t;
1099
- }
1100
- setSize(t, e) {
1101
- this.width = t, this.height = e;
1102
- }
1103
- setZoom(t) {
1104
- this.zoom = t;
1105
- }
1106
- setRotation(t) {
1107
- this.rotation = t;
1108
- }
1109
- get dimension() {
1110
- return [this.width, this.height];
1111
- }
1112
- get position() {
1113
- return [this.x, this.y];
1114
- }
1115
- get stateVector() {
1116
- return [this.x, this.y, this.width, this.height, this.rotation, this.zoom];
1117
- }
1118
- get translationMatrix() {
1119
- return E.translation(this.x, this.y);
1120
- }
1121
- get rotationMatrix() {
1122
- return E.rotation(this.rotation);
1123
- }
1124
- get scaleMatrix() {
1125
- return E.scaling(this.zoom, this.zoom);
1126
- }
1127
- get cameraMatrix() {
1128
- const t = E.multiply(this.translationMatrix, this.rotationMatrix);
1129
- return E.multiply(t, this.scaleMatrix);
1130
- }
1131
- get canvasMatrix() {
1132
- return E.inverse(this.cameraMatrix);
1133
- }
1134
- }
1135
- function le(s, t) {
1136
- s.setTranslation(t.x, t.y), s.setScale(t.sx, t.sy);
1137
- }
1138
- function ue(s, t, e) {
1139
- return {
1140
- label: "Flip",
1141
- do() {
1142
- for (const i of s) le(i.ref, i.end);
1143
- e && (e.scale[t === "horizontal" ? 0 : 1] *= -1);
1144
- },
1145
- undo() {
1146
- for (const i of s) le(i.ref, i.start);
1147
- e && (e.scale[t === "horizontal" ? 0 : 1] *= -1);
1148
- }
1149
- };
1150
- }
1151
- function fe(s, t) {
1152
- s.setTranslation(t.x, t.y), s.setScale(t.sx, t.sy);
1153
- }
1154
- function jt(s, t = "Transform") {
1155
- return {
1156
- label: t,
1157
- do() {
1158
- for (const e of s) fe(e.ref, e.end);
1159
- },
1160
- undo() {
1161
- for (const e of s) fe(e.ref, e.start);
1162
- }
1163
- };
1164
- }
1165
- class Pi {
1166
- // #canvas: Canvas;
1167
- #s;
1168
- #i = /* @__PURE__ */ new Set();
1169
- #e = /* @__PURE__ */ new Set();
1170
- #t;
1171
- #r;
1172
- #a;
1173
- get multiBoundingBox() {
1174
- return this.#t;
1175
- }
1176
- get boundingBoxes() {
1177
- return this.#e;
1178
- }
1179
- #o = !0;
1180
- #n;
1181
- #h;
1182
- get selected() {
1183
- return Array.from(this.#i);
1184
- }
1185
- set selected(t) {
1186
- this.#i.clear(), t.forEach((e) => {
1187
- this.#i.add(e), this.#e.add(new ce(e));
1188
- });
1189
- }
1190
- get marqueeBox() {
1191
- return this.#r;
1192
- }
1193
- set marqueeBox(t) {
1194
- this.#r = new Ri(
1195
- t.x,
1196
- t.y,
1197
- this.getWorldMatrix()
1198
- );
1199
- }
1200
- constructor(t, e, i, r, n, a, o, h) {
1201
- this.#n = i, this.#h = r, this.#s = t, this.#a = e, this.getWorldMatrix = n, this.getCanvasChildren = a, this.getWorldCoords = o, this.getMarqueeCoords = h;
1202
- const c = Object.getPrototypeOf(this);
1203
- for (const l of Object.getOwnPropertyNames(c)) {
1204
- const u = this[l];
1205
- typeof u == "function" && l !== "constructor" && (this[l] = u.bind(this));
1206
- }
1207
- }
1208
- // add, remove selected
1209
- add(t) {
1210
- t.forEach((e) => {
1211
- this.#i.has(e) || (this.#i.add(e), this.#e.add(new ce(e)));
1212
- }), this.#e.size > 1 && (this.#e.forEach((e) => e.setPassive()), this.#t || (this.#t = new _i([])), this.selected.forEach((e) => this.#t.add(e)));
1213
- }
1214
- remove(t) {
1215
- t.forEach((e) => {
1216
- if (!this.#i.has(e)) return;
1217
- this.#i.delete(e);
1218
- const i = Array.from(this.#e.values()).find(
1219
- (r) => r.target === e
1220
- );
1221
- i ? this.#e.delete(i) : console.error("No matching bounding box found"), this.#t && this.#t.remove(e);
1222
- }), this.#e.size <= 1 && (this.#e.forEach((e) => e.setActive()), this.#t = null);
1223
- }
1224
- deleteSelected(t) {
1225
- const e = [...this.#i];
1226
- this.remove(e);
1227
- for (const i of e)
1228
- i.destroy();
1229
- this.#s.push(xi(t, e));
1230
- }
1231
- /**
1232
- * Checks first if there is a hit in a multibounding and its handles. If not, check the one bounding box that is active.
1233
- */
1234
- hitTest(t, e) {
1235
- if (this.#t) {
1236
- const i = this.#t.hitTest(t, e, this.getWorldMatrix());
1237
- if (i) return i;
1238
- }
1239
- for (const i of this.#e.values()) {
1240
- const r = i.hitTest(t, e, this.getWorldMatrix());
1241
- if (r) return r;
1242
- }
1243
- return null;
1244
- }
1245
- isMultiBoundingBoxHit(t, e) {
1246
- return this.#t && this.#t.hitTest(t, e, this.getWorldMatrix());
1247
- }
1248
- isBoundingBoxHit(t, e) {
1249
- return this.#e.size === 1 && Array.from(this.#e)[0].hitTest(t, e, this.getWorldMatrix());
1250
- }
1251
- hitTestAdjustedCorner(t, e) {
1252
- if (this.#t) {
1253
- const i = this.#t.hitTest(t, e, this.getWorldMatrix());
1254
- if (i)
1255
- return this.#t.scale[0] * this.#t.scale[1] < 0 ? ae(i) : i;
1256
- }
1257
- for (const i of this.#e.values()) {
1258
- const r = i.hitTest(t, e, this.getWorldMatrix());
1259
- if (r)
1260
- return i.target.sx * i.target.sy < 0 ? ae(r) : r;
1261
- }
1262
- }
1263
- /**
1264
- * Update the existing bounding boxes
1265
- */
1266
- update() {
1267
- this.#e.forEach((t) => t.update()), this.#t && this.#t.update();
1268
- }
1269
- render(t) {
1270
- if (!this.#r && !this.#t && this.#e.size === 0)
1271
- return;
1272
- this.#n.useProgram(t);
1273
- const e = this.#n.getUniformLocation(t, "u_z");
1274
- e && this.#n.uniform1f(e, 1), this.#o && this.#e.forEach((i) => i.render(this.#n, t)), this.#t && this.#t.render(this.#n, t), this.#r && this.#r.render(this.#n, t);
1275
- }
1276
- isRectSelected(t) {
1277
- return this.#i.has(t);
1278
- }
1279
- clear() {
1280
- this.#i.clear(), this.#e.clear(), this.#t = null;
1281
- }
1282
- clearMarquee() {
1283
- this.#r && (this.#r = null);
1284
- }
1285
- move(t, e) {
1286
- if (this.#t)
1287
- this.#t.move(t, e);
1288
- else
1289
- for (const i of this.#e)
1290
- i.move(t, e);
1291
- this.#a.emit(N.Change);
1292
- }
1293
- /**
1294
- * Based on the corner you're dragging and the sign of the scaleX and scaleY values, there are only four possible sets of changes to the target's translation.
1295
- * 1) absolutely no change
1296
- * 2) x translation change only if negative delta
1297
- * 3) y translation change only if negative delta
1298
- * 4) x and y translation change if negative delta
1299
- * The tricky part is to consider the signs of the scale values and determine which corner is going to inhabit which behaviour.
1300
- * @param dx
1301
- * @param dy
1302
- * @param direction
1303
- */
1304
- resize(t, e, i) {
1305
- this.multiBoundingBox && this.multiBoundingBox.resize(t, e, i, this.getWorldMatrix());
1306
- for (const r of this.boundingBoxes)
1307
- this.multiBoundingBox ? r.update() : r.resize(t, e, i);
1308
- this.#a.emit(N.Change);
1309
- }
1310
- flip(t) {
1311
- if (this.multiBoundingBox) {
1312
- const e = this.multiBoundingBox.flip(
1313
- this.getWorldMatrix(),
1314
- t,
1315
- this.getWorldCoords
1316
- );
1317
- this.#s.push(
1318
- ue(e, t, this.multiBoundingBox)
1319
- );
1320
- } else {
1321
- const e = [];
1322
- for (const i of this.boundingBoxes)
1323
- e.push(i.flip(t));
1324
- this.#s.push(ue(e, t));
1325
- }
1326
- this.#a.emit(N.Change);
1327
- }
1328
- alignSelection(t) {
1329
- if (!this.multiBoundingBox) return;
1330
- const e = this.multiBoundingBox.align(t);
1331
- this.#s.push(jt(e)), this.#a.emit(N.Change);
1332
- }
1333
- normalize(t, e = "first") {
1334
- if (!this.multiBoundingBox) return;
1335
- const i = this.multiBoundingBox.normalize(t, e);
1336
- this.#s.push(jt(i)), this.#a.emit(N.Change);
1337
- }
1338
- onPointerMove(t, e, i, r, n, a, o, h) {
1339
- if (a())
1340
- o(t, e);
1341
- else if (n && n !== "CENTER")
1342
- this.resize(i, r, n);
1343
- else if (this.marqueeBox) {
1344
- this.marqueeBox.resize(i, r, h());
1345
- const c = this.getCanvasChildren(), l = this.marqueeBox.getBoundingBox(this.getMarqueeCoords);
1346
- for (const u of c) {
1347
- const g = u.getBoundingBox();
1348
- et.isColliding(g, l) && !this.#i.has(u) ? this.add([u]) : !et.isColliding(g, l) && this.#i.has(u) && this.remove([u]);
1349
- }
1350
- } else
1351
- this.move(i, r);
1352
- }
1353
- onSelectionPointerDown(t, e, i, r) {
1354
- e ? (t || this.clear(), this.add([e])) : (this.clear(), this.marqueeBox ? this.clearMarquee() : this.marqueeBox = { x: i, y: r });
1355
- }
1356
- // keep this for exporting as image in the future
1357
- // async copy() {
1358
- // const images = this.selected as Img[];
1359
- // if (images.length === 0) return;
1360
- // let blob: Blob;
1361
- // if (images.length === 1 && images[0].src.startsWith('data:image/png')) {
1362
- // // Fast path: already a PNG data URL
1363
- // const [header, base64] = images[0].src.split(',');
1364
- // const binary = atob(base64);
1365
- // const array = new Uint8Array(binary.length);
1366
- // for (let i = 0; i < binary.length; i++) array[i] = binary.charCodeAt(i);
1367
- // blob = new Blob([array], { type: 'image/png' });
1368
- // } else {
1369
- // // Batch draw all images to an offscreen canvas
1370
- // const { mergedCanvas, width, height } = await mergeImagesToCanvas(images);
1371
- // blob = await new Promise<Blob>(resolve => mergedCanvas.toBlob(b => resolve(b), 'image/png'));
1372
- // }
1373
- // const storedItem = new ClipboardItem({ [blob.type]: blob });
1374
- // try {
1375
- // await navigator.clipboard.write([storedItem]);
1376
- // } catch (err) {
1377
- // console.error(err);
1378
- // }
1379
- // }
1380
- }
1381
- var mt = /* @__PURE__ */ ((s) => (s[s.SELECT = 0] = "SELECT", s[s.PAN = 1] = "PAN", s))(mt || {});
1382
- const Ai = {
1383
- TOP: "ns-resize",
1384
- BOTTOM: "ns-resize",
1385
- LEFT: "ew-resize",
1386
- RIGHT: "ew-resize",
1387
- TOPLEFT: "nwse-resize",
1388
- BOTTOMRIGHT: "nwse-resize",
1389
- TOPRIGHT: "nesw-resize",
1390
- BOTTOMLEFT: "nesw-resize",
1391
- CENTER: "grab"
1392
- };
1393
- class Li {
1394
- constructor(t) {
1395
- for (const e in t)
1396
- e in t && t[e] !== void 0 && (this[e] = t[e]);
1397
- this.onPointerDown = this.onPointerDown.bind(this), this.onPointerMoveWhileDown = this.onPointerMoveWhileDown.bind(this), this.onPointerUp = this.onPointerUp.bind(this), this.addOnPointerMove(), this.addOnWheel(t.onWheel), this.addOnPointerDown(), window.addEventListener("copy", async (e) => {
1398
- e.preventDefault(), !this.isContextMenuActive() && await Re(this.getSelected());
1399
- }), window.addEventListener("paste", async (e) => {
1400
- e.preventDefault(), !this.isContextMenuActive() && await t.paste(
1401
- this.state.lastPointerPos.x,
1402
- this.state.lastPointerPos.y
1403
- );
1404
- });
1405
- }
1406
- changeMode() {
1407
- this.state.toggleMode();
1408
- }
1409
- // Add events
1410
- addOnPointerDown() {
1411
- this.assignEventListener("pointerdown", this.onPointerDown);
1412
- }
1413
- addOnPointerMove() {
1414
- this.assignEventListener("pointermove", (t) => {
1415
- [this.state.lastPointerPos.x, this.state.lastPointerPos.y] = this.getWorldCoords(t.clientX, t.clientY);
1416
- let e = this.hitTestAdjustedCorner(
1417
- this.state.lastPointerPos.x,
1418
- this.state.lastPointerPos.y
1419
- );
1420
- this.setCursorStyle(Ai[e] || "default");
1421
- });
1422
- }
1423
- addOnWheel(t) {
1424
- this.assignEventListener(
1425
- "wheel",
1426
- (e) => {
1427
- this.isContextMenuActive() || t(e);
1428
- },
1429
- { passive: !1 }
1430
- );
1431
- }
1432
- onPointerDown(t) {
1433
- t.stopPropagation(), t.preventDefault(), this.eventHub.emit(H.Close);
1434
- const [e, i] = this.getWorldCoords(t.clientX, t.clientY);
1435
- this.state.initialize(e, i), this.currentTransform = void 0, this.state.mode === 1 ? this.handlePanPointerDown() : this.state.mode === 0 && this.handleSelectPointerDown(t, e, i), document.addEventListener("pointermove", this.onPointerMoveWhileDown), document.addEventListener("pointerup", this.onPointerUp);
1436
- }
1437
- handlePanPointerDown() {
1438
- this.setCanvasGlobalClick(!0), this.clearSelection();
1439
- }
1440
- handleSelectPointerDown(t, e, i) {
1441
- this.setCanvasGlobalClick(!1);
1442
- const r = this.checkCollidingChild(e, i), n = this.checkIfSelectionHit(e, i);
1443
- if (t.button === 2)
1444
- n || this.clearSelection(), r && !this.isSelection(r) && this.addSelection([r]);
1445
- else {
1446
- n ? this.state.resizingDirection = n : this.onSelectionPointerDown(t.shiftKey, r, e, i);
1447
- const a = this.getSelected();
1448
- a.length && (this.currentTransform = {
1449
- targets: a.map((o) => ({
1450
- ref: o,
1451
- start: { x: o.x, y: o.y, sx: o.sx, sy: o.sy }
1452
- }))
1453
- });
1454
- }
1455
- }
1456
- onPointerMoveWhileDown(t) {
1457
- if (t.buttons === 2) return;
1458
- const [e, i] = this.getWorldCoords(t.clientX, t.clientY), r = e - this.state.lastWorldX, n = i - this.state.lastWorldY;
1459
- this.selectionPointerMove(
1460
- this.state.startWorldX - e,
1461
- this.state.startWorldY - i,
1462
- r,
1463
- n,
1464
- this.state.resizingDirection
1465
- ), this.state.updateLastWorldCoord(e, i), this.setCursorStyle("grabbing");
1466
- }
1467
- onPointerUp() {
1468
- if (document.removeEventListener("pointermove", this.onPointerMoveWhileDown), document.removeEventListener("pointerup", this.onPointerUp), this.setCanvasGlobalClick(!0), this.setCursorStyle("default"), this.currentTransform) {
1469
- const t = this.currentTransform.targets.map((e) => ({
1470
- ref: e.ref,
1471
- start: e.start,
1472
- end: { x: e.ref.x, y: e.ref.y, sx: e.ref.sx, sy: e.ref.sy }
1473
- })).filter(
1474
- (e) => e.start.x !== e.end.x || e.start.y !== e.end.y || e.start.sx !== e.end.sx || e.start.sy !== e.end.sy
1475
- );
1476
- t.length && this.history.push(jt(t));
1477
- }
1478
- this.currentTransform = void 0, this.state.resizingDirection = null, this.closeMarquee(), this.eventHub.emit("save");
1479
- }
1480
- checkCollidingChild(t, e) {
1481
- const i = this.getChildren();
1482
- for (let r = i.length - 1; r >= 0; r--) {
1483
- const n = i[r];
1484
- if (n instanceof ut && n.hitTest && n.hitTest(t, e))
1485
- return n;
1486
- }
1487
- return null;
1488
- }
1489
- }
1490
- class Oi {
1491
- constructor(t, e, i, r) {
1492
- this.history = t, this.deleteSelected = i, this.save = () => e.emit(N.Save), this.assignEventListener = r, this.onKeyPressed = this.onKeyPressed.bind(this), this.addOnKeyPressed();
1493
- }
1494
- addOnKeyPressed() {
1495
- document.addEventListener("keydown", this.onKeyPressed);
1496
- }
1497
- onKeyPressed(t) {
1498
- if (this.isCtrlZ(t)) {
1499
- t.preventDefault(), this.history.undo();
1500
- return;
1501
- }
1502
- if (this.isCtrlY(t)) {
1503
- t.preventDefault(), this.history.redo();
1504
- return;
1505
- }
1506
- if (this.isDelete(t)) {
1507
- this.deleteSelected();
1508
- return;
1509
- }
1510
- if (this.isSave(t)) {
1511
- t.preventDefault(), this.save();
1512
- return;
1513
- }
1514
- }
1515
- isCtrlZ(t) {
1516
- return t.key.toLowerCase() === "z" && (t.ctrlKey || t.metaKey) && !t.shiftKey;
1517
- }
1518
- isCtrlY(t) {
1519
- return t.key.toLowerCase() === "y" && (t.ctrlKey || t.metaKey) && !t.shiftKey;
1520
- }
1521
- isDelete(t) {
1522
- return t.key === "Delete";
1523
- }
1524
- isSave(t) {
1525
- return t.key.toLowerCase() === "s" && t.ctrlKey;
1526
- }
1527
- }
1528
- class Di {
1529
- #s = !1;
1530
- get isActive() {
1531
- return this.#s;
1532
- }
1533
- constructor(t, e, i, r, n) {
1534
- this.customContextMenu = (a) => {
1535
- a.preventDefault(), a.stopPropagation();
1536
- const [o, h] = r(a.clientX, a.clientY);
1537
- e(o, h) ? t.emit(H.Open, a.clientX, a.clientY, "multi") : i(o, h) ? t.emit(H.Open, a.clientX, a.clientY) : t.emit(H.Open, a.clientX, a.clientY, "canvas");
1538
- }, t.on(H.Open, () => {
1539
- this.#s = !0;
1540
- }), t.on(H.Close, () => {
1541
- this.#s = !1;
1542
- }), n("contextmenu", this.customContextMenu);
1543
- }
1544
- }
1545
- function me(s, t) {
1546
- s.renderOrder = t.renderOrder;
1547
- }
1548
- function Bi(s, t = "Order") {
1549
- return {
1550
- label: t,
1551
- do() {
1552
- for (const e of s) me(e.ref, e.end);
1553
- },
1554
- undo() {
1555
- for (const e of s) me(e.ref, e.start);
1556
- }
1557
- };
1558
- }
1559
- class zi {
1560
- constructor(t = mt.SELECT) {
1561
- this.lastPointerPos = { x: 0, y: 0 }, this.startWorldX = 0, this.startWorldY = 0, this.lastWorldX = 0, this.lastWorldY = 0, this.resizingDirection = null, this.mode = t;
1562
- }
1563
- // computed
1564
- get isResizing() {
1565
- return this.resizingDirection !== null;
1566
- }
1567
- get dragDXFromStart() {
1568
- return this.lastWorldX - this.startWorldX;
1569
- }
1570
- get dragDYFromStart() {
1571
- return this.lastWorldY - this.startWorldY;
1572
- }
1573
- // actions
1574
- setMode(t) {
1575
- this.mode = t;
1576
- }
1577
- toggleMode() {
1578
- this.mode = this.mode === mt.PAN ? mt.SELECT : mt.PAN;
1579
- }
1580
- setResizingDirection(t) {
1581
- this.resizingDirection = t;
1582
- }
1583
- clearResizingDirection() {
1584
- this.resizingDirection = null;
1585
- }
1586
- // Start an interaction at given world coords
1587
- initialize(t, e) {
1588
- this.startWorldX = t, this.startWorldY = e, this.lastWorldX = t, this.lastWorldY = e, this.resizingDirection = null;
1589
- }
1590
- updateLastWorldCoord(t, e) {
1591
- this.lastWorldX = t, this.lastWorldY = e;
1592
- }
1593
- }
1594
- class ki {
1595
- // reduces constant work to re-render if there are no changes
1596
- constructor() {
1597
- this.translation = [0, 0], this.angleRadians = 0, this.scale = [1, 1], this.localMatrix = E.identity(), this.worldMatrix = E.identity(), this.children = [], this.parent = null, this.renderDirtyFlag = !0, Ee(this, {
1598
- translation: B.struct,
1599
- angleRadians: B,
1600
- scale: B.struct,
1601
- localMatrix: B.ref,
1602
- worldMatrix: B.ref,
1603
- children: B.shallow,
1604
- parent: B.ref,
1605
- renderDirtyFlag: B,
1606
- x: nt,
1607
- y: nt,
1608
- scaleX: nt,
1609
- scaleY: nt,
1610
- dirty: nt,
1611
- setTranslation: b,
1612
- setScale: b,
1613
- flipVertical: b,
1614
- setAngle: b,
1615
- getChild: b,
1616
- appendChild: b,
1617
- appendChildren: b,
1618
- removeChild: b,
1619
- clearChildren: b,
1620
- setParent: b,
1621
- markDirty: b,
1622
- clearDirty: b,
1623
- updateLocalMatrix: b,
1624
- updateWorldMatrix: b,
1625
- setWorldMatrix: b
1626
- }), this.updateLocalMatrix(), this.updateWorldMatrix();
1627
- }
1628
- // Computed
1629
- get x() {
1630
- return this.translation[0];
1631
- }
1632
- get y() {
1633
- return this.translation[1];
1634
- }
1635
- get scaleX() {
1636
- return this.scale[0];
1637
- }
1638
- get scaleY() {
1639
- return this.scale[1];
1640
- }
1641
- get dirty() {
1642
- return this.renderDirtyFlag;
1643
- }
1644
- // Actions
1645
- setTranslation(t, e) {
1646
- this.translation[0] = t, this.translation[1] = e, this.markDirty();
1647
- }
1648
- updateTranslation(t, e) {
1649
- this.translation[0] += t, this.translation[1] += e, this.markDirty();
1650
- }
1651
- setScale(t, e) {
1652
- t === this.scale[0] && e === this.scale[1] || (this.scale[0] = t, this.scale[1] = e, this.markDirty());
1653
- }
1654
- updateScale(t, e) {
1655
- this.scale[0] *= t, this.scale[1] *= e, this.markDirty();
1656
- }
1657
- flipVertical(t) {
1658
- this.translation[1] += this.scale[1] * t, this.scale[1] *= -1, this.markDirty();
1659
- }
1660
- flipHorizontal(t) {
1661
- this.translation[0] += this.scale[0] * t, this.scale[0] *= -1, this.markDirty();
1662
- }
1663
- setAngle(t) {
1664
- const i = (360 - t) * Math.PI / 180;
1665
- i !== this.angleRadians && (this.angleRadians = i, this.markDirty());
1666
- }
1667
- getChild(t) {
1668
- return this.children[t];
1669
- }
1670
- appendChild(t) {
1671
- this.children.includes(t) || (this.children.push(t), this.markDirty());
1672
- }
1673
- appendChildren(t) {
1674
- for (const e of t) {
1675
- if (this.children.includes(e)) return;
1676
- this.children.push(e);
1677
- }
1678
- this.markDirty();
1679
- }
1680
- removeChild(t) {
1681
- const e = this.children.indexOf(t);
1682
- if (e < 0) return;
1683
- const i = this.children.splice(e, 1);
1684
- return t.state.setParent(null), this.markDirty(), i[0];
1685
- }
1686
- clearChildren() {
1687
- if (this.children) {
1688
- for (const t of this.children)
1689
- t.destroy();
1690
- this.children = [], this.markDirty();
1691
- }
1692
- }
1693
- setParent(t) {
1694
- this.parent !== t && (this.parent = t, this.markDirty());
1695
- }
1696
- markDirty() {
1697
- this.renderDirtyFlag || (this.renderDirtyFlag = !0, this.updateLocalMatrix());
1698
- }
1699
- clearDirty() {
1700
- this.renderDirtyFlag && (this.renderDirtyFlag = !1, this.updateLocalMatrix());
1701
- }
1702
- updateLocalMatrix() {
1703
- const t = E.translation(this.translation[0], this.translation[1]), e = E.rotation(this.angleRadians), i = E.scaling(this.scale[0], this.scale[1]);
1704
- this.localMatrix = E.multiply(E.multiply(t, e), i);
1705
- }
1706
- updateWorldMatrix(t) {
1707
- this.worldMatrix = t ? E.multiply(t, this.localMatrix) : this.localMatrix.slice();
1708
- const e = this.worldMatrix;
1709
- this.children.forEach((i) => {
1710
- i.updateWorldMatrix(e);
1711
- });
1712
- }
1713
- setWorldMatrix(t) {
1714
- this.worldMatrix = t;
1715
- }
1716
- }
1717
- class Pe {
1718
- get x() {
1719
- return this.state.x;
1720
- }
1721
- get y() {
1722
- return this.state.y;
1723
- }
1724
- get sx() {
1725
- return this.state.scaleX;
1726
- }
1727
- get sy() {
1728
- return this.state.scaleY;
1729
- }
1730
- get dirty() {
1731
- return this.state.dirty;
1732
- }
1733
- get localMatrix() {
1734
- return this.state.localMatrix;
1735
- }
1736
- get worldMatrix() {
1737
- return this.state.worldMatrix;
1738
- }
1739
- get children() {
1740
- return this.state.children;
1741
- }
1742
- get parent() {
1743
- return this.state.parent;
1744
- }
1745
- get angleRadians() {
1746
- return this.state.angleRadians;
1747
- }
1748
- updateTranslation(t, e) {
1749
- this.state.updateTranslation(t, e);
1750
- }
1751
- setTranslation(t, e) {
1752
- this.state.setTranslation(t, e);
1753
- }
1754
- updateScale(t, e) {
1755
- this.state.updateScale(t, e);
1756
- }
1757
- setScale(t, e) {
1758
- this.state.setScale(t, e);
1759
- }
1760
- setAngle(t) {
1761
- return this.state.setAngle(t);
1762
- }
1763
- flipVertical(t) {
1764
- this.state.flipVertical(t);
1765
- }
1766
- flipHorizontal(t) {
1767
- this.state.flipHorizontal(t);
1768
- }
1769
- markDirty() {
1770
- this.state.markDirty();
1771
- }
1772
- clearDirty() {
1773
- this.state.clearDirty();
1774
- }
1775
- updateLocalMatrix() {
1776
- this.state.updateLocalMatrix();
1777
- }
1778
- setWorldMatrix(t) {
1779
- this.state.setWorldMatrix(t);
1780
- }
1781
- addChild(t) {
1782
- this.state.appendChild(t);
1783
- }
1784
- addParent(t) {
1785
- return this.state.setParent(t);
1786
- }
1787
- clearChildren() {
1788
- return this.state.clearChildren();
1789
- }
1790
- constructor() {
1791
- this.state = new ki(), this.setWorldMatrix = this.setWorldMatrix.bind(this), this.updateWorldMatrix = this.updateWorldMatrix.bind(this);
1792
- }
1793
- appendChild(t) {
1794
- return t.setParent(this), !t._emitter && this._emitter && (t._emitter = this._emitter), t;
1795
- }
1796
- setParent(t) {
1797
- if (this.parent) {
1798
- const e = this.parent.children.indexOf(this);
1799
- e >= 0 && this.parent.children.splice(e, 1);
1800
- }
1801
- t && t.addChild(this), this.addParent(t);
1802
- }
1803
- updateWorldMatrix(t) {
1804
- this.updateLocalMatrix(), this.state.updateWorldMatrix(t);
1805
- }
1806
- addEventListener(t, e, i) {
1807
- const r = typeof e == "function" ? e : e.handleEvent.bind(e);
1808
- this._emitter.on(t, r);
1809
- }
1810
- removeEventListener(t, e, i) {
1811
- }
1812
- dispatchEvent(t) {
1813
- return this._emitter.emit(t.type, t), !t.defaultPrevented;
1814
- }
1815
- }
1816
- class Ae extends Pe {
1817
- constructor() {
1818
- super(...arguments), this.initialized = !1;
1819
- }
1820
- updateVertexData(t) {
1821
- const e = this.getPositions();
1822
- (!this.vertexArray || this.vertexArray.length !== e.length) && (this.vertexArray = new Float32Array(e.length)), this.vertexArray.set(e), t.bindBuffer(t.ARRAY_BUFFER, this.positionBuffer), t.bufferData(t.ARRAY_BUFFER, this.vertexArray, t.STATIC_DRAW);
1823
- }
1824
- setUpVertexData(t, e) {
1825
- this.positionBuffer || (this.positionBuffer = t.createBuffer()), this.attributeLocation = t.getAttribLocation(e, "a_position");
1826
- }
1827
- setUpUniforms(t, e) {
1828
- this.resolutionLocation = t.getUniformLocation(e, "u_resolution"), this.matrixLocation = t.getUniformLocation(e, "u_matrix");
1829
- }
1830
- updateUniforms(t) {
1831
- t.uniform2f(this.resolutionLocation, t.canvas.width, t.canvas.height), t.uniformMatrix3fv(this.matrixLocation, !1, this.worldMatrix);
1832
- }
1833
- }
1834
- const Wt = class Wt extends Ae {
1835
- constructor(t, e, i = 1, r = 1) {
1836
- super(), this._seq = Wt._seqCounter++, this.culled = !1, this._renderOrder = 0, this.color = [1, 0, 0.5, 1], this.setTranslation(t, e), this.setScale(i, r);
1837
- }
1838
- get renderOrder() {
1839
- return this._renderOrder;
1840
- }
1841
- set renderOrder(t) {
1842
- this._renderOrder !== t && (this._renderOrder = t, this.markDirty());
1843
- }
1844
- get seq() {
1845
- return this._seq;
1846
- }
1847
- getZ() {
1848
- const e = this.renderOrder * 1e-4 + 0.5;
1849
- return Math.max(0, Math.min(1, e));
1850
- }
1851
- render(t, e) {
1852
- this.updateWorldMatrix(this.parent ? this.parent.worldMatrix : void 0), t.useProgram(e), this.dirty && !this.culled && (this.initialized || (this.setUpVertexData(t, e), this.setUpUniforms(t, e), this.initialized = !0), this.updateVertexData(t), this.clearDirty()), this.updateUniforms(t);
1853
- const i = t.getUniformLocation(e, "u_color");
1854
- i && t.uniform4fv(i, this.color), this.culled || this.draw(t);
1855
- }
1856
- draw(t) {
1857
- t.bindBuffer(t.ARRAY_BUFFER, this.positionBuffer);
1858
- const e = 2, i = t.FLOAT;
1859
- t.vertexAttribPointer(
1860
- this.attributeLocation,
1861
- e,
1862
- i,
1863
- !1,
1864
- 0,
1865
- 0
1866
- ), t.enableVertexAttribArray(this.attributeLocation), t.drawArrays(t.TRIANGLES, 0, this.getVertexCount()), t.bindBuffer(t.ARRAY_BUFFER, null), t.disableVertexAttribArray(this.attributeLocation);
1867
- }
1868
- destroy() {
1869
- this.positionBuffer && (this.positionBuffer = void 0), this.initialized = !1;
1870
- }
1871
- };
1872
- Wt._seqCounter = 0;
1873
- let ut = Wt;
1874
- class Z extends ut {
1875
- constructor(t) {
1876
- super(t.x, t.y, t.sx, t.sy), this._width = t.width ?? 100, this._height = t.height ?? 100;
1877
- }
1878
- get width() {
1879
- return this._width;
1880
- }
1881
- set width(t) {
1882
- this._width !== t && (this._width = t, this.markDirty());
1883
- }
1884
- get height() {
1885
- return this._height;
1886
- }
1887
- set height(t) {
1888
- this._height !== t && (this._height = t, this.markDirty());
1889
- }
1890
- getVertexCount() {
1891
- return 6;
1892
- }
1893
- getPositions() {
1894
- const i = this.width, r = this.height;
1895
- return [
1896
- 0,
1897
- 0,
1898
- // top-left
1899
- 0,
1900
- r,
1901
- // bottom-left
1902
- i,
1903
- 0,
1904
- // top-right
1905
- i,
1906
- 0,
1907
- // top-right
1908
- 0,
1909
- r,
1910
- // bottom-left
1911
- i,
1912
- r
1913
- // bottom-right
1914
- ];
1915
- }
1916
- /**
1917
- *
1918
- * @returns A bounding box that is not adjusted for world space.
1919
- */
1920
- getBoundingBox() {
1921
- const t = this.state.translation[0], e = t + this.width * this.state.scaleX, i = this.state.translation[1], r = i + this.height * this.state.scaleY, n = Math.min(t, e), a = Math.max(t, e), o = Math.min(i, r), h = Math.max(i, r);
1922
- return this.AABB = new et(n, o, a, h), this.AABB;
1923
- }
1924
- getEdge() {
1925
- const t = this.x, e = this.y;
1926
- return {
1927
- minX: Math.min(t, t + this.width),
1928
- maxX: Math.max(t, t + this.width),
1929
- minY: Math.min(e, e + this.height),
1930
- maxY: Math.max(e, e + this.height)
1931
- };
1932
- }
1933
- hitTest(t, e) {
1934
- const [i, r] = tt(this.worldMatrix), [n, a] = Tt(this.worldMatrix), [o, h] = U(this.parent.worldMatrix, t, e), [c, l] = U(this.worldMatrix), u = this.width * i * n, g = this.height * r * a, m = Math.min(c, c + u), w = Math.max(c, c + u), x = Math.min(l, l + g), C = Math.max(l, l + g);
1935
- return o >= m && o <= w && h >= x && h <= C;
1936
- }
1937
- }
1938
- class wt extends Z {
1939
- constructor(t) {
1940
- super(t), this.texCoordArray = new Float32Array([
1941
- 0,
1942
- 0,
1943
- // top-left
1944
- 0,
1945
- 1,
1946
- // bottom-left
1947
- 1,
1948
- 0,
1949
- // top-right
1950
- 1,
1951
- 0,
1952
- // top-right
1953
- 0,
1954
- 1,
1955
- // bottom-left
1956
- 1,
1957
- 1
1958
- // bottom-right
1959
- ]), this.useLowRes = !1, this.lowResNeedsRefresh = !0, this._src = t.src, this.loadImage(t.src, t.width, t.height);
1960
- }
1961
- get src() {
1962
- return this._src;
1963
- }
1964
- set src(t) {
1965
- this._src !== t && (this._src = t, this.updateImageTexture(t), this.markDirty());
1966
- }
1967
- get fileId() {
1968
- return this._fileId;
1969
- }
1970
- set fileId(t) {
1971
- this._fileId = t;
1972
- }
1973
- determineIfLowRes(t, e, i = 0.1) {
1974
- const r = t.getArea();
1975
- return this.getBoundingBox().getArea() / r < i / e;
1976
- }
1977
- async setUseLowRes(t, e) {
1978
- this.useLowRes === t && !this.lowResNeedsRefresh || (this.useLowRes = t, (t && e || this.lowResNeedsRefresh) && await this.ensureLowResUploaded(e), this.markDirty(), this.lowResNeedsRefresh = !1);
1979
- }
1980
- loadImage(t, e, i) {
1981
- this.culled || this.updateImageTexture(t, e, i);
1982
- }
1983
- updateImageTexture(t, e, i) {
1984
- this._image = new Image(), this._image.crossOrigin = "anonymous", this._image.onload = async () => {
1985
- this.width = e ?? this._image.naturalWidth, this.height = i ?? this._image.naturalHeight;
1986
- try {
1987
- if (this.bitmap) {
1988
- try {
1989
- this.bitmap.close();
1990
- } catch {
1991
- }
1992
- this.bitmap = void 0;
1993
- }
1994
- typeof createImageBitmap == "function" && (this.bitmap = await createImageBitmap(this._image));
1995
- } catch (r) {
1996
- console.warn(
1997
- "createImageBitmap failed, falling back to HTMLImageElement",
1998
- r
1999
- ), this.bitmap = void 0;
2000
- }
2001
- if (this.gl && this.program)
2002
- try {
2003
- this.texture && this.gl && (this.gl.deleteTexture(this.texture), this.texture = void 0), this.initialiseTexture(), this.initialized = !0, this.markDirty();
2004
- } catch (r) {
2005
- console.error("Failed to initialise texture on image load", r);
2006
- }
2007
- this.lowResNeedsRefresh = !0;
2008
- }, this._image.onerror = (r) => {
2009
- console.error("Failed to load image:", t, r);
2010
- }, this._image.src = t;
2011
- }
2012
- async ensureLowResUploaded(t) {
2013
- if (!(this.lowResTexture && !this.lowResNeedsRefresh) && !(!this._image || !this._image.complete))
2014
- try {
2015
- const i = this._image.naturalWidth, r = this._image.naturalHeight, n = Math.min(
2016
- 1,
2017
- 256 / Math.max(1, Math.max(i, r))
2018
- ), a = Math.max(1, Math.round(i * n)), o = Math.max(1, Math.round(r * n));
2019
- let h;
2020
- typeof OffscreenCanvas < "u" ? h = new OffscreenCanvas(a, o) : (h = document.createElement("canvas"), h.width = a, h.height = o);
2021
- const c = h.getContext("2d");
2022
- c.clearRect(0, 0, a, o);
2023
- const l = Math.min(a / i, o / r), u = Math.round(i * l), g = Math.round(r * l), m = Math.round((a - u) / 2), w = Math.round((o - g) / 2);
2024
- c.drawImage(this._image, 0, 0, i, r, m, w, u, g), this.lowResBitmap = await createImageBitmap(h), this.setLowResTextureFromBitmap(t, this.lowResBitmap);
2025
- } catch (e) {
2026
- console.error("Failed to create/upload low-res image", e);
2027
- }
2028
- }
2029
- setLowResTextureFromBitmap(t, e) {
2030
- if (this.lowResTexture) {
2031
- try {
2032
- t.deleteTexture(this.lowResTexture);
2033
- } catch {
2034
- }
2035
- this.lowResTexture = void 0;
2036
- }
2037
- this.lowResTexture = t.createTexture(), t.bindTexture(t.TEXTURE_2D, this.lowResTexture), t.texParameteri(t.TEXTURE_2D, t.TEXTURE_WRAP_S, t.CLAMP_TO_EDGE), t.texParameteri(t.TEXTURE_2D, t.TEXTURE_WRAP_T, t.CLAMP_TO_EDGE), t.texParameteri(t.TEXTURE_2D, t.TEXTURE_MIN_FILTER, t.LINEAR), t.texParameteri(t.TEXTURE_2D, t.TEXTURE_MAG_FILTER, t.LINEAR), t.texImage2D(t.TEXTURE_2D, 0, t.RGBA, t.RGBA, t.UNSIGNED_BYTE, e), t.bindTexture(t.TEXTURE_2D, null), this.markDirty();
2038
- }
2039
- // data upload
2040
- initialiseTexture() {
2041
- !this.gl || !this.program || !this._image || !this._image.complete || this._image.naturalWidth === 0 || (this.setUpVertexData(this.gl, this.program), this.setUpTexData(this.gl, this.program), this.setTexture(this.gl), super.setUpUniforms(this.gl, this.program), this.samplerLocation = this.gl.getUniformLocation(this.program, "u_image"), this.samplerLocation && this.gl.uniform1i(this.samplerLocation, 0));
2042
- }
2043
- setUpTexData(t, e) {
2044
- this.texcoordBuffer || (this.texcoordBuffer = t.createBuffer()), this.texcoordLocation = t.getAttribLocation(e, "a_texCoord");
2045
- }
2046
- setTexture(t) {
2047
- if (this.texture) {
2048
- try {
2049
- try {
2050
- t.deleteTexture(this.texture);
2051
- } catch {
2052
- }
2053
- } catch {
2054
- }
2055
- this.texture = void 0;
2056
- }
2057
- this.texture = t.createTexture(), t.bindTexture(t.TEXTURE_2D, this.texture), t.texParameteri(t.TEXTURE_2D, t.TEXTURE_WRAP_S, t.CLAMP_TO_EDGE), t.texParameteri(t.TEXTURE_2D, t.TEXTURE_WRAP_T, t.CLAMP_TO_EDGE), t.texParameteri(t.TEXTURE_2D, t.TEXTURE_MIN_FILTER, t.NEAREST), t.texParameteri(t.TEXTURE_2D, t.TEXTURE_MAG_FILTER, t.NEAREST), t.texParameteri(t.TEXTURE_2D, t.TEXTURE_MIN_FILTER, t.LINEAR), t.texParameteri(t.TEXTURE_2D, t.TEXTURE_MAG_FILTER, t.LINEAR);
2058
- const e = this.bitmap ?? this._image;
2059
- e && t.texImage2D(
2060
- t.TEXTURE_2D,
2061
- 0,
2062
- t.RGBA,
2063
- t.RGBA,
2064
- t.UNSIGNED_BYTE,
2065
- e
2066
- ), t.bindTexture(t.TEXTURE_2D, null);
2067
- }
2068
- updateVertexData(t) {
2069
- super.updateVertexData(t), t.bindBuffer(t.ARRAY_BUFFER, this.texcoordBuffer), t.bufferData(t.ARRAY_BUFFER, this.texCoordArray, t.STATIC_DRAW);
2070
- }
2071
- getVertexCount() {
2072
- return 6;
2073
- }
2074
- render(t, e) {
2075
- if (this.dirty && !this.culled) {
2076
- if (this.updateWorldMatrix(this.parent ? this.parent.worldMatrix : void 0), !this.initialized)
2077
- if (this.gl = t, this.program = e, this.initialiseTexture(), this._image.complete && this._image.naturalWidth > 0)
2078
- this.initialized = !0;
2079
- else
2080
- return;
2081
- this.updateVertexData(t), this.clearDirty();
2082
- }
2083
- super.updateUniforms(t), this.culled || this.draw(t);
2084
- }
2085
- draw(t) {
2086
- t.bindBuffer(t.ARRAY_BUFFER, this.positionBuffer);
2087
- const e = 2, i = t.FLOAT, r = !1, n = 0, a = 0;
2088
- t.vertexAttribPointer(
2089
- this.attributeLocation,
2090
- e,
2091
- i,
2092
- r,
2093
- n,
2094
- a
2095
- ), t.enableVertexAttribArray(this.attributeLocation), t.bindBuffer(t.ARRAY_BUFFER, this.texcoordBuffer), t.vertexAttribPointer(
2096
- this.texcoordLocation,
2097
- e,
2098
- i,
2099
- r,
2100
- n,
2101
- a
2102
- ), t.enableVertexAttribArray(this.texcoordLocation), t.activeTexture(t.TEXTURE0);
2103
- try {
2104
- const o = this.useLowRes && this.lowResTexture ? this.lowResTexture : this.texture;
2105
- t.bindTexture(t.TEXTURE_2D, o), t.drawArrays(t.TRIANGLES, 0, this.getVertexCount()), t.bindBuffer(t.ARRAY_BUFFER, null), t.disableVertexAttribArray(this.attributeLocation), t.disableVertexAttribArray(this.texcoordLocation);
2106
- } catch (o) {
2107
- console.error(o);
2108
- }
2109
- }
2110
- destroy() {
2111
- if (this.texcoordBuffer) {
2112
- try {
2113
- this.gl.deleteBuffer(this.texcoordBuffer);
2114
- } catch {
2115
- }
2116
- this.texcoordBuffer = void 0;
2117
- }
2118
- if (this.texture) {
2119
- try {
2120
- this.gl.deleteTexture(this.texture);
2121
- } catch {
2122
- }
2123
- this.texture = void 0;
2124
- }
2125
- if (this.lowResTexture) {
2126
- try {
2127
- this.gl.deleteTexture(this.lowResTexture);
2128
- } catch {
2129
- }
2130
- this.lowResTexture = void 0;
2131
- }
2132
- if (this.bitmap) {
2133
- try {
2134
- this.bitmap.close();
2135
- } catch {
2136
- }
2137
- this.bitmap = void 0;
2138
- }
2139
- if (this.lowResBitmap) {
2140
- try {
2141
- this.lowResBitmap.close();
2142
- } catch {
2143
- }
2144
- this.lowResBitmap = void 0;
2145
- }
2146
- this.texcoordLocation = void 0, this.samplerLocation = void 0;
2147
- try {
2148
- super.destroy();
2149
- } catch {
2150
- }
2151
- }
2152
- }
2153
- var _t = /* @__PURE__ */ ((s) => (s[s.NONE = 0] = "NONE", s[s.GRID = 1] = "GRID", s))(_t || {});
2154
- class Le extends Ae {
2155
- constructor() {
2156
- super(...arguments), this.buffer = null, this.vertexCount = 0, this.gridType = 1, this.zoom = 1;
2157
- }
2158
- // Fullscreen big-triangle in clip space: covers [-1,1] without seams
2159
- getPositions() {
2160
- return new Float32Array([-1, -1, 3, -1, -1, 3]);
2161
- }
2162
- changeGridType(t) {
2163
- this.gridType = t;
2164
- }
2165
- render(t, e) {
2166
- if (this.buffer)
2167
- t.bindBuffer(t.ARRAY_BUFFER, this.buffer);
2168
- else {
2169
- if (this.buffer = t.createBuffer(), !this.buffer) throw new Error("Failed to create grid buffer");
2170
- const c = this.getPositions();
2171
- this.vertexCount = c.length / 2, t.bindBuffer(t.ARRAY_BUFFER, this.buffer), t.bufferData(t.ARRAY_BUFFER, c, t.STATIC_DRAW);
2172
- }
2173
- this.initialized || (this.setUpVertexData(t, e), this.setUpUniforms(t, e), this.initialized = !0);
2174
- const i = t.drawingBufferWidth, r = t.drawingBufferHeight, n = E.inverse(E.projection(i, r)), a = E.inverse(this.worldMatrix), o = E.multiply(a, n);
2175
- this.viewProjectionInvLocation && t.uniformMatrix3fv(
2176
- this.viewProjectionInvLocation,
2177
- !1,
2178
- new Float32Array(o)
2179
- ), this.zoomScaleLocation && t.uniform1f(this.zoomScaleLocation, this.zoom), this.checkboardStyleLocation && t.uniform1f(this.checkboardStyleLocation, this.gridType);
2180
- const h = t.getAttribLocation(e, "a_Position");
2181
- if (h === -1)
2182
- throw new Error("Attribute a_Position not found in grid program");
2183
- t.vertexAttribPointer(h, 2, t.FLOAT, !1, 0, 0), t.enableVertexAttribArray(h), t.drawArrays(t.TRIANGLES, 0, this.vertexCount), t.bindBuffer(t.ARRAY_BUFFER, null), t.disableVertexAttribArray(h);
2184
- }
2185
- destroy() {
2186
- this.buffer && (this.buffer = null);
2187
- }
2188
- hitTest(t, e) {
2189
- return !1;
2190
- }
2191
- setUpUniforms(t, e) {
2192
- const i = new Float32Array([1, 0, 0, 0, 1, 0, 0, 0, 1]);
2193
- this.viewProjectionInvLocation = t.getUniformLocation(
2194
- e,
2195
- "u_ViewProjectionInvMatrix"
2196
- ), this.zoomScaleLocation = t.getUniformLocation(e, "u_ZoomScale"), this.checkboardStyleLocation = t.getUniformLocation(
2197
- e,
2198
- "u_CheckboardStyle"
2199
- ), t.uniformMatrix3fv(this.viewProjectionInvLocation, !1, i), t.uniform1f(this.zoomScaleLocation, this.zoom), t.uniform1f(this.checkboardStyleLocation, 1);
2200
- }
2201
- }
2202
- const Ui = 0.02, Wi = 20;
2203
- class Fi {
2204
- constructor(t, e, i, r) {
2205
- this.viewportX = 0, this.viewportY = 0, this.state = t, this.updateCameraPos = this.updateCameraPos.bind(this), this.updateZoom = this.updateZoom.bind(this), this.onWheel = this.onWheel.bind(this), this.worldToCamera = this.worldToCamera.bind(this), this.getWorldCoords = r, this.setWorldMatrix = e, this.updateWorldMatrix = i, this.updateReaction = Je(
2206
- () => this.state.stateVector,
2207
- () => this.updateViewMatrix()
2208
- ), this.updateViewMatrix();
2209
- }
2210
- /**
2211
- * Called once to update the `worldMatrix` of the attached canvas, which is the view matrix.
2212
- */
2213
- updateViewMatrix() {
2214
- this.setWorldMatrix(this.state.canvasMatrix), this.updateWorldMatrix();
2215
- }
2216
- setViewPortDimension(t, e) {
2217
- this.state.width !== t && this.state.setWidth(t), this.state.height !== e && this.state.setHeight(e);
2218
- }
2219
- getBoundingBox() {
2220
- const [t, e] = this.getWorldCoords(this.viewportX, this.viewportY), [i, r] = this.getWorldCoords(
2221
- this.state.width + this.viewportX,
2222
- this.state.height + this.viewportY
2223
- );
2224
- return new et(t, e, i, r);
2225
- }
2226
- onWheel(t) {
2227
- t.preventDefault();
2228
- const i = Math.exp(-t.deltaY * 3e-3);
2229
- this.updateZoom(t.clientX, t.clientY, i);
2230
- }
2231
- updateCameraPos(t, e) {
2232
- this.state.incrementPosition(t, e);
2233
- }
2234
- /**
2235
- * Pass in the center position to resolve the scaling around
2236
- */
2237
- updateZoom(t, e, i) {
2238
- const [r, n] = this.getWorldCoords(t, e);
2239
- this.state.setZoom(
2240
- Math.min(Wi, Math.max(Ui, this.state.zoom * i))
2241
- );
2242
- const [a, o] = this.getWorldCoords(t, e);
2243
- this.state.incrementPosition(r - a, n - o);
2244
- }
2245
- worldToCamera(t, e) {
2246
- const i = this.state.cameraMatrix, r = i[0] * t + i[1] * e + i[2], n = i[3] * t + i[4] * e + i[5];
2247
- return [r, n];
2248
- }
2249
- dispose() {
2250
- this.updateReaction && (this.updateReaction(), this.updateReaction = void 0);
2251
- }
2252
- }
2253
- const ge = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBmaWxsPSIjYjNiM2IzIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xLjUgNmEyLjI1IDIuMjUgMCAwIDEgMi4yNS0yLjI1aDE2LjVBMi4yNSAyLjI1IDAgMCAxIDIyLjUgNnYxMmEyLjI1IDIuMjUgMCAwIDEtMi4yNSAyLjI1SDMuNzVBMi4yNSAyLjI1IDAgMCAxIDEuNSAxOHpNMyAxNi4wNlYxOGMwIC40MTQuMzM2Ljc1Ljc1Ljc1aDE2LjVBLjc1Ljc1IDAgMCAwIDIxIDE4di0xLjk0bC0yLjY5LTIuNjg5YTEuNSAxLjUgMCAwIDAtMi4xMiAwbC0uODguODc5bC45Ny45N2EuNzUuNzUgMCAxIDEtMS4wNiAxLjA2bC01LjE2LTUuMTU5YTEuNSAxLjUgMCAwIDAtMi4xMiAwem0xMC4xMjUtNy44MWExLjEyNSAxLjEyNSAwIDEgMSAyLjI1IDBhMS4xMjUgMS4xMjUgMCAwIDEtMi4yNSAwIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiLz48L3N2Zz4=", rt = 240;
2254
- function pe(s) {
2255
- return {
2256
- x: s.x ?? 0,
2257
- y: s.y ?? 0,
2258
- sx: s.sx ?? 1,
2259
- sy: s.sy ?? 1
2260
- };
2261
- }
2262
- function Yt(s) {
2263
- return s.children.map(Oe);
2264
- }
2265
- function Oe(s) {
2266
- return s instanceof wt ? {
2267
- type: "Img",
2268
- id: s.seq,
2269
- renderOrder: s.renderOrder,
2270
- transform: pe(s),
2271
- width: s.width,
2272
- height: s.height,
2273
- fileId: s.fileId,
2274
- children: s.children?.length ? Yt(s) : void 0
2275
- } : s instanceof Z ? {
2276
- type: "Rect",
2277
- id: s.seq,
2278
- renderOrder: s.renderOrder,
2279
- transform: pe(s),
2280
- width: s.width,
2281
- height: s.height,
2282
- color: s.color,
2283
- children: s.children?.length ? Yt(s) : void 0
2284
- } : s instanceof Le ? {
2285
- type: "Grid",
2286
- style: s.gridType
2287
- } : {
2288
- type: "Renderable",
2289
- children: s.children?.length ? Yt(s) : void 0
2290
- };
2291
- }
2292
- function Vt(s, t) {
2293
- const { gl: e } = s;
2294
- return {
2295
- version: 1,
2296
- canvas: {
2297
- width: e.canvas.width,
2298
- height: e.canvas.height,
2299
- dpr: window.devicePixelRatio || 1
2300
- },
2301
- camera: {
2302
- x: s.camera.state.x,
2303
- y: s.camera.state.y,
2304
- zoom: s.camera.state.zoom
2305
- },
2306
- root: Oe(s),
2307
- files: t
2308
- };
2309
- }
2310
- async function Zt(s, t, e, i) {
2311
- t.children.length = 0, s.camera && (t.camera.state.setZoom(s.camera.zoom), t.camera.state.setX(s.camera.x), t.camera.state.setY(s.camera.y));
2312
- async function r(n, a) {
2313
- let o;
2314
- switch (n.type) {
2315
- case "Rect":
2316
- o = new Z({
2317
- x: n.transform.x,
2318
- y: n.transform.y,
2319
- width: n.width,
2320
- height: n.height
2321
- }), o.setScale(n.transform.sx, n.transform.sy), t.appendChild(o);
2322
- break;
2323
- case "Img":
2324
- let h;
2325
- try {
2326
- h = s.files && Array.isArray(s.files) ? s.files.find(
2327
- (m) => m.id === n.fileId
2328
- )?.dataURL ?? ge : ge, i && i(h);
2329
- const c = n.width, l = n.height, u = await Xi(
2330
- h,
2331
- c * n.transform.sx,
2332
- l * n.transform.sy
2333
- );
2334
- o = new wt({
2335
- x: n.transform.x,
2336
- y: n.transform.y,
2337
- src: u,
2338
- width: c,
2339
- height: l
2340
- }), e(n.fileId).then((g) => {
2341
- o.src = g.dataURL;
2342
- }).catch((g) => console.error("Image not loaded", g)), o.fileId = n.fileId ?? await Qt(h), o.setScale(n.transform.sx, n.transform.sy), t.appendChild(o), typeof n.renderOrder == "number" && (o.renderOrder = n.renderOrder);
2343
- } catch {
2344
- console.error(`Failed to match image to restore with source: ${h}`);
2345
- } finally {
2346
- break;
2347
- }
2348
- case "Grid":
2349
- a instanceof kt && (a.grid.gridType = n.style);
2350
- break;
2351
- }
2352
- if (n.children)
2353
- for (const h of n.children) await r(h, o);
2354
- }
2355
- return await r(s.root, t), t;
2356
- }
2357
- async function Gi(s) {
2358
- const t = new Image();
2359
- return t.crossOrigin = "anonymous", new Promise((e, i) => {
2360
- t.onload = () => e(t), t.onerror = (r) => i(r), t.src = s;
2361
- });
2362
- }
2363
- async function Xi(s, t, e, i = "#d6d6d6ff") {
2364
- let r = null, n;
2365
- s instanceof Blob ? (r = URL.createObjectURL(s), n = r) : n = s;
2366
- try {
2367
- let a = null;
2368
- try {
2369
- a = await Gi(n);
2370
- } catch {
2371
- }
2372
- const o = t && t > 0 ? t : a?.naturalWidth ?? rt, h = e && e > 0 ? e : a?.naturalHeight ?? rt, c = document.createElement("canvas");
2373
- c.width = o, c.height = h;
2374
- const l = c.getContext("2d");
2375
- if (l.fillStyle = i, l.fillRect(0, 0, o, h), a) {
2376
- const u = Math.min(
2377
- o / a.naturalWidth,
2378
- h / a.naturalHeight
2379
- ), g = a.naturalHeight * u, m = a.naturalWidth * u;
2380
- let w = rt, x = rt;
2381
- (rt > g || rt > m) && (w = m, x = g);
2382
- const C = Math.round((o - w) / 2), v = Math.round((h - x) / 2);
2383
- l.drawImage(
2384
- a,
2385
- 0,
2386
- 0,
2387
- a.naturalWidth,
2388
- a.naturalHeight,
2389
- C,
2390
- v,
2391
- w,
2392
- x
2393
- );
2394
- }
2395
- return c.toDataURL("image/png");
2396
- } finally {
2397
- r && URL.revokeObjectURL(r);
2398
- }
2399
- }
2400
- var W, F, Q, ht, y, G, ct, J, X, V, P, dt, Ft, lt;
2401
- const R = class R extends Pe {
2402
- constructor(e, i, r, n, a, o) {
2403
- super();
2404
- O(this, W);
2405
- O(this, F);
2406
- O(this, Q);
2407
- O(this, ht);
2408
- O(this, y);
2409
- O(this, G);
2410
- O(this, ct);
2411
- O(this, J);
2412
- O(this, X);
2413
- O(this, V);
2414
- O(this, P);
2415
- O(this, dt);
2416
- O(this, Ft);
2417
- O(this, lt);
2418
- I(this, V, !0), this.orderDirty = !0, this.renderList = [], I(this, W, e), I(this, F, r), I(this, Q, i), I(this, X, new Le()), I(this, y, e.getContext("webgl", {
2419
- alpha: !0,
2420
- premultipliedAlpha: !1
2421
- })), f(this, y).enable(f(this, y).BLEND), f(this, y).blendFunc(f(this, y).SRC_ALPHA, f(this, y).ONE_MINUS_SRC_ALPHA), f(this, y).getExtension("OES_standard_derivatives"), f(this, y).enable(f(this, y).DEPTH_TEST), f(this, y).depthFunc(f(this, y).LEQUAL), I(this, G, Ht(f(this, y), bi, Ci)), I(this, ct, Ht(f(this, y), Ei, Ti)), I(this, J, Ht(f(this, y), Si, Mi)), this.writeToStorage = n, this.saveImgFileToStorage = a, this.getContainerDimension = o, this.engine = this.engine.bind(this), this.getBoundingClientRect = this.getBoundingClientRect.bind(this), this.appendChild = this.appendChild.bind(this), this.addImageToCanvas = this.addImageToCanvas.bind(this), this.setShapeZOrder = this.setShapeZOrder.bind(this), this.toggleGrid = this.toggleGrid.bind(this), this.changeMode = this.changeMode.bind(this), this.getSelected = this.getSelected.bind(this), this.updateZoomByFixedAmount = this.updateZoomByFixedAmount.bind(this), this.assignEventListener = this.assignEventListener.bind(this), this.getWorldsCoordsFromCanvas = (g, m) => K(g, m, this);
2422
- const h = (g, m) => K(
2423
- g + this.camera.viewportX,
2424
- m + this.camera.viewportY,
2425
- this
2426
- );
2427
- this.exportState = this.exportState.bind(this), this.importState = this.importState.bind(this), this.clearChildren = this.clearChildren.bind(this), I(this, P, new Pi(
2428
- i,
2429
- r,
2430
- this.gl,
2431
- f(this, G),
2432
- () => this.worldMatrix,
2433
- () => this.children,
2434
- this.getWorldsCoordsFromCanvas,
2435
- h
2436
- ));
2437
- const c = new Ii({});
2438
- I(this, ht, new Fi(
2439
- c,
2440
- this.setWorldMatrix,
2441
- this.updateWorldMatrix,
2442
- this.getWorldsCoordsFromCanvas
2443
- )), I(this, Ft, new Oi(
2444
- i,
2445
- r,
2446
- () => this.selectionManager.deleteSelected(this),
2447
- this.assignEventListener
2448
- )), I(this, lt, new Di(
2449
- r,
2450
- this.selectionManager.isMultiBoundingBoxHit,
2451
- this.selectionManager.isBoundingBoxHit,
2452
- this.getWorldsCoordsFromCanvas,
2453
- this.assignEventListener
2454
- ));
2455
- const l = new zi(), u = {
2456
- history: i,
2457
- eventHub: r,
2458
- state: l,
2459
- isContextMenuActive: () => f(this, lt).isActive,
2460
- getSelected: () => f(this, P).selected,
2461
- getChildren: () => this.children,
2462
- getWorldMatrix: () => this.worldMatrix,
2463
- getCanvasGlobalClick: () => this.isGlobalClick,
2464
- setCanvasGlobalClick: (g) => this.isGlobalClick = g,
2465
- getWorldCoords: this.getWorldsCoordsFromCanvas,
2466
- updateCameraPos: this.camera.updateCameraPos,
2467
- onWheel: this.camera.onWheel,
2468
- setCursorStyle: (g) => e.style.cursor = g,
2469
- paste: (g, m) => Ie(g, m, this, i),
2470
- assignEventListener: this.assignEventListener,
2471
- closeMarquee: f(this, P).clearMarquee,
2472
- selectionPointerMove: (g, m, w, x, C) => f(this, P).onPointerMove(
2473
- g,
2474
- m,
2475
- w,
2476
- x,
2477
- C,
2478
- () => this.isGlobalClick,
2479
- this.camera.updateCameraPos,
2480
- () => this.worldMatrix
2481
- ),
2482
- onSelectionPointerDown: this.selectionManager.onSelectionPointerDown,
2483
- checkIfSelectionHit: this.selectionManager.hitTest,
2484
- addSelection: this.selectionManager.add,
2485
- clearSelection: this.selectionManager.clear,
2486
- isSelection: this.selectionManager.isRectSelected,
2487
- hitTestAdjustedCorner: this.selectionManager.hitTestAdjustedCorner
2488
- };
2489
- I(this, dt, new Li(u)), f(this, F).on("save", this.writeToStorage);
2490
- }
2491
- // Call this whenever children/layers/z-order change
2492
- markOrderDirty() {
2493
- this.orderDirty = !0;
2494
- }
2495
- get gl() {
2496
- return f(this, y);
2497
- }
2498
- get grid() {
2499
- return f(this, X);
2500
- }
2501
- get history() {
2502
- return f(this, Q);
2503
- }
2504
- get eventHub() {
2505
- return f(this, F);
2506
- }
2507
- get pointerEventManager() {
2508
- return f(this, dt);
2509
- }
2510
- get selectionManager() {
2511
- return f(this, P);
2512
- }
2513
- get contextMenuManager() {
2514
- return f(this, lt);
2515
- }
2516
- get canvas() {
2517
- return f(this, W);
2518
- }
2519
- get camera() {
2520
- return f(this, ht);
2521
- }
2522
- get isGlobalClick() {
2523
- return f(this, V);
2524
- }
2525
- set isGlobalClick(e) {
2526
- I(this, V, e);
2527
- }
2528
- get basicShapeProgram() {
2529
- return f(this, G);
2530
- }
2531
- engine() {
2532
- return this;
2533
- }
2534
- get totalNumberOfChildren() {
2535
- return this.children.length;
2536
- }
2537
- get numberOfChildrenRendered() {
2538
- return this.renderList.length;
2539
- }
2540
- appendChild(e) {
2541
- if (super.appendChild(e), e instanceof ut) {
2542
- const i = this.children.map((n) => n.renderOrder), r = i.length ? Math.max(...i) : 0;
2543
- e.renderOrder = r + 1;
2544
- }
2545
- return this.markOrderDirty(), e;
2546
- }
2547
- removeChild(e) {
2548
- this.state.removeChild(e), f(this, P) && f(this, P).remove([e]), e.destroy(), this.markOrderDirty();
2549
- }
2550
- getChild(e) {
2551
- return this.state.getChild(e);
2552
- }
2553
- updateWorldMatrix() {
2554
- f(this, X).updateWorldMatrix(this.worldMatrix), this.children.forEach((e) => {
2555
- e.updateWorldMatrix(this.worldMatrix);
2556
- }), f(this, P).update();
2557
- }
2558
- render() {
2559
- f(this, y).clearColor(0, 0, 0, 0), f(this, y).clear(f(this, y).COLOR_BUFFER_BIT | f(this, y).DEPTH_BUFFER_BIT), f(this, y).viewport(0, 0, f(this, y).canvas.width, f(this, y).canvas.height);
2560
- const e = this.canvas.parentElement.getBoundingClientRect();
2561
- this.camera.setViewPortDimension(
2562
- e.width,
2563
- e.height
2564
- ), f(this, y).useProgram(f(this, J));
2565
- const i = f(this, y).getUniformLocation(f(this, J), "u_z");
2566
- f(this, y).uniform1f(i, 0), f(this, X).render(f(this, y), f(this, J));
2567
- const r = this.camera.getBoundingBox();
2568
- this.renderList = [];
2569
- for (const l of this.children)
2570
- et.isColliding(r, l.getBoundingBox()) ? (this.renderList.push(l), l.culled = !1) : l.culled = !0;
2571
- const [n, a] = K(0, 0, this), [o, h] = K(
2572
- window.screen.width,
2573
- window.screen.height,
2574
- this
2575
- ), c = new et(n, a, o, h);
2576
- this.renderList.forEach((l) => {
2577
- if (l instanceof wt) {
2578
- const u = l.determineIfLowRes(
2579
- c,
2580
- this.camera.state.zoom
2581
- );
2582
- l.setUseLowRes(u, this.gl);
2583
- }
2584
- });
2585
- for (const l of this.renderList) {
2586
- let u;
2587
- l instanceof wt ? u = f(this, ct) : l instanceof ut && (u = f(this, G)), f(this, y).useProgram(u);
2588
- const g = f(this, y).getUniformLocation(u, "u_z");
2589
- f(this, y).uniform1f(g, l.getZ()), l.render(f(this, y), u);
2590
- }
2591
- f(this, P).render(f(this, G));
2592
- }
2593
- destroy() {
2594
- f(this, y).deleteProgram(f(this, G)), f(this, y).deleteProgram(f(this, ct)), this.children.forEach((e) => {
2595
- "destroy" in e && e.destroy();
2596
- }), this.clearChildren();
2597
- }
2598
- getDOM() {
2599
- return f(this, W);
2600
- }
2601
- assignEventListener(e, i, r) {
2602
- f(this, W).addEventListener(e, i, r);
2603
- }
2604
- hitTest(e, i) {
2605
- return I(this, V, !0), f(this, V);
2606
- }
2607
- async addImageToCanvas(e, i, r, n = 1, a = 1, o = !1) {
2608
- const h = new wt({ x: i, y: r, src: e, sx: n, sy: a });
2609
- if (this.saveImgFileToStorage(e).then((c) => h.fileId = c), o) {
2610
- const c = new Image();
2611
- c.src = e.startsWith("data:image/png") ? e : await _e(e), c.onload = () => {
2612
- const l = c.naturalWidth || c.width || 0, u = c.naturalHeight || c.height || 0;
2613
- (l || u) && h.updateTranslation(-l / 2, -u / 2), h.src = c.src, this.appendChild(h);
2614
- };
2615
- }
2616
- return f(this, F).emit("save"), f(this, F).emit(N.Change), h;
2617
- }
2618
- exportState() {
2619
- return Vt(this);
2620
- }
2621
- async importState(e, i) {
2622
- return await Zt(e, this, i);
2623
- }
2624
- clearChildren() {
2625
- this.selectionManager.clear(), this.state.clearChildren(), f(this, Q).clear();
2626
- }
2627
- toggleGrid() {
2628
- f(this, X).changeGridType(
2629
- f(this, X).gridType === _t.GRID ? _t.NONE : _t.GRID
2630
- );
2631
- }
2632
- getSelected() {
2633
- return f(this, P).selected;
2634
- }
2635
- setShapeZOrder(e = !0) {
2636
- if (f(this, P).multiBoundingBox || f(this, P).boundingBoxes.size != 1)
2637
- return;
2638
- const i = Array.from(f(this, P).boundingBoxes)[0].target, r = {
2639
- ref: i,
2640
- start: {
2641
- renderOrder: i.renderOrder
2642
- }
2643
- }, n = this.children.map((h) => h.renderOrder);
2644
- if (n.length === 0)
2645
- throw new Error("Order unexpected missing.");
2646
- const a = Math.max(...n), o = Math.min(...n);
2647
- i.renderOrder = e ? a + 1 : o - 1, r.end = {
2648
- renderOrder: i.renderOrder
2649
- }, this.markOrderDirty(), f(this, Q).push(Bi([r])), f(this, F).emit(N.Change);
2650
- }
2651
- changeMode() {
2652
- f(this, dt).changeMode(), f(this, P).clear();
2653
- }
2654
- updateZoomByFixedAmount(e = 1) {
2655
- f(this, ht).updateZoom(
2656
- f(this, W).width / 2,
2657
- f(this, W).height / 2,
2658
- Math.exp(0.5 * 0.3 * e)
2659
- );
2660
- }
2661
- getBoundingClientRect() {
2662
- return f(this, W).getBoundingClientRect();
2663
- }
2664
- wrapWebGLContext(e) {
2665
- const i = e.createTexture.bind(e);
2666
- e.createTexture = () => (R.webglStats.texturesCreated++, console.log(`Textures created: ${R.webglStats.texturesCreated}`), i());
2667
- const r = e.deleteTexture.bind(e);
2668
- e.deleteTexture = (o) => (o && (R.webglStats.texturesDeleted++, console.log(`Textures deleted: ${R.webglStats.texturesDeleted}`)), r(o));
2669
- const n = e.createShader.bind(e);
2670
- e.createShader = (o) => (R.webglStats.shadersCreated++, console.log(`Shaders created: ${R.webglStats.shadersCreated}`), n(o));
2671
- const a = e.deleteShader.bind(e);
2672
- return e.deleteShader = (o) => (o && (R.webglStats.shadersDeleted++, console.log(`Shaders deleted: ${R.webglStats.shadersDeleted}`)), a(o)), e;
2673
- }
2674
- static getWebGLStats() {
2675
- return {
2676
- ...R.webglStats,
2677
- buffersLeaked: R.webglStats.buffersCreated - R.webglStats.buffersDeleted,
2678
- programsLeaked: R.webglStats.programsCreated - R.webglStats.programsDeleted,
2679
- texturesLeaked: R.webglStats.texturesCreated - R.webglStats.texturesDeleted,
2680
- shadersLeaked: R.webglStats.shadersCreated - R.webglStats.shadersDeleted
2681
- };
2682
- }
2683
- };
2684
- W = new WeakMap(), F = new WeakMap(), Q = new WeakMap(), ht = new WeakMap(), y = new WeakMap(), G = new WeakMap(), ct = new WeakMap(), J = new WeakMap(), X = new WeakMap(), V = new WeakMap(), P = new WeakMap(), dt = new WeakMap(), Ft = new WeakMap(), lt = new WeakMap(), R.webglStats = {
2685
- buffersCreated: 0,
2686
- buffersDeleted: 0,
2687
- programsCreated: 0,
2688
- programsDeleted: 0,
2689
- texturesCreated: 0,
2690
- texturesDeleted: 0,
2691
- shadersCreated: 0,
2692
- shadersDeleted: 0
2693
- };
2694
- let kt = R;
2695
- const xe = 25;
2696
- class Hi {
2697
- constructor() {
2698
- this._undoStack = [], this._redoStack = [], this._openGroup = null;
2699
- }
2700
- get undoStack() {
2701
- return this._undoStack;
2702
- }
2703
- begin(t) {
2704
- if (this._openGroup) throw new Error("History group already open");
2705
- this._openGroup = [], this._openLabel = t;
2706
- }
2707
- push(t) {
2708
- if (this._openGroup)
2709
- this._openGroup.push(t);
2710
- else {
2711
- for (; this._undoStack.length >= xe; )
2712
- this._undoStack.shift();
2713
- this._undoStack.push([t]), t.do(), this._redoStack.length = 0;
2714
- }
2715
- }
2716
- commit() {
2717
- if (!this._openGroup) return;
2718
- const t = this._openGroup;
2719
- this._openGroup = null;
2720
- for (const e of t) e.do();
2721
- for (; this._undoStack.length >= xe; )
2722
- this._undoStack.shift();
2723
- this._undoStack.push(t), this._redoStack.length = 0, this._openLabel = void 0;
2724
- }
2725
- cancel() {
2726
- this._openGroup = null, this._openLabel = void 0;
2727
- }
2728
- canUndo() {
2729
- return this._undoStack.length > 0;
2730
- }
2731
- canRedo() {
2732
- return this._redoStack.length > 0;
2733
- }
2734
- undo() {
2735
- const t = this._undoStack.pop();
2736
- if (t) {
2737
- for (let e = t.length - 1; e >= 0; e--) t[e].undo();
2738
- this._redoStack.push(t);
2739
- }
2740
- }
2741
- redo() {
2742
- const t = this._redoStack.pop();
2743
- if (t) {
2744
- for (const e of t) e.do();
2745
- this._undoStack.push(t);
2746
- }
2747
- }
2748
- clear() {
2749
- this._undoStack.length = 0, this._redoStack.length = 0, this._openGroup = null, this._openLabel = void 0;
2750
- }
2751
- }
2752
- const Ni = (s) => (t, e) => {
2753
- e !== void 0 ? e.addInitializer((() => {
2754
- customElements.define(s, t);
2755
- })) : customElements.define(s, t);
2756
- };
2757
- const Rt = globalThis, Jt = Rt.ShadowRoot && (Rt.ShadyCSS === void 0 || Rt.ShadyCSS.nativeShadow) && "adoptedStyleSheets" in Document.prototype && "replace" in CSSStyleSheet.prototype, De = Symbol(), ye = /* @__PURE__ */ new WeakMap();
2758
- let Yi = class {
2759
- constructor(t, e, i) {
2760
- if (this._$cssResult$ = !0, i !== De) throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");
2761
- this.cssText = t, this.t = e;
2762
- }
2763
- get styleSheet() {
2764
- let t = this.o;
2765
- const e = this.t;
2766
- if (Jt && t === void 0) {
2767
- const i = e !== void 0 && e.length === 1;
2768
- i && (t = ye.get(e)), t === void 0 && ((this.o = t = new CSSStyleSheet()).replaceSync(this.cssText), i && ye.set(e, t));
2769
- }
2770
- return t;
2771
- }
2772
- toString() {
2773
- return this.cssText;
2774
- }
2775
- };
2776
- const $i = (s) => new Yi(typeof s == "string" ? s : s + "", void 0, De), ji = (s, t) => {
2777
- if (Jt) s.adoptedStyleSheets = t.map(((e) => e instanceof CSSStyleSheet ? e : e.styleSheet));
2778
- else for (const e of t) {
2779
- const i = document.createElement("style"), r = Rt.litNonce;
2780
- r !== void 0 && i.setAttribute("nonce", r), i.textContent = e.cssText, s.appendChild(i);
2781
- }
2782
- }, we = Jt ? (s) => s : (s) => s instanceof CSSStyleSheet ? ((t) => {
2783
- let e = "";
2784
- for (const i of t.cssRules) e += i.cssText;
2785
- return $i(e);
2786
- })(s) : s;
2787
- const { is: Vi, defineProperty: Zi, getOwnPropertyDescriptor: qi, getOwnPropertyNames: Ki, getOwnPropertySymbols: Qi, getPrototypeOf: Ji } = Object, Gt = globalThis, ve = Gt.trustedTypes, ts = ve ? ve.emptyScript : "", es = Gt.reactiveElementPolyfillSupport, vt = (s, t) => s, qt = { toAttribute(s, t) {
2788
- switch (t) {
2789
- case Boolean:
2790
- s = s ? ts : null;
2791
- break;
2792
- case Object:
2793
- case Array:
2794
- s = s == null ? s : JSON.stringify(s);
2795
- }
2796
- return s;
2797
- }, fromAttribute(s, t) {
2798
- let e = s;
2799
- switch (t) {
2800
- case Boolean:
2801
- e = s !== null;
2802
- break;
2803
- case Number:
2804
- e = s === null ? null : Number(s);
2805
- break;
2806
- case Object:
2807
- case Array:
2808
- try {
2809
- e = JSON.parse(s);
2810
- } catch {
2811
- e = null;
2812
- }
2813
- }
2814
- return e;
2815
- } }, Be = (s, t) => !Vi(s, t), be = { attribute: !0, type: String, converter: qt, reflect: !1, useDefault: !1, hasChanged: Be };
2816
- Symbol.metadata ??= Symbol("metadata"), Gt.litPropertyMetadata ??= /* @__PURE__ */ new WeakMap();
2817
- class ft extends HTMLElement {
2818
- static addInitializer(t) {
2819
- this._$Ei(), (this.l ??= []).push(t);
2820
- }
2821
- static get observedAttributes() {
2822
- return this.finalize(), this._$Eh && [...this._$Eh.keys()];
2823
- }
2824
- static createProperty(t, e = be) {
2825
- if (e.state && (e.attribute = !1), this._$Ei(), this.prototype.hasOwnProperty(t) && ((e = Object.create(e)).wrapped = !0), this.elementProperties.set(t, e), !e.noAccessor) {
2826
- const i = Symbol(), r = this.getPropertyDescriptor(t, i, e);
2827
- r !== void 0 && Zi(this.prototype, t, r);
2828
- }
2829
- }
2830
- static getPropertyDescriptor(t, e, i) {
2831
- const { get: r, set: n } = qi(this.prototype, t) ?? { get() {
2832
- return this[e];
2833
- }, set(a) {
2834
- this[e] = a;
2835
- } };
2836
- return { get: r, set(a) {
2837
- const o = r?.call(this);
2838
- n?.call(this, a), this.requestUpdate(t, o, i);
2839
- }, configurable: !0, enumerable: !0 };
2840
- }
2841
- static getPropertyOptions(t) {
2842
- return this.elementProperties.get(t) ?? be;
2843
- }
2844
- static _$Ei() {
2845
- if (this.hasOwnProperty(vt("elementProperties"))) return;
2846
- const t = Ji(this);
2847
- t.finalize(), t.l !== void 0 && (this.l = [...t.l]), this.elementProperties = new Map(t.elementProperties);
2848
- }
2849
- static finalize() {
2850
- if (this.hasOwnProperty(vt("finalized"))) return;
2851
- if (this.finalized = !0, this._$Ei(), this.hasOwnProperty(vt("properties"))) {
2852
- const e = this.properties, i = [...Ki(e), ...Qi(e)];
2853
- for (const r of i) this.createProperty(r, e[r]);
2854
- }
2855
- const t = this[Symbol.metadata];
2856
- if (t !== null) {
2857
- const e = litPropertyMetadata.get(t);
2858
- if (e !== void 0) for (const [i, r] of e) this.elementProperties.set(i, r);
2859
- }
2860
- this._$Eh = /* @__PURE__ */ new Map();
2861
- for (const [e, i] of this.elementProperties) {
2862
- const r = this._$Eu(e, i);
2863
- r !== void 0 && this._$Eh.set(r, e);
2864
- }
2865
- this.elementStyles = this.finalizeStyles(this.styles);
2866
- }
2867
- static finalizeStyles(t) {
2868
- const e = [];
2869
- if (Array.isArray(t)) {
2870
- const i = new Set(t.flat(1 / 0).reverse());
2871
- for (const r of i) e.unshift(we(r));
2872
- } else t !== void 0 && e.push(we(t));
2873
- return e;
2874
- }
2875
- static _$Eu(t, e) {
2876
- const i = e.attribute;
2877
- return i === !1 ? void 0 : typeof i == "string" ? i : typeof t == "string" ? t.toLowerCase() : void 0;
2878
- }
2879
- constructor() {
2880
- super(), this._$Ep = void 0, this.isUpdatePending = !1, this.hasUpdated = !1, this._$Em = null, this._$Ev();
2881
- }
2882
- _$Ev() {
2883
- this._$ES = new Promise(((t) => this.enableUpdating = t)), this._$AL = /* @__PURE__ */ new Map(), this._$E_(), this.requestUpdate(), this.constructor.l?.forEach(((t) => t(this)));
2884
- }
2885
- addController(t) {
2886
- (this._$EO ??= /* @__PURE__ */ new Set()).add(t), this.renderRoot !== void 0 && this.isConnected && t.hostConnected?.();
2887
- }
2888
- removeController(t) {
2889
- this._$EO?.delete(t);
2890
- }
2891
- _$E_() {
2892
- const t = /* @__PURE__ */ new Map(), e = this.constructor.elementProperties;
2893
- for (const i of e.keys()) this.hasOwnProperty(i) && (t.set(i, this[i]), delete this[i]);
2894
- t.size > 0 && (this._$Ep = t);
2895
- }
2896
- createRenderRoot() {
2897
- const t = this.shadowRoot ?? this.attachShadow(this.constructor.shadowRootOptions);
2898
- return ji(t, this.constructor.elementStyles), t;
2899
- }
2900
- connectedCallback() {
2901
- this.renderRoot ??= this.createRenderRoot(), this.enableUpdating(!0), this._$EO?.forEach(((t) => t.hostConnected?.()));
2902
- }
2903
- enableUpdating(t) {
2904
- }
2905
- disconnectedCallback() {
2906
- this._$EO?.forEach(((t) => t.hostDisconnected?.()));
2907
- }
2908
- attributeChangedCallback(t, e, i) {
2909
- this._$AK(t, i);
2910
- }
2911
- _$ET(t, e) {
2912
- const i = this.constructor.elementProperties.get(t), r = this.constructor._$Eu(t, i);
2913
- if (r !== void 0 && i.reflect === !0) {
2914
- const n = (i.converter?.toAttribute !== void 0 ? i.converter : qt).toAttribute(e, i.type);
2915
- this._$Em = t, n == null ? this.removeAttribute(r) : this.setAttribute(r, n), this._$Em = null;
2916
- }
2917
- }
2918
- _$AK(t, e) {
2919
- const i = this.constructor, r = i._$Eh.get(t);
2920
- if (r !== void 0 && this._$Em !== r) {
2921
- const n = i.getPropertyOptions(r), a = typeof n.converter == "function" ? { fromAttribute: n.converter } : n.converter?.fromAttribute !== void 0 ? n.converter : qt;
2922
- this._$Em = r;
2923
- const o = a.fromAttribute(e, n.type);
2924
- this[r] = o ?? this._$Ej?.get(r) ?? o, this._$Em = null;
2925
- }
2926
- }
2927
- requestUpdate(t, e, i) {
2928
- if (t !== void 0) {
2929
- const r = this.constructor, n = this[t];
2930
- if (i ??= r.getPropertyOptions(t), !((i.hasChanged ?? Be)(n, e) || i.useDefault && i.reflect && n === this._$Ej?.get(t) && !this.hasAttribute(r._$Eu(t, i)))) return;
2931
- this.C(t, e, i);
2932
- }
2933
- this.isUpdatePending === !1 && (this._$ES = this._$EP());
2934
- }
2935
- C(t, e, { useDefault: i, reflect: r, wrapped: n }, a) {
2936
- i && !(this._$Ej ??= /* @__PURE__ */ new Map()).has(t) && (this._$Ej.set(t, a ?? e ?? this[t]), n !== !0 || a !== void 0) || (this._$AL.has(t) || (this.hasUpdated || i || (e = void 0), this._$AL.set(t, e)), r === !0 && this._$Em !== t && (this._$Eq ??= /* @__PURE__ */ new Set()).add(t));
2937
- }
2938
- async _$EP() {
2939
- this.isUpdatePending = !0;
2940
- try {
2941
- await this._$ES;
2942
- } catch (e) {
2943
- Promise.reject(e);
2944
- }
2945
- const t = this.scheduleUpdate();
2946
- return t != null && await t, !this.isUpdatePending;
2947
- }
2948
- scheduleUpdate() {
2949
- return this.performUpdate();
2950
- }
2951
- performUpdate() {
2952
- if (!this.isUpdatePending) return;
2953
- if (!this.hasUpdated) {
2954
- if (this.renderRoot ??= this.createRenderRoot(), this._$Ep) {
2955
- for (const [r, n] of this._$Ep) this[r] = n;
2956
- this._$Ep = void 0;
2957
- }
2958
- const i = this.constructor.elementProperties;
2959
- if (i.size > 0) for (const [r, n] of i) {
2960
- const { wrapped: a } = n, o = this[r];
2961
- a !== !0 || this._$AL.has(r) || o === void 0 || this.C(r, void 0, n, o);
2962
- }
2963
- }
2964
- let t = !1;
2965
- const e = this._$AL;
2966
- try {
2967
- t = this.shouldUpdate(e), t ? (this.willUpdate(e), this._$EO?.forEach(((i) => i.hostUpdate?.())), this.update(e)) : this._$EM();
2968
- } catch (i) {
2969
- throw t = !1, this._$EM(), i;
2970
- }
2971
- t && this._$AE(e);
2972
- }
2973
- willUpdate(t) {
2974
- }
2975
- _$AE(t) {
2976
- this._$EO?.forEach(((e) => e.hostUpdated?.())), this.hasUpdated || (this.hasUpdated = !0, this.firstUpdated(t)), this.updated(t);
2977
- }
2978
- _$EM() {
2979
- this._$AL = /* @__PURE__ */ new Map(), this.isUpdatePending = !1;
2980
- }
2981
- get updateComplete() {
2982
- return this.getUpdateComplete();
2983
- }
2984
- getUpdateComplete() {
2985
- return this._$ES;
2986
- }
2987
- shouldUpdate(t) {
2988
- return !0;
2989
- }
2990
- update(t) {
2991
- this._$Eq &&= this._$Eq.forEach(((e) => this._$ET(e, this[e]))), this._$EM();
2992
- }
2993
- updated(t) {
2994
- }
2995
- firstUpdated(t) {
2996
- }
2997
- }
2998
- ft.elementStyles = [], ft.shadowRootOptions = { mode: "open" }, ft[vt("elementProperties")] = /* @__PURE__ */ new Map(), ft[vt("finalized")] = /* @__PURE__ */ new Map(), es?.({ ReactiveElement: ft }), (Gt.reactiveElementVersions ??= []).push("2.1.1");
2999
- class ze {
3000
- constructor(t, e) {
3001
- this.options = [], this.rootNode = e, this._el = document.createElement("div"), this._el.classList.add("context-menu"), t.options.forEach((i, r) => {
3002
- this.createOptionGroup(i), r !== t.options.length - 1 && this.addDivider();
3003
- }), this._el.addEventListener("contextmenu", (i) => {
3004
- i.preventDefault();
3005
- });
3006
- }
3007
- get el() {
3008
- return this._el;
3009
- }
3010
- attachToParent(t) {
3011
- t.appendChild(this.el);
3012
- }
3013
- createOptionGroup(t) {
3014
- const e = new is(t, this.rootNode);
3015
- this.options.push(e), this.el.appendChild(e.el);
3016
- }
3017
- addDivider() {
3018
- const t = document.createElement("hr");
3019
- t.classList.add("context-menu-divider"), this.el.appendChild(t);
3020
- }
3021
- }
3022
- class is {
3023
- constructor(t, e) {
3024
- this.childOptions = [], this.rootNode = e, this._el = document.createElement("div"), this.createOptionElement = this.createOptionElement.bind(this), t.childOptions.forEach((i) => this.createOptionElement(i));
3025
- }
3026
- get el() {
3027
- return this._el;
3028
- }
3029
- attachToParent(t) {
3030
- t.appendChild(this.el);
3031
- }
3032
- createOptionElement(t) {
3033
- t.parent = this;
3034
- const e = new ss(t, this.rootNode);
3035
- this.childOptions.push(e);
3036
- }
3037
- }
3038
- class ss {
3039
- get el() {
3040
- return this._el;
3041
- }
3042
- constructor(t, e) {
3043
- this.displayText = t.text, this.rootNode = e, this.parent = t.parent, this._el = document.createElement("button"), this._el.textContent = t.text, this._el.classList.add("context-menu-option"), this.parent.el.appendChild(this._el), "onClick" in t && this._el.addEventListener("click", t.onClick), this._el.addEventListener(
3044
- "pointerenter",
3045
- (i) => rs(i, t, this._el, this.rootNode)
3046
- ), this._el.addEventListener("contextmenu", (i) => {
3047
- i.preventDefault();
3048
- });
3049
- }
3050
- }
3051
- function rs(s, t, e, i) {
3052
- if (!i) return;
3053
- const r = i.querySelector(".sub-context-menu");
3054
- if (r && r.remove(), t.subMenu) {
3055
- const n = new ze(t.subMenu, this);
3056
- i.appendChild(n.el), n.el.id = `${t.text}-context-menu`, n.el.classList.add("sub-context-menu");
3057
- const a = i.getBoundingClientRect(), o = e.getBoundingClientRect(), h = n.el.getBoundingClientRect(), c = a.right - a.left, l = a.bottom - a.top, u = o.right + h.width;
3058
- o.top + h.height > l ? n._el.style.top = `${o.bottom - h.height}px` : n._el.style.top = `${o.top}px`, u > c ? n._el.style.left = `${o.left - h.width}px` : n._el.style.left = `${o.right}px`;
3059
- }
3060
- }
3061
- const St = 5;
3062
- function Xt(s) {
3063
- const t = this;
3064
- return function(...e) {
3065
- const i = s.apply(t, e);
3066
- return t.clearContextMenu(), i;
3067
- };
3068
- }
3069
- function ns(s, t, e = "single") {
3070
- const i = new ze(
3071
- e === "single" ? this.singleImageMenuOptions : e === "multi" ? this.multiImageMenuOptions : this.canvasImageMenuOptions,
3072
- this.rootDiv
3073
- );
3074
- if (!this.rootDiv) {
3075
- console.error("Can't add to parent div");
3076
- return;
3077
- }
3078
- i.attachToParent(this.rootDiv);
3079
- const r = this.getBoundingClientRect(), n = s - r.left, a = t - r.top, o = r.right - r.left, h = r.bottom - r.top, c = i.el.getBoundingClientRect(), l = [
3080
- n + c.width > o ? 1 : 0,
3081
- a + c.height > h ? 1 : 0
3082
- ], u = c.height * l[1], g = c.width * l[0];
3083
- if (u > h) {
3084
- const m = h - 2 * St;
3085
- i._el.style.height = `${m}px`, i._el.style.top = `${St}px`;
3086
- } else
3087
- i._el.style.top = `${a - u}px`;
3088
- g > o ? (i._el.style.width = `${o - 2 * St}px`, i._el.style.left = `${St}px`) : i._el.style.left = `${n - g}px`;
3089
- }
3090
- function as() {
3091
- const s = this.renderRoot.querySelector(".context-menu");
3092
- s && (s.remove(), this.eventHub.emit(H.Close));
3093
- }
3094
- function os() {
3095
- return this.renderRoot.querySelector(".context-menu") !== null;
3096
- }
3097
- function hs() {
3098
- const s = Xt.bind(this);
3099
- return {
3100
- options: [
3101
- {
3102
- childOptions: [
3103
- {
3104
- text: "Cut",
3105
- onClick: async () => {
3106
- await this.copyImage.bind(this)(), s(this.deleteSelectedImages.bind(this))();
3107
- }
3108
- },
3109
- {
3110
- text: "Copy",
3111
- onClick: s(this.copyImage.bind(this))
3112
- },
3113
- {
3114
- text: "Paste",
3115
- onClick: (t) => s(this.pasteImage.bind(this))(t)
3116
- },
3117
- {
3118
- text: "Delete",
3119
- onClick: s(this.deleteSelectedImages.bind(this))
3120
- }
3121
- ]
3122
- },
3123
- {
3124
- childOptions: [
3125
- {
3126
- text: "Flip Horizontal",
3127
- onClick: s(this.flipHorizontal.bind(this))
3128
- },
3129
- {
3130
- text: "Flip Vertical",
3131
- onClick: s(this.flipVertical.bind(this))
3132
- }
3133
- ]
3134
- }
3135
- ]
3136
- };
3137
- }
3138
- function cs(s) {
3139
- const t = Xt.bind(this);
3140
- return {
3141
- options: [
3142
- ...s ?? [],
3143
- {
3144
- childOptions: [
3145
- {
3146
- text: "Send to Front",
3147
- onClick: () => t(this.sendShapeToNewZOrder.bind(this))(!0)
3148
- },
3149
- {
3150
- text: "Send to Back",
3151
- onClick: () => t(this.sendShapeToNewZOrder.bind(this))(!1)
3152
- }
3153
- ]
3154
- }
3155
- ]
3156
- };
3157
- }
3158
- function ds(s) {
3159
- const t = Xt.bind(this);
3160
- return {
3161
- options: [
3162
- ...s ?? [],
3163
- {
3164
- childOptions: [
3165
- {
3166
- text: "Align",
3167
- onHover: () => {
3168
- },
3169
- subMenu: {
3170
- options: [
3171
- {
3172
- childOptions: [
3173
- {
3174
- text: "Align Left",
3175
- onClick: () => t(this.align.bind(this))("left")
3176
- },
3177
- {
3178
- text: "Align Right",
3179
- onClick: () => t(this.align.bind(this))("right")
3180
- },
3181
- {
3182
- text: "Align Top",
3183
- onClick: () => t(this.align.bind(this))("top")
3184
- },
3185
- {
3186
- text: "Align Bottom",
3187
- onClick: () => t(this.align.bind(this))("bottom")
3188
- }
3189
- ]
3190
- }
3191
- ]
3192
- }
3193
- },
3194
- {
3195
- text: "Normalize by First",
3196
- onHover: () => {
3197
- },
3198
- subMenu: {
3199
- options: [
3200
- {
3201
- childOptions: [
3202
- {
3203
- text: "Height",
3204
- onClick: () => t(this.normalizeSelection.bind(this))(
3205
- "height",
3206
- "first"
3207
- )
3208
- },
3209
- {
3210
- text: "Width",
3211
- onClick: () => t(this.normalizeSelection.bind(this))(
3212
- "width",
3213
- "first"
3214
- )
3215
- },
3216
- {
3217
- text: "Size",
3218
- onClick: () => t(this.normalizeSelection.bind(this))(
3219
- "size",
3220
- "first"
3221
- )
3222
- },
3223
- {
3224
- text: "Scale",
3225
- onClick: () => t(this.normalizeSelection.bind(this))(
3226
- "scale",
3227
- "first"
3228
- )
3229
- }
3230
- ]
3231
- }
3232
- ]
3233
- }
3234
- },
3235
- {
3236
- text: "Normalize by Average",
3237
- onHover: () => {
3238
- },
3239
- subMenu: {
3240
- options: [
3241
- {
3242
- childOptions: [
3243
- {
3244
- text: "Height",
3245
- onClick: () => t(this.normalizeSelection.bind(this))(
3246
- "height",
3247
- "average"
3248
- )
3249
- },
3250
- {
3251
- text: "Width",
3252
- onClick: () => t(this.normalizeSelection.bind(this))(
3253
- "width",
3254
- "average"
3255
- )
3256
- },
3257
- {
3258
- text: "Size",
3259
- onClick: () => t(this.normalizeSelection.bind(this))(
3260
- "size",
3261
- "average"
3262
- )
3263
- },
3264
- {
3265
- text: "Scale",
3266
- onClick: () => t(this.normalizeSelection.bind(this))(
3267
- "scale",
3268
- "average"
3269
- )
3270
- }
3271
- ]
3272
- }
3273
- ]
3274
- }
3275
- }
3276
- ]
3277
- }
3278
- ]
3279
- };
3280
- }
3281
- function ls(s) {
3282
- const t = Xt.bind(this);
3283
- return {
3284
- options: [
3285
- ...s ?? [],
3286
- {
3287
- childOptions: [
3288
- {
3289
- text: "Change mode",
3290
- onClick: () => t(this.togglePointerMode.bind(this))()
3291
- },
3292
- {
3293
- text: "Toggle Grid",
3294
- onClick: () => t(this.toggleGrid.bind(this))()
3295
- }
3296
- ]
3297
- },
3298
- {
3299
- childOptions: [
3300
- {
3301
- text: "Save",
3302
- onClick: () => t(this.saveToCanvasStorage.bind(this))()
3303
- },
3304
- {
3305
- text: "Paste",
3306
- onClick: (e) => t(this.pasteImage.bind(this))(e)
3307
- }
3308
- ]
3309
- }
3310
- ]
3311
- };
3312
- }
3313
- class te {
3314
- _touch() {
3315
- this._lastRetrieved = Date.now();
3316
- }
3317
- get id() {
3318
- return this._touch(), this._id;
3319
- }
3320
- get dataURL() {
3321
- return this._touch(), this._dataURL;
3322
- }
3323
- get mimetype() {
3324
- return this._touch(), this._mimetype;
3325
- }
3326
- get created() {
3327
- return this._touch(), this._created;
3328
- }
3329
- get lastRetrieved() {
3330
- return this._lastRetrieved;
3331
- }
3332
- constructor(t) {
3333
- this._dataURL = t, this._mimetype = li(t), this._created = Date.now(), this._lastRetrieved = Date.now();
3334
- }
3335
- static async create(t) {
3336
- const e = new te(t);
3337
- return e._id = await Qt(t), e;
3338
- }
3339
- }
3340
- class us {
3341
- }
3342
- class fs {
3343
- }
3344
- function ke(s) {
3345
- s.Version.prototype._parseStoresSpec = Y.override(
3346
- s.Version.prototype._parseStoresSpec,
3347
- ms
3348
- ), s.open = Y.override(s.open, ps(s));
3349
- }
3350
- function ms(s) {
3351
- return function(t, e) {
3352
- s.call(this, t, e), Object.keys(e).forEach(function(i) {
3353
- let r = e[i];
3354
- r.primKey.name.indexOf("$$") === 0 && (r.primKey.uuid = !0, r.primKey.name = r.primKey.name.substr(2), r.primKey.keyPath = r.primKey.keyPath.substr(2));
3355
- });
3356
- };
3357
- }
3358
- function gs(s) {
3359
- return function(e, i) {
3360
- let r;
3361
- return e === void 0 && s.schema.primKey.uuid && (e = r = ii(), s.schema.primKey.keyPath && Y.setByKeyPath(i, s.schema.primKey.keyPath, e)), r;
3362
- };
3363
- }
3364
- function ps(s) {
3365
- return function(e) {
3366
- return function() {
3367
- return Object.keys(s._allTables).forEach((i) => {
3368
- let r = s._allTables[i];
3369
- r.hook("creating").subscribe(gs(r));
3370
- }), e.apply(this, arguments);
3371
- };
3372
- };
3373
- }
3374
- Y.UUIDPrimaryKey = ke;
3375
- Y.addons.push(ke);
3376
- Y.UUIDPrimaryKey;
3377
- const xs = {
3378
- files: "$$id, mimetype, created, lastRetrieved"
3379
- }, Ce = {
3380
- MAX_IMAGE_ENTRIES: 1e3
3381
- };
3382
- class Mt extends us {
3383
- constructor() {
3384
- super(), this.dbQueue = new Me(), this.cache = /* @__PURE__ */ new Map(), this.CACHE_LIMIT = 500, this.dbQueue = new Me(), this.dbPromise = this.initDb();
3385
- }
3386
- async initDb() {
3387
- return $(async () => {
3388
- let t = new Y("InfiniteCanvas");
3389
- return Y.UUIDPrimaryKey(t), t.version(1).stores(xs), await t.open(), t;
3390
- });
3391
- }
3392
- async getIndexDb() {
3393
- return this.dbPromise;
3394
- }
3395
- /**
3396
- * Writes to indexedDB
3397
- * @param data
3398
- * @param mimetype
3399
- * @returns the file ID
3400
- */
3401
- async write(t) {
3402
- const e = await te.create(t), i = vs(e.dataURL);
3403
- return this.dbQueue.add(
3404
- () => $(async () => {
3405
- const r = await this.getIndexDb();
3406
- return await r.transaction("rw", r.files, async () => (await ws(r), await r.files.add({
3407
- id: e.id,
3408
- blob: i,
3409
- dataURL: e.dataURL,
3410
- mimetype: e.mimetype,
3411
- created: e.created,
3412
- lastRetrieved: e.lastRetrieved
3413
- }))).catch((n) => {
3414
- throw console.error("Failed to save image blob to local DB:", n), n;
3415
- });
3416
- })
3417
- );
3418
- }
3419
- async readAll() {
3420
- return $(async () => await (await this.getIndexDb()).files.toArray());
3421
- }
3422
- async readPage(t, e) {
3423
- return $(async () => await (await this.getIndexDb()).files.offset(t).limit(e).toArray());
3424
- }
3425
- async read(t) {
3426
- return $(async () => {
3427
- const e = await this.getIndexDb();
3428
- if (this.cache.has(t))
3429
- return this.cache.get(t);
3430
- const i = await e.files.get(t);
3431
- if (!i) return null;
3432
- if (this.dbQueue.add(async () => {
3433
- try {
3434
- await e.files.update(t, { lastRetrieved: Date.now() });
3435
- } catch (r) {
3436
- console.error("Failed to update lastRetrieved", r);
3437
- }
3438
- }).catch(() => {
3439
- }), this.cache.set(t, i), this.cache.size > this.CACHE_LIMIT) {
3440
- const r = this.cache.keys().next().value;
3441
- this.cache.delete(r);
3442
- }
3443
- return i;
3444
- });
3445
- }
3446
- async delete(t) {
3447
- return this.dbQueue.add(
3448
- () => $(async () => {
3449
- const e = await this.getIndexDb();
3450
- return await e.transaction("rw", e.files, async () => {
3451
- const i = await e.files.where("id").equals(t).first();
3452
- return await e.files.delete(i.id), i;
3453
- }).catch((i) => {
3454
- throw console.error("Failed to save image blob to local DB:", i), i;
3455
- });
3456
- })
3457
- );
3458
- }
3459
- async update(t) {
3460
- return this.dbQueue.add(
3461
- () => $(async () => {
3462
- const e = await this.getIndexDb();
3463
- return await e.transaction("rw", e.files, async () => {
3464
- await e.files.update(t.id, {
3465
- dataURL: t.dataURL,
3466
- mimetype: t.mimetype,
3467
- lastRetrieved: Date.now()
3468
- });
3469
- }), await e.files.where("id").equals(t.id).first();
3470
- })
3471
- );
3472
- }
3473
- async checkIfImageStored(t) {
3474
- return $(async () => {
3475
- const i = await (await this.getIndexDb()).files.where("id").equals(t).first();
3476
- return i ? i.id : null;
3477
- });
3478
- }
3479
- }
3480
- class $t extends fs {
3481
- constructor(t) {
3482
- super(), this.key = "infinite_canvas", this.key = t;
3483
- }
3484
- async write(t) {
3485
- return new Promise((e, i) => {
3486
- try {
3487
- localStorage.setItem(this.key, JSON.stringify(t)), e();
3488
- } catch (r) {
3489
- i(r);
3490
- }
3491
- });
3492
- }
3493
- async read() {
3494
- return new Promise((t, e) => {
3495
- try {
3496
- t(localStorage.getItem(this.key));
3497
- } catch (i) {
3498
- e(i);
3499
- }
3500
- });
3501
- }
3502
- async delete() {
3503
- return new Promise((t, e) => {
3504
- try {
3505
- localStorage.removeItem(this.key), t();
3506
- } catch (i) {
3507
- e(i);
3508
- }
3509
- });
3510
- }
3511
- async update(t) {
3512
- return this.write(t);
3513
- }
3514
- }
3515
- class Se extends Error {
3516
- constructor(t) {
3517
- super(t), this.name = "QuotaExceededError";
3518
- }
3519
- }
3520
- class ys extends Error {
3521
- constructor(t) {
3522
- super(t), this.name = "DatabaseLimitError";
3523
- }
3524
- }
3525
- class Me {
3526
- constructor() {
3527
- this.queue = Promise.resolve();
3528
- }
3529
- async add(t) {
3530
- const e = this.queue.then(() => t());
3531
- return this.queue = e.catch(() => {
3532
- }), e;
3533
- }
3534
- }
3535
- const $ = async (s) => {
3536
- try {
3537
- return await s();
3538
- } catch (t) {
3539
- throw t instanceof DOMException && t.name === "QuotaExceededError" ? new Se(
3540
- "Storage quota exceeded. Please free up space."
3541
- ) : t instanceof Y.QuotaExceededError ? new Se(
3542
- "Database quota exceeded. Please free up space."
3543
- ) : t;
3544
- }
3545
- };
3546
- async function ws(s) {
3547
- if (await s.files.count() >= Ce.MAX_IMAGE_ENTRIES)
3548
- throw new ys(
3549
- `Cannot save image: limit of ${Ce.MAX_IMAGE_ENTRIES} reached`
3550
- );
3551
- }
3552
- function vs(s) {
3553
- const t = s.split(","), e = t[0], i = t[1], r = e.match(/:(.*?);/), n = r ? r[1] : "application/octet-stream", a = atob(i), o = a.length, h = new Uint8Array(o);
3554
- for (let c = 0; c < o; c++)
3555
- h[c] = a.charCodeAt(c);
3556
- return new Blob([h], { type: n });
3557
- }
3558
- class bs {
3559
- get el() {
3560
- return this._el;
3561
- }
3562
- constructor(t) {
3563
- this.type = t.type, this.message = t.message, this._el = document.createElement("div"), this._el.classList.add("canvas-loader"), this.render();
3564
- }
3565
- render() {
3566
- if (this._el.innerHTML = "", this.type === "spinner") {
3567
- const t = document.createElement("div");
3568
- if (t.classList.add("canvas-loader-spinner"), this._el.appendChild(t), this.message) {
3569
- const e = document.createElement("div");
3570
- e.classList.add("canvas-loader-message"), e.textContent = this.message, this._el.appendChild(e);
3571
- }
3572
- } else if (this.type === "message") {
3573
- const t = document.createElement("div");
3574
- t.classList.add("canvas-loader-message"), t.textContent = this.message ?? "", this._el.appendChild(t);
3575
- }
3576
- }
3577
- setMessage(t) {
3578
- this.message = t, this.render();
3579
- }
3580
- setProgress(t) {
3581
- this.progress = t, this.render();
3582
- }
3583
- attachToParent(t) {
3584
- t.appendChild(this.el);
3585
- }
3586
- remove() {
3587
- this._el.parentNode && this._el.parentNode.removeChild(this._el);
3588
- }
3589
- }
3590
- function Cs(s, t) {
3591
- const e = new bs({ type: s, message: t });
3592
- e.attachToParent(this.renderRoot);
3593
- const i = this.getBoundingClientRect();
3594
- return e.el.style.width = `${i.right}px`, e.el.style.height = `${i.bottom}px`, e._el.style.top = `${-i.bottom}px`, e;
3595
- }
3596
- function Ss() {
3597
- const s = this.renderRoot.querySelector(".canvas-loader");
3598
- s && s.remove();
3599
- }
3600
- var Ms = Object.getOwnPropertyDescriptor, Ue = (s) => {
3601
- throw TypeError(s);
3602
- }, Es = (s, t, e, i) => {
3603
- for (var r = i > 1 ? void 0 : i ? Ms(t, e) : t, n = s.length - 1, a; n >= 0; n--)
3604
- (a = s[n]) && (r = a(r) || r);
3605
- return r;
3606
- }, We = (s, t, e) => t.has(s) || Ue("Cannot " + e), d = (s, t, e) => (We(s, t, "read from private field"), e ? e.call(s) : t.get(s)), D = (s, t, e) => t.has(s) ? Ue("Cannot add the same private member more than once") : t instanceof WeakSet ? t.add(s) : t.set(s, e), M = (s, t, e, i) => (We(s, t, "write to private field"), t.set(s, e), e), p, _, It, j, L, k, gt, Pt, pt, xt, q, at, At, Lt, Ot;
3607
- let Ut = class extends ei {
3608
- constructor() {
3609
- super(...arguments), this.name = "Reffy", this.displayMode = "fullscreen", D(this, p), D(this, _), D(this, It), D(this, j), D(this, L), D(this, k), D(this, gt, 3e5), D(this, Pt), D(this, pt), D(this, xt), D(this, q), D(this, at), D(this, At), D(this, Lt), D(this, Ot), this.handleGlobalPointerDown = (s) => {
3610
- !this.contains(s.target) && !this.renderRoot.contains(s.target) && this.clearContextMenu();
3611
- };
3612
- }
3613
- get singleImageMenuOptions() {
3614
- return d(this, At);
3615
- }
3616
- get multiImageMenuOptions() {
3617
- return d(this, Lt);
3618
- }
3619
- get canvasImageMenuOptions() {
3620
- return d(this, Ot);
3621
- }
3622
- get canvas() {
3623
- return d(this, p);
3624
- }
3625
- get onCanvasChange() {
3626
- return d(this, at);
3627
- }
3628
- set onCanvasChange(s) {
3629
- M(this, at, s);
3630
- }
3631
- get eventHub() {
3632
- return d(this, _);
3633
- }
3634
- get rootDiv() {
3635
- return d(this, q);
3636
- }
3637
- // Lifecycle
3638
- connectedCallback() {
3639
- super.connectedCallback(), this.handleGlobalPointerDown = this.handleGlobalPointerDown.bind(this), document.addEventListener(
3640
- "pointerdown",
3641
- this.handleGlobalPointerDown,
3642
- !0
3643
- );
3644
- }
3645
- disconnectedCallback() {
3646
- document.removeEventListener(
3647
- "pointerdown",
3648
- this.handleGlobalPointerDown,
3649
- !0
3650
- ), window.removeEventListener("resize", d(this, xt)), d(this, It)?.disconnect(), M(this, It, void 0), d(this, p).destroy(), super.disconnectedCallback();
3651
- }
3652
- firstUpdated(s) {
3653
- try {
3654
- this.initCanvas();
3655
- } catch (t) {
3656
- throw console.error(t), t;
3657
- }
3658
- }
3659
- updated(s) {
3660
- if (!(s.has("width") || s.has("height") || s.has("displayMode"))) return;
3661
- const e = d(this, q), i = this.renderRoot.querySelector(
3662
- "canvas"
3663
- );
3664
- e && i && this.resizeCanvas(e, i);
3665
- }
3666
- async initCanvas() {
3667
- await this.warmUpStorage(), M(this, j, new Hi()), M(this, _, new si());
3668
- const s = document.createElement("div");
3669
- s.style.overflow = "hidden", this.renderRoot.appendChild(s), M(this, q, s);
3670
- const t = document.createElement("canvas");
3671
- this.assignFileStorage = this.assignFileStorage.bind(this), this.getImageFileMetadata = this.getImageFileMetadata.bind(this), this.getAllImageFileMetdata = this.getAllImageFileMetdata.bind(this), this.saveImageFileMetadata = this.saveImageFileMetadata.bind(this), this.restoreStateFromCanvasStorage = this.restoreStateFromCanvasStorage.bind(this), this.assignCanvasStorage = this.assignCanvasStorage.bind(this), this.saveToCanvasStorage = this.saveToCanvasStorage.bind(this), this.debounceSaveToCanvasStorage = this.debounceSaveToCanvasStorage.bind(this), this.importCanvas = this.importCanvas.bind(this), this.exportCanvas = this.exportCanvas.bind(this), this.addContextMenu = ns.bind(this), this.clearContextMenu = as.bind(this), this.isContextMenuActive = os.bind(this), this.getContainerSize = this.getContainerSize.bind(this), s.contains(t) || s.appendChild(t), this.registerSignal(), M(this, p, new kt(
3672
- t,
3673
- d(this, j),
3674
- d(this, _),
3675
- this.debounceSaveToCanvasStorage,
3676
- this.saveImageFileMetadata,
3677
- this.getContainerSize
3678
- ));
3679
- try {
3680
- await this.restoreStateFromCanvasStorage();
3681
- } catch {
3682
- console.error("Failed to restore canvas");
3683
- }
3684
- this.resizeCanvas(s, t), M(this, xt, () => this.resizeCanvas(s, t)), window.addEventListener("resize", d(this, xt));
3685
- const e = hs.bind(this)();
3686
- M(this, At, cs.bind(this)(
3687
- e.options
3688
- )), M(this, Ot, ls.bind(this)()), M(this, Lt, ds.bind(this)(
3689
- e.options
3690
- )), this.dispatchEvent(new Event("load"));
3691
- const i = new ri();
3692
- i.showPanel(0), this.renderRoot.contains(i.dom) || this.renderRoot.appendChild(i.dom);
3693
- const r = () => {
3694
- i && i.update(), d(this, p).render(), requestAnimationFrame(r);
3695
- };
3696
- r();
3697
- }
3698
- normalizeCssSize(s) {
3699
- if (!s) return s;
3700
- const t = String(s).trim();
3701
- return /^\d+$/.test(t) ? `${t}px` : t;
3702
- }
3703
- resizeCanvas(s, t) {
3704
- s.style.width = this.displayMode === "fullscreen" ? "100vw" : this.normalizeCssSize(this.width), s.style.height = this.displayMode === "fullscreen" ? "100vh" : this.normalizeCssSize(this.height), s.style.overflow = "hidden";
3705
- const e = window.devicePixelRatio || 1;
3706
- let i = window.screen.width, r = window.screen.height;
3707
- const n = s.getBoundingClientRect(), a = Math.round(i * e), o = Math.round(r * e);
3708
- (t.width !== a || t.height !== o) && (t.width = a, t.height = o), t.style.width = `${i}px`, t.style.height = `${r}px`, this.canvas.camera.viewportX = n.x, this.canvas.camera.viewportY = n.y, this.canvas.camera.state.setHeight(n.height), this.canvas.camera.state.setWidth(n.width);
3709
- }
3710
- // Register signal
3711
- registerSignal() {
3712
- d(this, _).on(it.start, Cs.bind(this), "spinner"), d(this, _).on(it.done, Ss.bind(this)), d(this, _).on(H.Open, this.addContextMenu), d(this, _).on(H.Close, this.clearContextMenu), d(this, _).on(N.Change, () => {
3713
- d(this, at) && d(this, at).call(this);
3714
- }), d(this, _).on(st.Save, this.saveToCanvasStorage), d(this, _).on(st.SaveCompleted, () => {
3715
- }), d(this, _).on(
3716
- st.SaveFailed,
3717
- () => console.error("Failed to Save!")
3718
- );
3719
- }
3720
- // need to check if this is good practice
3721
- async warmUpStorage() {
3722
- d(this, L) || M(this, L, new Mt());
3723
- try {
3724
- await d(this, L).readAll();
3725
- } catch (s) {
3726
- console.error("Storage warm-up failed", s);
3727
- }
3728
- }
3729
- /**
3730
- * @returns An array containing the width and height of the container
3731
- */
3732
- getContainerSize() {
3733
- if (!d(this, q)) return;
3734
- const s = d(this, q).getBoundingClientRect();
3735
- return [s.width, s.height];
3736
- }
3737
- // Storage & Persistence
3738
- /**
3739
- * @param storage Canvas storage stores the positions of all the renderables
3740
- * @param saveFrequency How often should auto save execute
3741
- */
3742
- assignCanvasStorage(s, t = d(this, gt)) {
3743
- M(this, k, s), M(this, gt, t), d(this, pt) && clearInterval(d(this, pt)), M(this, pt, setInterval(
3744
- this.saveToCanvasStorage,
3745
- d(this, gt)
3746
- ));
3747
- }
3748
- /**
3749
- * @param storage File storage captures the information about the image data that has previously been added. Made more efficient by using SHA of the image data for storage.
3750
- */
3751
- assignFileStorage(s) {
3752
- M(this, L, s);
3753
- }
3754
- /**
3755
- * Duplicate images will not be written to the database
3756
- * @param dataURL
3757
- * @returns The unique ID that the image has been logged with. This is a hashed version of the image data URL
3758
- */
3759
- async saveImageFileMetadata(s) {
3760
- d(this, L) || M(this, L, new Mt());
3761
- try {
3762
- const t = await Qt(s);
3763
- return await d(this, L).checkIfImageStored(t) ? t : await d(this, L).write(s);
3764
- } catch (t) {
3765
- console.error(t);
3766
- }
3767
- }
3768
- /**
3769
- * @param fileId Retrieves the file metadata
3770
- * @returns
3771
- */
3772
- async getImageFileMetadata(s) {
3773
- d(this, L) || M(this, L, new Mt());
3774
- try {
3775
- return await d(this, L).read(s);
3776
- } catch (t) {
3777
- console.error(t);
3778
- }
3779
- }
3780
- /**
3781
- * @returns All file metadata saved in connected storage
3782
- */
3783
- async getAllImageFileMetdata() {
3784
- d(this, L) || M(this, L, new Mt());
3785
- try {
3786
- return await d(this, L).readAll();
3787
- } catch (s) {
3788
- console.error(s);
3789
- }
3790
- }
3791
- /**
3792
- * Schedule the auto save to the canvas storage based on timer
3793
- */
3794
- debounceSaveToCanvasStorage(s = 1e3) {
3795
- d(this, k) || M(this, k, new $t(this.name)), clearTimeout(d(this, Pt)), M(this, Pt, setTimeout(this.saveToCanvasStorage, s));
3796
- }
3797
- async saveToCanvasStorage() {
3798
- d(this, k) || M(this, k, new $t(this.name)), d(this, k).write(Vt(d(this, p))).then(() => d(this, _).emit(st.SaveCompleted)).catch(() => d(this, _).emit(st.SaveFailed));
3799
- }
3800
- async restoreStateFromCanvasStorage() {
3801
- d(this, k) || M(this, k, new $t(this.name));
3802
- const s = await d(this, k).read(), t = JSON.parse(s);
3803
- t && await Zt(t, d(this, p), this.getImageFileMetadata);
3804
- }
3805
- // Canvas API
3806
- togglePointerMode() {
3807
- d(this, p) && d(this, p).changeMode();
3808
- }
3809
- toggleGrid() {
3810
- d(this, p) && d(this, p).toggleGrid();
3811
- }
3812
- zoomIn() {
3813
- d(this, p) && d(this, p).updateZoomByFixedAmount(-1);
3814
- }
3815
- zoomOut() {
3816
- d(this, p) && d(this, p).updateZoomByFixedAmount();
3817
- }
3818
- async addImages(s) {
3819
- if (!d(this, p)) return;
3820
- const t = d(this, p).getBoundingClientRect(), e = t.left + t.width / 2, i = t.top + t.height / 2, [r, n] = K(e, i, d(this, p)), a = await ui(
3821
- s,
3822
- (o) => d(this, p).addImageToCanvas(o, r, n, 1, 1, !0)
3823
- );
3824
- d(this, j).push(zt(d(this, p), a));
3825
- }
3826
- async removeImage(s) {
3827
- if (!d(this, p)) return;
3828
- const t = d(this, p).getChild(s);
3829
- d(this, p).removeChild(t), d(this, j).push(pi(d(this, p), t));
3830
- }
3831
- /**
3832
- * @param url Currently only accept base64 url and the image is automatically added to screen center
3833
- */
3834
- async addImageFromUrl(s) {
3835
- if (!d(this, p)) return;
3836
- const t = d(this, p).getBoundingClientRect(), e = t.left + t.width / 2, i = t.top + t.height / 2, [r, n] = K(e, i, d(this, p)), a = await d(this, p).addImageToCanvas(s, r, n, 1, 1, !0);
3837
- d(this, j).push(zt(d(this, p), [a]));
3838
- }
3839
- async copyImage() {
3840
- d(this, p) && await Re(d(this, p).getSelected());
3841
- }
3842
- async pasteImage(s) {
3843
- d(this, p) && await Ie(s.clientX, s.clientY, d(this, p), d(this, j), !1);
3844
- }
3845
- flipVertical() {
3846
- d(this, p) && d(this, p).selectionManager.flip("vertical");
3847
- }
3848
- flipHorizontal() {
3849
- d(this, p) && d(this, p).selectionManager.flip("horizontal");
3850
- }
3851
- align(s) {
3852
- d(this, p) && d(this, p).selectionManager.alignSelection(s);
3853
- }
3854
- normalizeSelection(s, t) {
3855
- d(this, p) && d(this, p).selectionManager.normalize(s, t);
3856
- }
3857
- sendShapeToNewZOrder(s) {
3858
- d(this, p) && d(this, p).setShapeZOrder(s);
3859
- }
3860
- deleteSelectedImages() {
3861
- d(this, p) && d(this, p).selectionManager.deleteSelected(d(this, p));
3862
- }
3863
- async exportCanvas(s = "infinite-canvas.json") {
3864
- if (!d(this, p)) return;
3865
- d(this, _).emit(it.start, "spinner");
3866
- const t = await this.getAllImageFileMetdata(), e = Vt(d(this, p), t);
3867
- fi(s, e), d(this, _).emit(it.done);
3868
- }
3869
- async importCanvas(s) {
3870
- if (d(this, _).emit(it.start, "spinner"), !d(this, p) || !s || s.length !== 1) return;
3871
- const t = s[0];
3872
- if (!t.type || !t.type.includes("json") && !t.name.toLowerCase().endsWith(".json"))
3873
- return;
3874
- const e = await mi(t);
3875
- await Zt(
3876
- e,
3877
- d(this, p),
3878
- this.getImageFileMetadata,
3879
- this.saveImageFileMetadata
3880
- ), d(this, _).emit(st.Save), d(this, _).emit(it.done);
3881
- }
3882
- clearCanvas() {
3883
- d(this, p) && d(this, p).clearChildren();
3884
- }
3885
- /**
3886
- * A non-reactive method that captures the number of images added to the canvas
3887
- */
3888
- getTotalNumberOfChildren() {
3889
- if (d(this, p))
3890
- return d(this, p).totalNumberOfChildren;
3891
- }
3892
- /**
3893
- * A non-reactive method that captures the number of images that are in camera
3894
- */
3895
- getNumberOfChildrenRendered() {
3896
- if (d(this, p))
3897
- return d(this, p).numberOfChildrenRendered;
3898
- }
3899
- };
3900
- p = /* @__PURE__ */ new WeakMap();
3901
- _ = /* @__PURE__ */ new WeakMap();
3902
- It = /* @__PURE__ */ new WeakMap();
3903
- j = /* @__PURE__ */ new WeakMap();
3904
- L = /* @__PURE__ */ new WeakMap();
3905
- k = /* @__PURE__ */ new WeakMap();
3906
- gt = /* @__PURE__ */ new WeakMap();
3907
- Pt = /* @__PURE__ */ new WeakMap();
3908
- pt = /* @__PURE__ */ new WeakMap();
3909
- xt = /* @__PURE__ */ new WeakMap();
3910
- q = /* @__PURE__ */ new WeakMap();
3911
- at = /* @__PURE__ */ new WeakMap();
3912
- At = /* @__PURE__ */ new WeakMap();
3913
- Lt = /* @__PURE__ */ new WeakMap();
3914
- Ot = /* @__PURE__ */ new WeakMap();
3915
- Ut.properties = {
3916
- name: { type: String, reflect: !0 },
3917
- width: { type: String, reflect: !0 },
3918
- height: { type: String, reflect: !0 },
3919
- displayMode: { type: String, reflect: !0 }
3920
- };
3921
- Ut.styles = ti`
3922
- :host {
3923
- position: relative;
3924
- overflow: hidden;
3925
- }
3926
-
3927
- .context-menu {
3928
- position: absolute;
3929
- background: white;
3930
- min-width: 180px;
3931
- background: var(--menu-bg, #fff);
3932
- border-radius: 6px;
3933
- border: 1px solid var(--menu-border, #9f9f9fff);
3934
- box-sizing: border-box;
3935
- padding: 6px 0;
3936
- display: flex;
3937
- gap: 2px;
3938
- flex-direction: column;
3939
- font-family: system-ui, sans-serif;
3940
- animation: fadeInMenu 0.13s cubic-bezier(0.4, 0, 0.2, 1);
3941
- overflow: scroll;
3942
- }
3943
-
3944
- @keyframes fadeInMenu {
3945
- from {
3946
- opacity: 0;
3947
- transform: translateY(8px);
3948
- }
3949
- to {
3950
- opacity: 1;
3951
- transform: none;
3952
- }
3953
- }
3954
-
3955
- .context-menu button {
3956
- all: unset;
3957
- display: flex;
3958
- align-items: center;
3959
- box-sizing: border-box;
3960
- width: 100%;
3961
- padding: 8px 18px;
3962
- font-size: 15px;
3963
- color: var(--menu-fg, #222);
3964
- background: none;
3965
- cursor: pointer;
3966
- transition:
3967
- background 0.1s,
3968
- color 0.1s;
3969
- user-select: none;
3970
- outline: none;
3971
- }
3972
-
3973
- .context-menu button:hover,
3974
- .context-menu button:focus-visible {
3975
- background: var(--menu-hover, #c7d5eaff);
3976
- color: var(--menu-accent, #155290ff);
3977
- }
3978
-
3979
- .context-menu button:active {
3980
- background: var(--menu-active, #e3eaf3);
3981
- }
3982
-
3983
- .context-menu button[disabled] {
3984
- color: #aaa;
3985
- cursor: not-allowed;
3986
- background: none;
3987
- }
3988
-
3989
- .context-menu-divider {
3990
- height: 1px;
3991
- background: var(--menu-divider, #c7d5eaff);
3992
- margin: 6px 12px;
3993
- border: none;
3994
- }
3995
-
3996
- canvas {
3997
- width: 100%;
3998
- height: 100%;
3999
- outline: none;
4000
- padding: 0;
4001
- margin: 0;
4002
- touch-action: none;
4003
- display: block;
4004
- }
4005
-
4006
- .canvas-loader {
4007
- position: absolute;
4008
- top: 0;
4009
- left: 0;
4010
- display: flex;
4011
- flex-direction: column;
4012
- align-items: center;
4013
- justify-content: center;
4014
- background: rgba(255, 255, 255, 0.7);
4015
- z-index: 1000;
4016
- pointer-events: all;
4017
- }
4018
-
4019
- .canvas-loader-spinner {
4020
- width: 48px;
4021
- height: 48px;
4022
- border: 6px solid #e0e0e0;
4023
- border-top: 6px solid #1976d2;
4024
- border-radius: 50%;
4025
- animation: canvas-loader-spin 1s linear infinite;
4026
- margin-bottom: 16px;
4027
- }
4028
-
4029
- @keyframes canvas-loader-spin {
4030
- 0% {
4031
- transform: rotate(0deg);
4032
- }
4033
- 100% {
4034
- transform: rotate(360deg);
4035
- }
4036
- }
4037
-
4038
- .canvas-loader-message {
4039
- font-size: 1.1rem;
4040
- color: #333;
4041
- background: rgba(255, 255, 255, 0.9);
4042
- padding: 8px 16px;
4043
- border-radius: 4px;
4044
- margin-top: 8px;
4045
- text-align: center;
4046
- max-width: 80%;
4047
- word-break: break-word;
4048
- }
4049
- `;
4050
- Ut = Es([
4051
- Ni("infinite-canvas")
4052
- ], Ut);
4053
- class Fe {
4054
- constructor(t) {
4055
- if (!t) throw new Error("InfiniteCanvasElement is required");
4056
- this.el = t, this.assignCanvasStorage = this.assignCanvasStorage.bind(this), this.zoomIn = this.zoomIn.bind(this), this.zoomOut = this.zoomOut.bind(this), this.toggleMode = this.toggleMode.bind(this), this.addImageFromLocal = this.addImageFromLocal.bind(this), this.exportCanvas = this.exportCanvas.bind(this), this.importCanvas = this.importCanvas.bind(this), this.clearCanvas = this.clearCanvas.bind(this);
4057
- }
4058
- static async forElement(t) {
4059
- let e;
4060
- if (typeof t == "string" ? (await customElements.whenDefined("infinite-canvas"), e = document.querySelector(
4061
- t
4062
- )) : e = t, !e) throw new Error("infinite-canvas element not found");
4063
- return e.canvas || await new Promise(
4064
- (i) => e.addEventListener("load", () => i(), { once: !0 })
4065
- ), new Fe(e);
4066
- }
4067
- /**
4068
- * Without assigning storage, the canvas will not save any data
4069
- * @param storage
4070
- * @param saveFrequency How often auto save occurs in ms
4071
- */
4072
- assignCanvasStorage(t, e = 3e3) {
4073
- return this.el.assignCanvasStorage(t, e), this;
4074
- }
4075
- async zoomIn() {
4076
- console.log("zooming"), this.el.zoomIn();
4077
- }
4078
- async zoomOut() {
4079
- this.el.zoomOut();
4080
- }
4081
- async toggleMode() {
4082
- this.el.togglePointerMode();
4083
- }
4084
- async addImageFromLocal(t) {
4085
- if (!(!t || t.length === 0)) {
4086
- for (let e = 0; e < t.length; e++) {
4087
- const i = t[e];
4088
- if (!i || !i.type || !i.type.startsWith("image/"))
4089
- throw new Error(
4090
- "Only specific image files are supported. Please select image files only."
4091
- );
4092
- }
4093
- await this.el.addImages(t);
4094
- }
4095
- }
4096
- async exportCanvas(t) {
4097
- this.el.exportCanvas(t);
4098
- }
4099
- async importCanvas(t) {
4100
- !t || t.length !== 1 || await this.el.importCanvas(t);
4101
- }
4102
- async clearCanvas() {
4103
- this.el.clearCanvas();
4104
- }
4105
- }
4106
- export {
4107
- Fi as Camera,
4108
- kt as Canvas,
4109
- Fe as InfiniteCanvasAPI,
4110
- Ut as InfiniteCanvasElement,
4111
- Wi as ZOOM_MAX,
4112
- Ui as ZOOM_MIN
4113
- };
4114
- //# sourceMappingURL=index.js.map