@reffy/infinite-canvas 0.0.10 → 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,4110 +0,0 @@
1
- var ie = (s) => {
2
- throw TypeError(s);
3
- };
4
- var se = (s, t, e) => t.has(s) || ie("Cannot " + e);
5
- var l = (s, t, e) => (se(s, t, "read from private field"), e ? e.call(s) : t.get(s)), L = (s, t, e) => t.has(s) ? ie("Cannot add the same private member more than once") : t instanceof WeakSet ? t.add(s) : t.set(s, e), I = (s, t, e, i) => (se(s, t, "write to private field"), i ? i.call(s, e) : t.set(s, e), e);
6
- import { makeObservable as Me, computed as st, action as b, observable as B, reaction as Qe } from "mobx";
7
- import { css as Je, LitElement as ti } from "lit";
8
- import Y from "dexie";
9
- import { v4 as ei } from "uuid";
10
- import ii from "eventemitter3";
11
- import si from "stats.js";
12
- const pt = ["TOP", "BOTTOM", "LEFT", "RIGHT"], Mt = ["TOPLEFT", "TOPRIGHT", "BOTTOMLEFT", "BOTTOMRIGHT"], re = {
13
- TOPLEFT: "TOPRIGHT",
14
- TOPRIGHT: "TOPLEFT",
15
- BOTTOMLEFT: "BOTTOMRIGHT",
16
- BOTTOMRIGHT: "BOTTOMLEFT"
17
- };
18
- function ne(s) {
19
- return re[s] ? re[s] : s;
20
- }
21
- const Ee = 8, qt = 2, M = {
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], u = s[8], f = 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
- f * e + g * n + m * h,
39
- f * i + g * a + m * c,
40
- f * r + g * o + m * u,
41
- w * e + x * n + C * h,
42
- w * i + x * a + C * c,
43
- w * r + x * o + C * u,
44
- v * e + A * n + T * h,
45
- v * i + A * a + T * c,
46
- v * r + A * o + T * u
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], u = s[8], f = u * a - o * c, g = -u * n + o * h, m = c * n - a * h, x = 1 / (e * f + i * g + r * m);
51
- return t[0] = f * x, t[1] = (-u * i + r * c) * x, t[2] = (o * i - r * a) * x, t[3] = g * x, t[4] = (u * 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 Xt(s, t, e) {
66
- const i = ae(s, s.VERTEX_SHADER, t), r = ae(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 ae(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 ri(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, u = h / e * 2 - 1, f = c / i * -2 + 1, g = M.projection(e, i), m = M.multiply(g, n), w = M.inverse(m), [x, C] = M.transformPoint(w, [u, f]);
81
- return [x, C];
82
- }
83
- function wt(s, t, e) {
84
- const { gl: i, canvas: r } = e;
85
- return ri(
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 ni(s) {
102
- return Math.hypot(s[0], s[1]);
103
- }
104
- function ai(s) {
105
- return Math.hypot(s[3], s[4]);
106
- }
107
- function J(s) {
108
- return [ni(s), ai(s)];
109
- }
110
- function oe(s) {
111
- return s / Math.abs(s);
112
- }
113
- function Et(s) {
114
- return [oe(s[0]), oe(s[4])];
115
- }
116
- const Lt = (s, t) => Math.abs(s) < t ? 0 : Math.sign(s), Dt = (s, t, e) => {
117
- const i = s * t;
118
- return Lt(s, e) !== Lt(i, e);
119
- };
120
- async function oi(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 hi = [
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 ci(s) {
141
- return hi.includes(s);
142
- }
143
- async function Kt(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 di(s) {
148
- const t = /^data:([^;]+);base64,/.exec(s);
149
- return t ? t[1] : void 0;
150
- }
151
- async function li(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 (ci(r.type))
157
- try {
158
- const n = await oi(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 ui(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 fi(s) {
171
- const t = await s.text();
172
- return JSON.parse(t);
173
- }
174
- function Te(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 nt = [0.33, 0.6, 0.95, 1], bt = [
188
- 0.33,
189
- 0.6,
190
- 0.95,
191
- 0.6
192
- ], mi = [
193
- 0.33,
194
- 0.6,
195
- 0.95,
196
- 0.4
197
- ];
198
- function Bt(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 gi(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 pi(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 xi = ["image/", "text/plain"], yi = () => "clipboard" in navigator && "writeText" in navigator.clipboard;
251
- async function _e(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 (yi())
265
- try {
266
- await navigator.clipboard.write([r]);
267
- return;
268
- } catch (n) {
269
- console.error(n);
270
- }
271
- if (!wi(i))
272
- throw new Error("Error copying to clipboard.");
273
- }
274
- function wi(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 Re(s, t, e, i, r = !0) {
289
- const n = await navigator.clipboard.read(), a = n[0].types, [o, h] = r ? [s, t] : wt(s, t, e);
290
- for (const c of a) {
291
- if (!xi.find(
292
- (m) => m.endsWith("/") ? c.startsWith(m) : c === m
293
- )) continue;
294
- const f = await n[0].getType(c);
295
- try {
296
- if (c === "text/plain") {
297
- const m = JSON.parse(await f.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(Bt(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 f.text();
324
- g = await Te(
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(f);
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(Bt(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
- }, tt = {
358
- start: "startloading",
359
- done: "completeloading"
360
- }, et = {
361
- Save: "save",
362
- SaveCompleted: "savecompleted",
363
- SaveFailed: "savefailed"
364
- }, vi = `
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
- `, bi = `
383
- precision mediump float;
384
- uniform vec4 u_color;
385
-
386
- void main() {
387
- gl_FragColor = u_color;
388
- }
389
- `, Ci = (
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
- ), Si = (
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
- ), Mi = `
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
- `, Ei = `
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 he {
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 = qt, this.boxSize = Ee / 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 ? J(e) : [1, 1], { width: n, height: a, borderSize: o } = this, [h, c] = U(e), [u, f] = Et(e);
528
- return {
529
- TOP: {
530
- x: u > 0 ? h : h - n * i,
531
- y: c,
532
- width: n * i,
533
- height: o
534
- },
535
- BOTTOM: {
536
- x: u > 0 ? h : h - n * i,
537
- y: c + a * r * f,
538
- width: n * i,
539
- height: o
540
- },
541
- LEFT: {
542
- x: h,
543
- y: f > 0 ? c : c - a * r,
544
- width: o,
545
- height: a * r
546
- },
547
- RIGHT: {
548
- x: h + n * i * u,
549
- y: f > 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 ? J(e) : [1, 1], { width: n, height: a, boxSize: o } = this, [h, c] = U(e), [u, f] = Et(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 * u,
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 * f,
573
- width: o * 2,
574
- height: o * 2
575
- },
576
- BOTTOMRIGHT: {
577
- x: h - o + n * i * u,
578
- y: c - o + a * r * f,
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] = J(this.target.worldMatrix), [a, o] = Et(this.target.worldMatrix), [h, c] = U(i, t, e), u = 4;
599
- for (const T of Mt) {
600
- const S = this.getCornersInScreenSpace(
601
- T,
602
- this.target.worldMatrix
603
- );
604
- if (h >= S.x - u && h <= S.x + S.width + u && c >= S.y - u && c <= S.y + S.height + u)
605
- return T;
606
- }
607
- for (const T of pt) {
608
- const S = this.getSidesInScreenSpace(T, this.target.worldMatrix);
609
- if (h >= S.x - u && h <= S.x + S.width + u && c >= S.y - u && c <= S.y + S.height + u)
610
- return T;
611
- }
612
- const [f, g] = U(this.target.worldMatrix), m = this.width * r * a, w = this.height * n * o, x = Math.min(f, f + m), C = Math.max(f, f + 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, u = Math.abs(r * o) < c ? c * Lt(r * o || 1, c) : r * o, f = Math.abs(n * h) < c ? c * Lt(n * h || 1, c) : n * h, g = t / u, m = e / f, 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 (Dt(o, x, w) || Dt(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 Mt) {
681
- const e = new Z(
682
- this.getCornersInScreenSpace(t, this.target.worldMatrix)
683
- );
684
- e.color = this.mode === z.ACTIVE ? nt : bt, this.corners.set(t, e);
685
- }
686
- }
687
- removeCorners() {
688
- this.corners.clear();
689
- }
690
- updateCorners() {
691
- for (const t of Mt) {
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 ? nt : bt);
697
- }
698
- }
699
- addSides() {
700
- for (const t of pt) {
701
- const e = new Z(
702
- this.getSidesInScreenSpace(t, this.target.worldMatrix)
703
- );
704
- e.color = this.mode === z.ACTIVE ? nt : bt, this.sides.set(t, e);
705
- }
706
- }
707
- updateSides() {
708
- for (const t of pt) {
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 ? nt : bt);
711
- }
712
- }
713
- }
714
- const Ht = [
715
- ...Mt,
716
- ...pt
717
- ];
718
- class Ti {
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 = qt, this.boxSize = Ee / 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"), u = i.includes("RIGHT"), f = c ? this.x + n : u ? 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] = J(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 (Dt(this.scale[0], S, m) || Dt(this.scale[1], S, m))
749
- return;
750
- const Fe = n * S, Ge = a * S;
751
- if (!(Math.abs(Fe) < m || Math.abs(Ge) < m))
752
- for (const vt of this.targets) {
753
- const Xe = vt.x, He = vt.y, [te, ee] = U(r, Xe, He), Ne = f + (te - f) * S, Ye = g + (ee - g) * S, $e = Ne - te, je = Ye - ee, Ve = Math.abs(C) < m ? C < 0 ? -m : m : C, Ze = Math.abs(v) < m ? v < 0 ? -m : m : v, qe = $e / Ve, Ke = je / Ze;
754
- vt.updateScale(S, S), vt.updateTranslation(qe, Ke);
755
- }
756
- }
757
- flip(t, e, i) {
758
- J(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 u = a.height * a.sy, f = Math.abs(n / u);
824
- a.updateScale(f, f);
825
- } else if (t === "width") {
826
- const u = a.width * a.sx, f = Math.abs(n / u);
827
- a.updateScale(f, f);
828
- } else if (t === "scale") {
829
- const u = Math.sign(a.sx), f = Math.sign(a.sy);
830
- a.setScale(n * u, n * f);
831
- } else if (t === "size") {
832
- const u = a.width * a.height * a.sx * a.sy, f = Math.sqrt(Math.abs(n / u));
833
- a.updateScale(f, f);
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 f of Ht) {
870
- const g = this.getHandleConfig(f);
871
- if (r >= g.x - a && r <= g.x + g.width + a && n >= g.y - a && n <= g.y + g.height + a)
872
- return f;
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), u = Math.max(this.y, this.y + this.height);
875
- if (r >= o && r <= h && n >= c && n <= u)
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, u] = 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 ? u : h), r = Math.max(r, a.sx < 0 ? o : c), n = Math.max(n, a.sy < 0 ? h : u);
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 Ht) {
897
- const e = this.getHandleConfig(t), i = new Z(e);
898
- i.color = nt, this.handles.set(t, i);
899
- }
900
- }
901
- updateHandles() {
902
- for (const t of Ht) {
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 dt {
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 ce = ["CENTER", ...pt];
974
- class _i {
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 = qt, 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 dt(a, h, o, c);
1034
- }
1035
- resize(t, e, i) {
1036
- const [r, n] = J(i);
1037
- this.width += t * r, this.height += e * n;
1038
- }
1039
- addRects() {
1040
- for (const t of ce) {
1041
- const e = this.getRectConfig(t), i = new Z(e);
1042
- i.color = nt, this.rects.set(t, i);
1043
- }
1044
- }
1045
- updateRects() {
1046
- for (const t of ce) {
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 = mi));
1049
- }
1050
- }
1051
- }
1052
- class Ri {
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, Me(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: st
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 M.translation(this.x, this.y);
1120
- }
1121
- get rotationMatrix() {
1122
- return M.rotation(this.rotation);
1123
- }
1124
- get scaleMatrix() {
1125
- return M.scaling(this.zoom, this.zoom);
1126
- }
1127
- get cameraMatrix() {
1128
- const t = M.multiply(this.translationMatrix, this.rotationMatrix);
1129
- return M.multiply(t, this.scaleMatrix);
1130
- }
1131
- get canvasMatrix() {
1132
- return M.inverse(this.cameraMatrix);
1133
- }
1134
- }
1135
- function de(s, t) {
1136
- s.setTranslation(t.x, t.y), s.setScale(t.sx, t.sy);
1137
- }
1138
- function le(s, t, e) {
1139
- return {
1140
- label: "Flip",
1141
- do() {
1142
- for (const i of s) de(i.ref, i.end);
1143
- e && (e.scale[t === "horizontal" ? 0 : 1] *= -1);
1144
- },
1145
- undo() {
1146
- for (const i of s) de(i.ref, i.start);
1147
- e && (e.scale[t === "horizontal" ? 0 : 1] *= -1);
1148
- }
1149
- };
1150
- }
1151
- function ue(s, t) {
1152
- s.setTranslation(t.x, t.y), s.setScale(t.sx, t.sy);
1153
- }
1154
- function $t(s, t = "Transform") {
1155
- return {
1156
- label: t,
1157
- do() {
1158
- for (const e of s) ue(e.ref, e.end);
1159
- },
1160
- undo() {
1161
- for (const e of s) ue(e.ref, e.start);
1162
- }
1163
- };
1164
- }
1165
- class Ii {
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 he(e));
1188
- });
1189
- }
1190
- get marqueeBox() {
1191
- return this.#r;
1192
- }
1193
- set marqueeBox(t) {
1194
- this.#r = new _i(
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 u of Object.getOwnPropertyNames(c)) {
1204
- const f = this[u];
1205
- typeof f == "function" && u !== "constructor" && (this[u] = f.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 he(e)));
1212
- }), this.#e.size > 1 && (this.#e.forEach((e) => e.setPassive()), this.#t || (this.#t = new Ti([])), 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(pi(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 ? ne(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 ? ne(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
- le(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(le(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($t(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($t(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(), u = this.marqueeBox.getBoundingBox(this.getMarqueeCoords);
1346
- for (const f of c) {
1347
- const g = f.getBoundingBox();
1348
- dt.isColliding(g, u) && !this.#i.has(f) ? this.add([f]) : !dt.isColliding(g, u) && this.#i.has(f) && this.remove([f]);
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 ft = /* @__PURE__ */ ((s) => (s[s.SELECT = 0] = "SELECT", s[s.PAN = 1] = "PAN", s))(ft || {});
1382
- const Pi = {
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 Ai {
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 _e(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(Pi[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($t(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 lt && 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 Li {
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 fe(s, t) {
1546
- s.renderOrder = t.renderOrder;
1547
- }
1548
- function Di(s, t = "Order") {
1549
- return {
1550
- label: t,
1551
- do() {
1552
- for (const e of s) fe(e.ref, e.end);
1553
- },
1554
- undo() {
1555
- for (const e of s) fe(e.ref, e.start);
1556
- }
1557
- };
1558
- }
1559
- class Bi {
1560
- constructor(t = ft.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 === ft.PAN ? ft.SELECT : ft.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 zi {
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 = M.identity(), this.worldMatrix = M.identity(), this.children = [], this.parent = null, this.renderDirtyFlag = !0, Me(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: st,
1607
- y: st,
1608
- scaleX: st,
1609
- scaleY: st,
1610
- dirty: st,
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 = M.translation(this.translation[0], this.translation[1]), e = M.rotation(this.angleRadians), i = M.scaling(this.scale[0], this.scale[1]);
1704
- this.localMatrix = M.multiply(M.multiply(t, e), i);
1705
- }
1706
- updateWorldMatrix(t) {
1707
- this.worldMatrix = t ? M.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 Ie {
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 zi(), 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 Pe extends Ie {
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 Ut = class Ut extends Pe {
1835
- constructor(t, e, i = 1, r = 1) {
1836
- super(), this._seq = Ut._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
- Ut._seqCounter = 0;
1873
- let lt = Ut;
1874
- class Z extends lt {
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 dt(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] = J(this.worldMatrix), [n, a] = Et(this.worldMatrix), [o, h] = U(this.parent.worldMatrix, t, e), [c, u] = U(this.worldMatrix), f = this.width * i * n, g = this.height * r * a, m = Math.min(c, c + f), w = Math.max(c, c + f), x = Math.min(u, u + g), C = Math.max(u, u + g);
1935
- return o >= m && o <= w && h >= x && h <= C;
1936
- }
1937
- }
1938
- class xt 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 u = Math.min(a / i, o / r), f = Math.round(i * u), g = Math.round(r * u), m = Math.round((a - f) / 2), w = Math.round((o - g) / 2);
2024
- c.drawImage(this._image, 0, 0, i, r, m, w, f, 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 Tt = /* @__PURE__ */ ((s) => (s[s.NONE = 0] = "NONE", s[s.GRID = 1] = "GRID", s))(Tt || {});
2154
- class Ae extends Pe {
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 = M.inverse(M.projection(i, r)), a = M.inverse(this.worldMatrix), o = M.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 ki = 0.02, Ui = 20;
2203
- class Wi {
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 = Qe(
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 dt(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(Ui, Math.max(ki, 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 me = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBmaWxsPSIjYjNiM2IzIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xLjUgNmEyLjI1IDIuMjUgMCAwIDEgMi4yNS0yLjI1aDE2LjVBMi4yNSAyLjI1IDAgMCAxIDIyLjUgNnYxMmEyLjI1IDIuMjUgMCAwIDEtMi4yNSAyLjI1SDMuNzVBMi4yNSAyLjI1IDAgMCAxIDEuNSAxOHpNMyAxNi4wNlYxOGMwIC40MTQuMzM2Ljc1Ljc1Ljc1aDE2LjVBLjc1Ljc1IDAgMCAwIDIxIDE4di0xLjk0bC0yLjY5LTIuNjg5YTEuNSAxLjUgMCAwIDAtMi4xMiAwbC0uODguODc5bC45Ny45N2EuNzUuNzUgMCAxIDEtMS4wNiAxLjA2bC01LjE2LTUuMTU5YTEuNSAxLjUgMCAwIDAtMi4xMiAwem0xMC4xMjUtNy44MWExLjEyNSAxLjEyNSAwIDEgMSAyLjI1IDBhMS4xMjUgMS4xMjUgMCAwIDEtMi4yNSAwIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiLz48L3N2Zz4=", it = 240;
2254
- function ge(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 Nt(s) {
2263
- return s.children.map(Oe);
2264
- }
2265
- function Oe(s) {
2266
- return s instanceof xt ? {
2267
- type: "Img",
2268
- id: s.seq,
2269
- renderOrder: s.renderOrder,
2270
- transform: ge(s),
2271
- width: s.width,
2272
- height: s.height,
2273
- fileId: s.fileId,
2274
- children: s.children?.length ? Nt(s) : void 0
2275
- } : s instanceof Z ? {
2276
- type: "Rect",
2277
- id: s.seq,
2278
- renderOrder: s.renderOrder,
2279
- transform: ge(s),
2280
- width: s.width,
2281
- height: s.height,
2282
- color: s.color,
2283
- children: s.children?.length ? Nt(s) : void 0
2284
- } : s instanceof Ae ? {
2285
- type: "Grid",
2286
- style: s.gridType
2287
- } : {
2288
- type: "Renderable",
2289
- children: s.children?.length ? Nt(s) : void 0
2290
- };
2291
- }
2292
- function jt(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 Vt(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 ?? me : me, i && i(h);
2329
- const c = n.width, u = n.height, f = await Gi(
2330
- h,
2331
- c * n.transform.sx,
2332
- u * n.transform.sy
2333
- );
2334
- o = new xt({
2335
- x: n.transform.x,
2336
- y: n.transform.y,
2337
- src: f,
2338
- width: c,
2339
- height: u
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 Kt(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 zt && (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 Fi(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 Gi(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 Fi(n);
2370
- } catch {
2371
- }
2372
- const o = t && t > 0 ? t : a?.naturalWidth ?? it, h = e && e > 0 ? e : a?.naturalHeight ?? it, c = document.createElement("canvas");
2373
- c.width = o, c.height = h;
2374
- const u = c.getContext("2d");
2375
- if (u.fillStyle = i, u.fillRect(0, 0, o, h), a) {
2376
- const f = Math.min(
2377
- o / a.naturalWidth,
2378
- h / a.naturalHeight
2379
- ), g = a.naturalHeight * f, m = a.naturalWidth * f;
2380
- let w = it, x = it;
2381
- (it > g || it > m) && (w = m, x = g);
2382
- const C = Math.round((o - w) / 2), v = Math.round((h - x) / 2);
2383
- u.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, K, at, y, G, ot, Q, X, V, P, ht, Wt, ct;
2401
- const R = class R extends Ie {
2402
- constructor(e, i, r, n, a, o) {
2403
- super();
2404
- L(this, W);
2405
- L(this, F);
2406
- L(this, K);
2407
- L(this, at);
2408
- L(this, y);
2409
- L(this, G);
2410
- L(this, ot);
2411
- L(this, Q);
2412
- L(this, X);
2413
- L(this, V);
2414
- L(this, P);
2415
- L(this, ht);
2416
- L(this, Wt);
2417
- L(this, ct);
2418
- I(this, V, !0), this.orderDirty = !0, this.renderList = [], I(this, W, e), I(this, F, r), I(this, K, i), I(this, X, new Ae()), I(this, y, e.getContext("webgl", {
2419
- alpha: !0,
2420
- premultipliedAlpha: !1
2421
- })), l(this, y).enable(l(this, y).BLEND), l(this, y).blendFunc(l(this, y).SRC_ALPHA, l(this, y).ONE_MINUS_SRC_ALPHA), l(this, y).getExtension("OES_standard_derivatives"), l(this, y).enable(l(this, y).DEPTH_TEST), l(this, y).depthFunc(l(this, y).LEQUAL), I(this, G, Xt(l(this, y), vi, bi)), I(this, ot, Xt(l(this, y), Mi, Ei)), I(this, Q, Xt(l(this, y), Ci, Si)), 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) => wt(g, m, this);
2422
- const h = (g, m) => wt(
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 Ii(
2428
- i,
2429
- r,
2430
- this.gl,
2431
- l(this, G),
2432
- () => this.worldMatrix,
2433
- () => this.children,
2434
- this.getWorldsCoordsFromCanvas,
2435
- h
2436
- ));
2437
- const c = new Ri({});
2438
- I(this, at, new Wi(
2439
- c,
2440
- this.setWorldMatrix,
2441
- this.updateWorldMatrix,
2442
- this.getWorldsCoordsFromCanvas
2443
- )), I(this, Wt, new Oi(
2444
- i,
2445
- r,
2446
- () => this.selectionManager.deleteSelected(this),
2447
- this.assignEventListener
2448
- )), I(this, ct, new Li(
2449
- r,
2450
- this.selectionManager.isMultiBoundingBoxHit,
2451
- this.selectionManager.isBoundingBoxHit,
2452
- this.getWorldsCoordsFromCanvas,
2453
- this.assignEventListener
2454
- ));
2455
- const u = new Bi(), f = {
2456
- history: i,
2457
- eventHub: r,
2458
- state: u,
2459
- isContextMenuActive: () => l(this, ct).isActive,
2460
- getSelected: () => l(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) => Re(g, m, this, i),
2470
- assignEventListener: this.assignEventListener,
2471
- closeMarquee: l(this, P).clearMarquee,
2472
- selectionPointerMove: (g, m, w, x, C) => l(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, ht, new Ai(f)), l(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 l(this, y);
2497
- }
2498
- get grid() {
2499
- return l(this, X);
2500
- }
2501
- get history() {
2502
- return l(this, K);
2503
- }
2504
- get eventHub() {
2505
- return l(this, F);
2506
- }
2507
- get pointerEventManager() {
2508
- return l(this, ht);
2509
- }
2510
- get selectionManager() {
2511
- return l(this, P);
2512
- }
2513
- get contextMenuManager() {
2514
- return l(this, ct);
2515
- }
2516
- get canvas() {
2517
- return l(this, W);
2518
- }
2519
- get camera() {
2520
- return l(this, at);
2521
- }
2522
- get isGlobalClick() {
2523
- return l(this, V);
2524
- }
2525
- set isGlobalClick(e) {
2526
- I(this, V, e);
2527
- }
2528
- get basicShapeProgram() {
2529
- return l(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 lt) {
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), l(this, P) && l(this, P).remove([e]), e.destroy(), this.markOrderDirty();
2549
- }
2550
- getChild(e) {
2551
- return this.state.getChild(e);
2552
- }
2553
- updateWorldMatrix() {
2554
- l(this, X).updateWorldMatrix(this.worldMatrix), this.children.forEach((e) => {
2555
- e.updateWorldMatrix(this.worldMatrix);
2556
- }), l(this, P).update();
2557
- }
2558
- render() {
2559
- l(this, y).clearColor(0, 0, 0, 0), l(this, y).clear(l(this, y).COLOR_BUFFER_BIT | l(this, y).DEPTH_BUFFER_BIT), l(this, y).viewport(0, 0, l(this, y).canvas.width, l(this, y).canvas.height);
2560
- const e = this.canvas.parentElement.getBoundingClientRect();
2561
- this.camera.setViewPortDimension(
2562
- e.width,
2563
- e.height
2564
- ), l(this, y).useProgram(l(this, Q));
2565
- const i = l(this, y).getUniformLocation(l(this, Q), "u_z");
2566
- l(this, y).uniform1f(i, 0), l(this, X).render(l(this, y), l(this, Q));
2567
- const r = this.camera.getBoundingBox();
2568
- this.renderList = [];
2569
- for (const n of this.children)
2570
- dt.isColliding(r, n.getBoundingBox()) ? (this.renderList.push(n), n.culled = !1) : n.culled = !0;
2571
- this.renderList.forEach((n) => {
2572
- if (n instanceof xt) {
2573
- const a = n.determineIfLowRes(
2574
- r,
2575
- this.camera.state.zoom
2576
- );
2577
- n.setUseLowRes(a, this.gl);
2578
- }
2579
- });
2580
- for (const n of this.renderList) {
2581
- let a;
2582
- n instanceof xt ? a = l(this, ot) : n instanceof lt && (a = l(this, G)), l(this, y).useProgram(a);
2583
- const o = l(this, y).getUniformLocation(a, "u_z");
2584
- l(this, y).uniform1f(o, n.getZ()), n.render(l(this, y), a);
2585
- }
2586
- l(this, P).render(l(this, G));
2587
- }
2588
- destroy() {
2589
- l(this, y).deleteProgram(l(this, G)), l(this, y).deleteProgram(l(this, ot)), this.children.forEach((e) => {
2590
- "destroy" in e && e.destroy();
2591
- }), this.clearChildren();
2592
- }
2593
- getDOM() {
2594
- return l(this, W);
2595
- }
2596
- assignEventListener(e, i, r) {
2597
- l(this, W).addEventListener(e, i, r);
2598
- }
2599
- hitTest(e, i) {
2600
- return I(this, V, !0), l(this, V);
2601
- }
2602
- async addImageToCanvas(e, i, r, n = 1, a = 1, o = !1) {
2603
- const h = new xt({ x: i, y: r, src: e, sx: n, sy: a });
2604
- if (this.saveImgFileToStorage(e).then((c) => h.fileId = c), o) {
2605
- const c = new Image();
2606
- c.src = e.startsWith("data:image/png") ? e : await Te(e), c.onload = () => {
2607
- const u = c.naturalWidth || c.width || 0, f = c.naturalHeight || c.height || 0;
2608
- (u || f) && h.updateTranslation(-u / 2, -f / 2), h.src = c.src, this.appendChild(h);
2609
- };
2610
- }
2611
- return l(this, F).emit("save"), l(this, F).emit(N.Change), h;
2612
- }
2613
- exportState() {
2614
- return jt(this);
2615
- }
2616
- async importState(e, i) {
2617
- return await Vt(e, this, i);
2618
- }
2619
- clearChildren() {
2620
- this.selectionManager.clear(), this.state.clearChildren(), l(this, K).clear();
2621
- }
2622
- toggleGrid() {
2623
- l(this, X).changeGridType(
2624
- l(this, X).gridType === Tt.GRID ? Tt.NONE : Tt.GRID
2625
- );
2626
- }
2627
- getSelected() {
2628
- return l(this, P).selected;
2629
- }
2630
- setShapeZOrder(e = !0) {
2631
- if (l(this, P).multiBoundingBox || l(this, P).boundingBoxes.size != 1)
2632
- return;
2633
- const i = Array.from(l(this, P).boundingBoxes)[0].target, r = {
2634
- ref: i,
2635
- start: {
2636
- renderOrder: i.renderOrder
2637
- }
2638
- }, n = this.children.map((h) => h.renderOrder);
2639
- if (n.length === 0)
2640
- throw new Error("Order unexpected missing.");
2641
- const a = Math.max(...n), o = Math.min(...n);
2642
- i.renderOrder = e ? a + 1 : o - 1, r.end = {
2643
- renderOrder: i.renderOrder
2644
- }, this.markOrderDirty(), l(this, K).push(Di([r])), l(this, F).emit(N.Change);
2645
- }
2646
- changeMode() {
2647
- l(this, ht).changeMode(), l(this, P).clear();
2648
- }
2649
- updateZoomByFixedAmount(e = 1) {
2650
- l(this, at).updateZoom(
2651
- l(this, W).width / 2,
2652
- l(this, W).height / 2,
2653
- Math.exp(0.5 * 0.3 * e)
2654
- );
2655
- }
2656
- getBoundingClientRect() {
2657
- return l(this, W).getBoundingClientRect();
2658
- }
2659
- wrapWebGLContext(e) {
2660
- const i = e.createTexture.bind(e);
2661
- e.createTexture = () => (R.webglStats.texturesCreated++, console.log(`Textures created: ${R.webglStats.texturesCreated}`), i());
2662
- const r = e.deleteTexture.bind(e);
2663
- e.deleteTexture = (o) => (o && (R.webglStats.texturesDeleted++, console.log(`Textures deleted: ${R.webglStats.texturesDeleted}`)), r(o));
2664
- const n = e.createShader.bind(e);
2665
- e.createShader = (o) => (R.webglStats.shadersCreated++, console.log(`Shaders created: ${R.webglStats.shadersCreated}`), n(o));
2666
- const a = e.deleteShader.bind(e);
2667
- return e.deleteShader = (o) => (o && (R.webglStats.shadersDeleted++, console.log(`Shaders deleted: ${R.webglStats.shadersDeleted}`)), a(o)), e;
2668
- }
2669
- static getWebGLStats() {
2670
- return {
2671
- ...R.webglStats,
2672
- buffersLeaked: R.webglStats.buffersCreated - R.webglStats.buffersDeleted,
2673
- programsLeaked: R.webglStats.programsCreated - R.webglStats.programsDeleted,
2674
- texturesLeaked: R.webglStats.texturesCreated - R.webglStats.texturesDeleted,
2675
- shadersLeaked: R.webglStats.shadersCreated - R.webglStats.shadersDeleted
2676
- };
2677
- }
2678
- };
2679
- W = new WeakMap(), F = new WeakMap(), K = new WeakMap(), at = new WeakMap(), y = new WeakMap(), G = new WeakMap(), ot = new WeakMap(), Q = new WeakMap(), X = new WeakMap(), V = new WeakMap(), P = new WeakMap(), ht = new WeakMap(), Wt = new WeakMap(), ct = new WeakMap(), R.webglStats = {
2680
- buffersCreated: 0,
2681
- buffersDeleted: 0,
2682
- programsCreated: 0,
2683
- programsDeleted: 0,
2684
- texturesCreated: 0,
2685
- texturesDeleted: 0,
2686
- shadersCreated: 0,
2687
- shadersDeleted: 0
2688
- };
2689
- let zt = R;
2690
- const pe = 25;
2691
- class Xi {
2692
- constructor() {
2693
- this._undoStack = [], this._redoStack = [], this._openGroup = null;
2694
- }
2695
- get undoStack() {
2696
- return this._undoStack;
2697
- }
2698
- begin(t) {
2699
- if (this._openGroup) throw new Error("History group already open");
2700
- this._openGroup = [], this._openLabel = t;
2701
- }
2702
- push(t) {
2703
- if (this._openGroup)
2704
- this._openGroup.push(t);
2705
- else {
2706
- for (; this._undoStack.length >= pe; )
2707
- this._undoStack.shift();
2708
- this._undoStack.push([t]), t.do(), this._redoStack.length = 0;
2709
- }
2710
- }
2711
- commit() {
2712
- if (!this._openGroup) return;
2713
- const t = this._openGroup;
2714
- this._openGroup = null;
2715
- for (const e of t) e.do();
2716
- for (; this._undoStack.length >= pe; )
2717
- this._undoStack.shift();
2718
- this._undoStack.push(t), this._redoStack.length = 0, this._openLabel = void 0;
2719
- }
2720
- cancel() {
2721
- this._openGroup = null, this._openLabel = void 0;
2722
- }
2723
- canUndo() {
2724
- return this._undoStack.length > 0;
2725
- }
2726
- canRedo() {
2727
- return this._redoStack.length > 0;
2728
- }
2729
- undo() {
2730
- const t = this._undoStack.pop();
2731
- if (t) {
2732
- for (let e = t.length - 1; e >= 0; e--) t[e].undo();
2733
- this._redoStack.push(t);
2734
- }
2735
- }
2736
- redo() {
2737
- const t = this._redoStack.pop();
2738
- if (t) {
2739
- for (const e of t) e.do();
2740
- this._undoStack.push(t);
2741
- }
2742
- }
2743
- clear() {
2744
- this._undoStack.length = 0, this._redoStack.length = 0, this._openGroup = null, this._openLabel = void 0;
2745
- }
2746
- }
2747
- const Hi = (s) => (t, e) => {
2748
- e !== void 0 ? e.addInitializer((() => {
2749
- customElements.define(s, t);
2750
- })) : customElements.define(s, t);
2751
- };
2752
- const _t = globalThis, Qt = _t.ShadowRoot && (_t.ShadyCSS === void 0 || _t.ShadyCSS.nativeShadow) && "adoptedStyleSheets" in Document.prototype && "replace" in CSSStyleSheet.prototype, Le = Symbol(), xe = /* @__PURE__ */ new WeakMap();
2753
- let Ni = class {
2754
- constructor(t, e, i) {
2755
- if (this._$cssResult$ = !0, i !== Le) throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");
2756
- this.cssText = t, this.t = e;
2757
- }
2758
- get styleSheet() {
2759
- let t = this.o;
2760
- const e = this.t;
2761
- if (Qt && t === void 0) {
2762
- const i = e !== void 0 && e.length === 1;
2763
- i && (t = xe.get(e)), t === void 0 && ((this.o = t = new CSSStyleSheet()).replaceSync(this.cssText), i && xe.set(e, t));
2764
- }
2765
- return t;
2766
- }
2767
- toString() {
2768
- return this.cssText;
2769
- }
2770
- };
2771
- const Yi = (s) => new Ni(typeof s == "string" ? s : s + "", void 0, Le), $i = (s, t) => {
2772
- if (Qt) s.adoptedStyleSheets = t.map(((e) => e instanceof CSSStyleSheet ? e : e.styleSheet));
2773
- else for (const e of t) {
2774
- const i = document.createElement("style"), r = _t.litNonce;
2775
- r !== void 0 && i.setAttribute("nonce", r), i.textContent = e.cssText, s.appendChild(i);
2776
- }
2777
- }, ye = Qt ? (s) => s : (s) => s instanceof CSSStyleSheet ? ((t) => {
2778
- let e = "";
2779
- for (const i of t.cssRules) e += i.cssText;
2780
- return Yi(e);
2781
- })(s) : s;
2782
- const { is: ji, defineProperty: Vi, getOwnPropertyDescriptor: Zi, getOwnPropertyNames: qi, getOwnPropertySymbols: Ki, getPrototypeOf: Qi } = Object, Ft = globalThis, we = Ft.trustedTypes, Ji = we ? we.emptyScript : "", ts = Ft.reactiveElementPolyfillSupport, yt = (s, t) => s, Zt = { toAttribute(s, t) {
2783
- switch (t) {
2784
- case Boolean:
2785
- s = s ? Ji : null;
2786
- break;
2787
- case Object:
2788
- case Array:
2789
- s = s == null ? s : JSON.stringify(s);
2790
- }
2791
- return s;
2792
- }, fromAttribute(s, t) {
2793
- let e = s;
2794
- switch (t) {
2795
- case Boolean:
2796
- e = s !== null;
2797
- break;
2798
- case Number:
2799
- e = s === null ? null : Number(s);
2800
- break;
2801
- case Object:
2802
- case Array:
2803
- try {
2804
- e = JSON.parse(s);
2805
- } catch {
2806
- e = null;
2807
- }
2808
- }
2809
- return e;
2810
- } }, De = (s, t) => !ji(s, t), ve = { attribute: !0, type: String, converter: Zt, reflect: !1, useDefault: !1, hasChanged: De };
2811
- Symbol.metadata ??= Symbol("metadata"), Ft.litPropertyMetadata ??= /* @__PURE__ */ new WeakMap();
2812
- class ut extends HTMLElement {
2813
- static addInitializer(t) {
2814
- this._$Ei(), (this.l ??= []).push(t);
2815
- }
2816
- static get observedAttributes() {
2817
- return this.finalize(), this._$Eh && [...this._$Eh.keys()];
2818
- }
2819
- static createProperty(t, e = ve) {
2820
- 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) {
2821
- const i = Symbol(), r = this.getPropertyDescriptor(t, i, e);
2822
- r !== void 0 && Vi(this.prototype, t, r);
2823
- }
2824
- }
2825
- static getPropertyDescriptor(t, e, i) {
2826
- const { get: r, set: n } = Zi(this.prototype, t) ?? { get() {
2827
- return this[e];
2828
- }, set(a) {
2829
- this[e] = a;
2830
- } };
2831
- return { get: r, set(a) {
2832
- const o = r?.call(this);
2833
- n?.call(this, a), this.requestUpdate(t, o, i);
2834
- }, configurable: !0, enumerable: !0 };
2835
- }
2836
- static getPropertyOptions(t) {
2837
- return this.elementProperties.get(t) ?? ve;
2838
- }
2839
- static _$Ei() {
2840
- if (this.hasOwnProperty(yt("elementProperties"))) return;
2841
- const t = Qi(this);
2842
- t.finalize(), t.l !== void 0 && (this.l = [...t.l]), this.elementProperties = new Map(t.elementProperties);
2843
- }
2844
- static finalize() {
2845
- if (this.hasOwnProperty(yt("finalized"))) return;
2846
- if (this.finalized = !0, this._$Ei(), this.hasOwnProperty(yt("properties"))) {
2847
- const e = this.properties, i = [...qi(e), ...Ki(e)];
2848
- for (const r of i) this.createProperty(r, e[r]);
2849
- }
2850
- const t = this[Symbol.metadata];
2851
- if (t !== null) {
2852
- const e = litPropertyMetadata.get(t);
2853
- if (e !== void 0) for (const [i, r] of e) this.elementProperties.set(i, r);
2854
- }
2855
- this._$Eh = /* @__PURE__ */ new Map();
2856
- for (const [e, i] of this.elementProperties) {
2857
- const r = this._$Eu(e, i);
2858
- r !== void 0 && this._$Eh.set(r, e);
2859
- }
2860
- this.elementStyles = this.finalizeStyles(this.styles);
2861
- }
2862
- static finalizeStyles(t) {
2863
- const e = [];
2864
- if (Array.isArray(t)) {
2865
- const i = new Set(t.flat(1 / 0).reverse());
2866
- for (const r of i) e.unshift(ye(r));
2867
- } else t !== void 0 && e.push(ye(t));
2868
- return e;
2869
- }
2870
- static _$Eu(t, e) {
2871
- const i = e.attribute;
2872
- return i === !1 ? void 0 : typeof i == "string" ? i : typeof t == "string" ? t.toLowerCase() : void 0;
2873
- }
2874
- constructor() {
2875
- super(), this._$Ep = void 0, this.isUpdatePending = !1, this.hasUpdated = !1, this._$Em = null, this._$Ev();
2876
- }
2877
- _$Ev() {
2878
- this._$ES = new Promise(((t) => this.enableUpdating = t)), this._$AL = /* @__PURE__ */ new Map(), this._$E_(), this.requestUpdate(), this.constructor.l?.forEach(((t) => t(this)));
2879
- }
2880
- addController(t) {
2881
- (this._$EO ??= /* @__PURE__ */ new Set()).add(t), this.renderRoot !== void 0 && this.isConnected && t.hostConnected?.();
2882
- }
2883
- removeController(t) {
2884
- this._$EO?.delete(t);
2885
- }
2886
- _$E_() {
2887
- const t = /* @__PURE__ */ new Map(), e = this.constructor.elementProperties;
2888
- for (const i of e.keys()) this.hasOwnProperty(i) && (t.set(i, this[i]), delete this[i]);
2889
- t.size > 0 && (this._$Ep = t);
2890
- }
2891
- createRenderRoot() {
2892
- const t = this.shadowRoot ?? this.attachShadow(this.constructor.shadowRootOptions);
2893
- return $i(t, this.constructor.elementStyles), t;
2894
- }
2895
- connectedCallback() {
2896
- this.renderRoot ??= this.createRenderRoot(), this.enableUpdating(!0), this._$EO?.forEach(((t) => t.hostConnected?.()));
2897
- }
2898
- enableUpdating(t) {
2899
- }
2900
- disconnectedCallback() {
2901
- this._$EO?.forEach(((t) => t.hostDisconnected?.()));
2902
- }
2903
- attributeChangedCallback(t, e, i) {
2904
- this._$AK(t, i);
2905
- }
2906
- _$ET(t, e) {
2907
- const i = this.constructor.elementProperties.get(t), r = this.constructor._$Eu(t, i);
2908
- if (r !== void 0 && i.reflect === !0) {
2909
- const n = (i.converter?.toAttribute !== void 0 ? i.converter : Zt).toAttribute(e, i.type);
2910
- this._$Em = t, n == null ? this.removeAttribute(r) : this.setAttribute(r, n), this._$Em = null;
2911
- }
2912
- }
2913
- _$AK(t, e) {
2914
- const i = this.constructor, r = i._$Eh.get(t);
2915
- if (r !== void 0 && this._$Em !== r) {
2916
- const n = i.getPropertyOptions(r), a = typeof n.converter == "function" ? { fromAttribute: n.converter } : n.converter?.fromAttribute !== void 0 ? n.converter : Zt;
2917
- this._$Em = r;
2918
- const o = a.fromAttribute(e, n.type);
2919
- this[r] = o ?? this._$Ej?.get(r) ?? o, this._$Em = null;
2920
- }
2921
- }
2922
- requestUpdate(t, e, i) {
2923
- if (t !== void 0) {
2924
- const r = this.constructor, n = this[t];
2925
- if (i ??= r.getPropertyOptions(t), !((i.hasChanged ?? De)(n, e) || i.useDefault && i.reflect && n === this._$Ej?.get(t) && !this.hasAttribute(r._$Eu(t, i)))) return;
2926
- this.C(t, e, i);
2927
- }
2928
- this.isUpdatePending === !1 && (this._$ES = this._$EP());
2929
- }
2930
- C(t, e, { useDefault: i, reflect: r, wrapped: n }, a) {
2931
- 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));
2932
- }
2933
- async _$EP() {
2934
- this.isUpdatePending = !0;
2935
- try {
2936
- await this._$ES;
2937
- } catch (e) {
2938
- Promise.reject(e);
2939
- }
2940
- const t = this.scheduleUpdate();
2941
- return t != null && await t, !this.isUpdatePending;
2942
- }
2943
- scheduleUpdate() {
2944
- return this.performUpdate();
2945
- }
2946
- performUpdate() {
2947
- if (!this.isUpdatePending) return;
2948
- if (!this.hasUpdated) {
2949
- if (this.renderRoot ??= this.createRenderRoot(), this._$Ep) {
2950
- for (const [r, n] of this._$Ep) this[r] = n;
2951
- this._$Ep = void 0;
2952
- }
2953
- const i = this.constructor.elementProperties;
2954
- if (i.size > 0) for (const [r, n] of i) {
2955
- const { wrapped: a } = n, o = this[r];
2956
- a !== !0 || this._$AL.has(r) || o === void 0 || this.C(r, void 0, n, o);
2957
- }
2958
- }
2959
- let t = !1;
2960
- const e = this._$AL;
2961
- try {
2962
- t = this.shouldUpdate(e), t ? (this.willUpdate(e), this._$EO?.forEach(((i) => i.hostUpdate?.())), this.update(e)) : this._$EM();
2963
- } catch (i) {
2964
- throw t = !1, this._$EM(), i;
2965
- }
2966
- t && this._$AE(e);
2967
- }
2968
- willUpdate(t) {
2969
- }
2970
- _$AE(t) {
2971
- this._$EO?.forEach(((e) => e.hostUpdated?.())), this.hasUpdated || (this.hasUpdated = !0, this.firstUpdated(t)), this.updated(t);
2972
- }
2973
- _$EM() {
2974
- this._$AL = /* @__PURE__ */ new Map(), this.isUpdatePending = !1;
2975
- }
2976
- get updateComplete() {
2977
- return this.getUpdateComplete();
2978
- }
2979
- getUpdateComplete() {
2980
- return this._$ES;
2981
- }
2982
- shouldUpdate(t) {
2983
- return !0;
2984
- }
2985
- update(t) {
2986
- this._$Eq &&= this._$Eq.forEach(((e) => this._$ET(e, this[e]))), this._$EM();
2987
- }
2988
- updated(t) {
2989
- }
2990
- firstUpdated(t) {
2991
- }
2992
- }
2993
- ut.elementStyles = [], ut.shadowRootOptions = { mode: "open" }, ut[yt("elementProperties")] = /* @__PURE__ */ new Map(), ut[yt("finalized")] = /* @__PURE__ */ new Map(), ts?.({ ReactiveElement: ut }), (Ft.reactiveElementVersions ??= []).push("2.1.1");
2994
- class Be {
2995
- constructor(t, e) {
2996
- this.options = [], this.rootNode = e, this._el = document.createElement("div"), this._el.classList.add("context-menu"), t.options.forEach((i, r) => {
2997
- this.createOptionGroup(i), r !== t.options.length - 1 && this.addDivider();
2998
- }), this._el.addEventListener("contextmenu", (i) => {
2999
- i.preventDefault();
3000
- });
3001
- }
3002
- get el() {
3003
- return this._el;
3004
- }
3005
- attachToParent(t) {
3006
- t.appendChild(this.el);
3007
- }
3008
- createOptionGroup(t) {
3009
- const e = new es(t, this.rootNode);
3010
- this.options.push(e), this.el.appendChild(e.el);
3011
- }
3012
- addDivider() {
3013
- const t = document.createElement("hr");
3014
- t.classList.add("context-menu-divider"), this.el.appendChild(t);
3015
- }
3016
- }
3017
- class es {
3018
- constructor(t, e) {
3019
- this.childOptions = [], this.rootNode = e, this._el = document.createElement("div"), this.createOptionElement = this.createOptionElement.bind(this), t.childOptions.forEach((i) => this.createOptionElement(i));
3020
- }
3021
- get el() {
3022
- return this._el;
3023
- }
3024
- attachToParent(t) {
3025
- t.appendChild(this.el);
3026
- }
3027
- createOptionElement(t) {
3028
- t.parent = this;
3029
- const e = new is(t, this.rootNode);
3030
- this.childOptions.push(e);
3031
- }
3032
- }
3033
- class is {
3034
- get el() {
3035
- return this._el;
3036
- }
3037
- constructor(t, e) {
3038
- 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(
3039
- "pointerenter",
3040
- (i) => ss(i, t, this._el, this.rootNode)
3041
- ), this._el.addEventListener("contextmenu", (i) => {
3042
- i.preventDefault();
3043
- });
3044
- }
3045
- }
3046
- function ss(s, t, e, i) {
3047
- if (!i) return;
3048
- const r = i.querySelector(".sub-context-menu");
3049
- if (r && r.remove(), t.subMenu) {
3050
- const n = new Be(t.subMenu, this);
3051
- i.appendChild(n.el), n.el.id = `${t.text}-context-menu`, n.el.classList.add("sub-context-menu");
3052
- const a = i.getBoundingClientRect(), o = e.getBoundingClientRect(), h = n.el.getBoundingClientRect(), c = a.right - a.left, u = a.bottom - a.top, f = o.right + h.width;
3053
- o.top + h.height > u ? n._el.style.top = `${o.bottom - h.height}px` : n._el.style.top = `${o.top}px`, f > c ? n._el.style.left = `${o.left - h.width}px` : n._el.style.left = `${o.right}px`;
3054
- }
3055
- }
3056
- const Ct = 5;
3057
- function Gt(s) {
3058
- const t = this;
3059
- return function(...e) {
3060
- const i = s.apply(t, e);
3061
- return t.clearContextMenu(), i;
3062
- };
3063
- }
3064
- function rs(s, t, e = "single") {
3065
- const i = new Be(
3066
- e === "single" ? this.singleImageMenuOptions : e === "multi" ? this.multiImageMenuOptions : this.canvasImageMenuOptions,
3067
- this.rootDiv
3068
- );
3069
- if (!this.rootDiv) {
3070
- console.error("Can't add to parent div");
3071
- return;
3072
- }
3073
- i.attachToParent(this.rootDiv);
3074
- 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(), u = [
3075
- n + c.width > o ? 1 : 0,
3076
- a + c.height > h ? 1 : 0
3077
- ], f = c.height * u[1], g = c.width * u[0];
3078
- if (f > h) {
3079
- const m = h - 2 * Ct;
3080
- i._el.style.height = `${m}px`, i._el.style.top = `${Ct}px`;
3081
- } else
3082
- i._el.style.top = `${a - f}px`;
3083
- g > o ? (i._el.style.width = `${o - 2 * Ct}px`, i._el.style.left = `${Ct}px`) : i._el.style.left = `${n - g}px`;
3084
- }
3085
- function ns() {
3086
- const s = this.renderRoot.querySelector(".context-menu");
3087
- s && (s.remove(), this.eventHub.emit(H.Close));
3088
- }
3089
- function as() {
3090
- return this.renderRoot.querySelector(".context-menu") !== null;
3091
- }
3092
- function os() {
3093
- const s = Gt.bind(this);
3094
- return {
3095
- options: [
3096
- {
3097
- childOptions: [
3098
- {
3099
- text: "Cut",
3100
- onClick: async () => {
3101
- await this.copyImage.bind(this)(), s(this.deleteSelectedImages.bind(this))();
3102
- }
3103
- },
3104
- {
3105
- text: "Copy",
3106
- onClick: s(this.copyImage.bind(this))
3107
- },
3108
- {
3109
- text: "Paste",
3110
- onClick: (t) => s(this.pasteImage.bind(this))(t)
3111
- },
3112
- {
3113
- text: "Delete",
3114
- onClick: s(this.deleteSelectedImages.bind(this))
3115
- }
3116
- ]
3117
- },
3118
- {
3119
- childOptions: [
3120
- {
3121
- text: "Flip Horizontal",
3122
- onClick: s(this.flipHorizontal.bind(this))
3123
- },
3124
- {
3125
- text: "Flip Vertical",
3126
- onClick: s(this.flipVertical.bind(this))
3127
- }
3128
- ]
3129
- }
3130
- ]
3131
- };
3132
- }
3133
- function hs(s) {
3134
- const t = Gt.bind(this);
3135
- return {
3136
- options: [
3137
- ...s ?? [],
3138
- {
3139
- childOptions: [
3140
- {
3141
- text: "Send to Front",
3142
- onClick: () => t(this.sendShapeToNewZOrder.bind(this))(!0)
3143
- },
3144
- {
3145
- text: "Send to Back",
3146
- onClick: () => t(this.sendShapeToNewZOrder.bind(this))(!1)
3147
- }
3148
- ]
3149
- }
3150
- ]
3151
- };
3152
- }
3153
- function cs(s) {
3154
- const t = Gt.bind(this);
3155
- return {
3156
- options: [
3157
- ...s ?? [],
3158
- {
3159
- childOptions: [
3160
- {
3161
- text: "Align",
3162
- onHover: () => {
3163
- },
3164
- subMenu: {
3165
- options: [
3166
- {
3167
- childOptions: [
3168
- {
3169
- text: "Align Left",
3170
- onClick: () => t(this.align.bind(this))("left")
3171
- },
3172
- {
3173
- text: "Align Right",
3174
- onClick: () => t(this.align.bind(this))("right")
3175
- },
3176
- {
3177
- text: "Align Top",
3178
- onClick: () => t(this.align.bind(this))("top")
3179
- },
3180
- {
3181
- text: "Align Bottom",
3182
- onClick: () => t(this.align.bind(this))("bottom")
3183
- }
3184
- ]
3185
- }
3186
- ]
3187
- }
3188
- },
3189
- {
3190
- text: "Normalize by First",
3191
- onHover: () => {
3192
- },
3193
- subMenu: {
3194
- options: [
3195
- {
3196
- childOptions: [
3197
- {
3198
- text: "Height",
3199
- onClick: () => t(this.normalizeSelection.bind(this))(
3200
- "height",
3201
- "first"
3202
- )
3203
- },
3204
- {
3205
- text: "Width",
3206
- onClick: () => t(this.normalizeSelection.bind(this))(
3207
- "width",
3208
- "first"
3209
- )
3210
- },
3211
- {
3212
- text: "Size",
3213
- onClick: () => t(this.normalizeSelection.bind(this))(
3214
- "size",
3215
- "first"
3216
- )
3217
- },
3218
- {
3219
- text: "Scale",
3220
- onClick: () => t(this.normalizeSelection.bind(this))(
3221
- "scale",
3222
- "first"
3223
- )
3224
- }
3225
- ]
3226
- }
3227
- ]
3228
- }
3229
- },
3230
- {
3231
- text: "Normalize by Average",
3232
- onHover: () => {
3233
- },
3234
- subMenu: {
3235
- options: [
3236
- {
3237
- childOptions: [
3238
- {
3239
- text: "Height",
3240
- onClick: () => t(this.normalizeSelection.bind(this))(
3241
- "height",
3242
- "average"
3243
- )
3244
- },
3245
- {
3246
- text: "Width",
3247
- onClick: () => t(this.normalizeSelection.bind(this))(
3248
- "width",
3249
- "average"
3250
- )
3251
- },
3252
- {
3253
- text: "Size",
3254
- onClick: () => t(this.normalizeSelection.bind(this))(
3255
- "size",
3256
- "average"
3257
- )
3258
- },
3259
- {
3260
- text: "Scale",
3261
- onClick: () => t(this.normalizeSelection.bind(this))(
3262
- "scale",
3263
- "average"
3264
- )
3265
- }
3266
- ]
3267
- }
3268
- ]
3269
- }
3270
- }
3271
- ]
3272
- }
3273
- ]
3274
- };
3275
- }
3276
- function ds(s) {
3277
- const t = Gt.bind(this);
3278
- return {
3279
- options: [
3280
- ...s ?? [],
3281
- {
3282
- childOptions: [
3283
- {
3284
- text: "Change mode",
3285
- onClick: () => t(this.togglePointerMode.bind(this))()
3286
- },
3287
- {
3288
- text: "Toggle Grid",
3289
- onClick: () => t(this.toggleGrid.bind(this))()
3290
- }
3291
- ]
3292
- },
3293
- {
3294
- childOptions: [
3295
- {
3296
- text: "Save",
3297
- onClick: () => t(this.saveToCanvasStorage.bind(this))()
3298
- },
3299
- {
3300
- text: "Paste",
3301
- onClick: (e) => t(this.pasteImage.bind(this))(e)
3302
- }
3303
- ]
3304
- }
3305
- ]
3306
- };
3307
- }
3308
- class Jt {
3309
- _touch() {
3310
- this._lastRetrieved = Date.now();
3311
- }
3312
- get id() {
3313
- return this._touch(), this._id;
3314
- }
3315
- get dataURL() {
3316
- return this._touch(), this._dataURL;
3317
- }
3318
- get mimetype() {
3319
- return this._touch(), this._mimetype;
3320
- }
3321
- get created() {
3322
- return this._touch(), this._created;
3323
- }
3324
- get lastRetrieved() {
3325
- return this._lastRetrieved;
3326
- }
3327
- constructor(t) {
3328
- this._dataURL = t, this._mimetype = di(t), this._created = Date.now(), this._lastRetrieved = Date.now();
3329
- }
3330
- static async create(t) {
3331
- const e = new Jt(t);
3332
- return e._id = await Kt(t), e;
3333
- }
3334
- }
3335
- class ls {
3336
- }
3337
- class us {
3338
- }
3339
- function ze(s) {
3340
- s.Version.prototype._parseStoresSpec = Y.override(
3341
- s.Version.prototype._parseStoresSpec,
3342
- fs
3343
- ), s.open = Y.override(s.open, gs(s));
3344
- }
3345
- function fs(s) {
3346
- return function(t, e) {
3347
- s.call(this, t, e), Object.keys(e).forEach(function(i) {
3348
- let r = e[i];
3349
- 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));
3350
- });
3351
- };
3352
- }
3353
- function ms(s) {
3354
- return function(e, i) {
3355
- let r;
3356
- return e === void 0 && s.schema.primKey.uuid && (e = r = ei(), s.schema.primKey.keyPath && Y.setByKeyPath(i, s.schema.primKey.keyPath, e)), r;
3357
- };
3358
- }
3359
- function gs(s) {
3360
- return function(e) {
3361
- return function() {
3362
- return Object.keys(s._allTables).forEach((i) => {
3363
- let r = s._allTables[i];
3364
- r.hook("creating").subscribe(ms(r));
3365
- }), e.apply(this, arguments);
3366
- };
3367
- };
3368
- }
3369
- Y.UUIDPrimaryKey = ze;
3370
- Y.addons.push(ze);
3371
- Y.UUIDPrimaryKey;
3372
- const ps = {
3373
- files: "$$id, mimetype, created, lastRetrieved"
3374
- }, be = {
3375
- MAX_IMAGE_ENTRIES: 1e3
3376
- };
3377
- class St extends ls {
3378
- constructor() {
3379
- super(), this.dbQueue = new Se(), this.cache = /* @__PURE__ */ new Map(), this.CACHE_LIMIT = 500, this.dbQueue = new Se(), this.dbPromise = this.initDb();
3380
- }
3381
- async initDb() {
3382
- return $(async () => {
3383
- let t = new Y("InfiniteCanvas");
3384
- return Y.UUIDPrimaryKey(t), t.version(1).stores(ps), await t.open(), t;
3385
- });
3386
- }
3387
- async getIndexDb() {
3388
- return this.dbPromise;
3389
- }
3390
- /**
3391
- * Writes to indexedDB
3392
- * @param data
3393
- * @param mimetype
3394
- * @returns the file ID
3395
- */
3396
- async write(t) {
3397
- const e = await Jt.create(t), i = ws(e.dataURL);
3398
- return this.dbQueue.add(
3399
- () => $(async () => {
3400
- const r = await this.getIndexDb();
3401
- return await r.transaction("rw", r.files, async () => (await ys(r), await r.files.add({
3402
- id: e.id,
3403
- blob: i,
3404
- dataURL: e.dataURL,
3405
- mimetype: e.mimetype,
3406
- created: e.created,
3407
- lastRetrieved: e.lastRetrieved
3408
- }))).catch((n) => {
3409
- throw console.error("Failed to save image blob to local DB:", n), n;
3410
- });
3411
- })
3412
- );
3413
- }
3414
- async readAll() {
3415
- return $(async () => await (await this.getIndexDb()).files.toArray());
3416
- }
3417
- async readPage(t, e) {
3418
- return $(async () => await (await this.getIndexDb()).files.offset(t).limit(e).toArray());
3419
- }
3420
- async read(t) {
3421
- return $(async () => {
3422
- const e = await this.getIndexDb();
3423
- if (this.cache.has(t))
3424
- return this.cache.get(t);
3425
- const i = await e.files.get(t);
3426
- if (!i) return null;
3427
- if (this.dbQueue.add(async () => {
3428
- try {
3429
- await e.files.update(t, { lastRetrieved: Date.now() });
3430
- } catch (r) {
3431
- console.error("Failed to update lastRetrieved", r);
3432
- }
3433
- }).catch(() => {
3434
- }), this.cache.set(t, i), this.cache.size > this.CACHE_LIMIT) {
3435
- const r = this.cache.keys().next().value;
3436
- this.cache.delete(r);
3437
- }
3438
- return i;
3439
- });
3440
- }
3441
- async delete(t) {
3442
- return this.dbQueue.add(
3443
- () => $(async () => {
3444
- const e = await this.getIndexDb();
3445
- return await e.transaction("rw", e.files, async () => {
3446
- const i = await e.files.where("id").equals(t).first();
3447
- return await e.files.delete(i.id), i;
3448
- }).catch((i) => {
3449
- throw console.error("Failed to save image blob to local DB:", i), i;
3450
- });
3451
- })
3452
- );
3453
- }
3454
- async update(t) {
3455
- return this.dbQueue.add(
3456
- () => $(async () => {
3457
- const e = await this.getIndexDb();
3458
- return await e.transaction("rw", e.files, async () => {
3459
- await e.files.update(t.id, {
3460
- dataURL: t.dataURL,
3461
- mimetype: t.mimetype,
3462
- lastRetrieved: Date.now()
3463
- });
3464
- }), await e.files.where("id").equals(t.id).first();
3465
- })
3466
- );
3467
- }
3468
- async checkIfImageStored(t) {
3469
- return $(async () => {
3470
- const i = await (await this.getIndexDb()).files.where("id").equals(t).first();
3471
- return i ? i.id : null;
3472
- });
3473
- }
3474
- }
3475
- class Yt extends us {
3476
- constructor(t) {
3477
- super(), this.key = "infinite_canvas", this.key = t;
3478
- }
3479
- async write(t) {
3480
- return new Promise((e, i) => {
3481
- try {
3482
- localStorage.setItem(this.key, JSON.stringify(t)), e();
3483
- } catch (r) {
3484
- i(r);
3485
- }
3486
- });
3487
- }
3488
- async read() {
3489
- return new Promise((t, e) => {
3490
- try {
3491
- t(localStorage.getItem(this.key));
3492
- } catch (i) {
3493
- e(i);
3494
- }
3495
- });
3496
- }
3497
- async delete() {
3498
- return new Promise((t, e) => {
3499
- try {
3500
- localStorage.removeItem(this.key), t();
3501
- } catch (i) {
3502
- e(i);
3503
- }
3504
- });
3505
- }
3506
- async update(t) {
3507
- return this.write(t);
3508
- }
3509
- }
3510
- class Ce extends Error {
3511
- constructor(t) {
3512
- super(t), this.name = "QuotaExceededError";
3513
- }
3514
- }
3515
- class xs extends Error {
3516
- constructor(t) {
3517
- super(t), this.name = "DatabaseLimitError";
3518
- }
3519
- }
3520
- class Se {
3521
- constructor() {
3522
- this.queue = Promise.resolve();
3523
- }
3524
- async add(t) {
3525
- const e = this.queue.then(() => t());
3526
- return this.queue = e.catch(() => {
3527
- }), e;
3528
- }
3529
- }
3530
- const $ = async (s) => {
3531
- try {
3532
- return await s();
3533
- } catch (t) {
3534
- throw t instanceof DOMException && t.name === "QuotaExceededError" ? new Ce(
3535
- "Storage quota exceeded. Please free up space."
3536
- ) : t instanceof Y.QuotaExceededError ? new Ce(
3537
- "Database quota exceeded. Please free up space."
3538
- ) : t;
3539
- }
3540
- };
3541
- async function ys(s) {
3542
- if (await s.files.count() >= be.MAX_IMAGE_ENTRIES)
3543
- throw new xs(
3544
- `Cannot save image: limit of ${be.MAX_IMAGE_ENTRIES} reached`
3545
- );
3546
- }
3547
- function ws(s) {
3548
- 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);
3549
- for (let c = 0; c < o; c++)
3550
- h[c] = a.charCodeAt(c);
3551
- return new Blob([h], { type: n });
3552
- }
3553
- class vs {
3554
- get el() {
3555
- return this._el;
3556
- }
3557
- constructor(t) {
3558
- this.type = t.type, this.message = t.message, this._el = document.createElement("div"), this._el.classList.add("canvas-loader"), this.render();
3559
- }
3560
- render() {
3561
- if (this._el.innerHTML = "", this.type === "spinner") {
3562
- const t = document.createElement("div");
3563
- if (t.classList.add("canvas-loader-spinner"), this._el.appendChild(t), this.message) {
3564
- const e = document.createElement("div");
3565
- e.classList.add("canvas-loader-message"), e.textContent = this.message, this._el.appendChild(e);
3566
- }
3567
- } else if (this.type === "message") {
3568
- const t = document.createElement("div");
3569
- t.classList.add("canvas-loader-message"), t.textContent = this.message ?? "", this._el.appendChild(t);
3570
- }
3571
- }
3572
- setMessage(t) {
3573
- this.message = t, this.render();
3574
- }
3575
- setProgress(t) {
3576
- this.progress = t, this.render();
3577
- }
3578
- attachToParent(t) {
3579
- t.appendChild(this.el);
3580
- }
3581
- remove() {
3582
- this._el.parentNode && this._el.parentNode.removeChild(this._el);
3583
- }
3584
- }
3585
- function bs(s, t) {
3586
- const e = new vs({ type: s, message: t });
3587
- e.attachToParent(this.renderRoot);
3588
- const i = this.getBoundingClientRect();
3589
- return e.el.style.width = `${i.right}px`, e.el.style.height = `${i.bottom}px`, e._el.style.top = `${-i.bottom}px`, e;
3590
- }
3591
- function Cs() {
3592
- const s = this.renderRoot.querySelector(".canvas-loader");
3593
- s && s.remove();
3594
- }
3595
- var Ss = Object.getOwnPropertyDescriptor, ke = (s) => {
3596
- throw TypeError(s);
3597
- }, Ms = (s, t, e, i) => {
3598
- for (var r = i > 1 ? void 0 : i ? Ss(t, e) : t, n = s.length - 1, a; n >= 0; n--)
3599
- (a = s[n]) && (r = a(r) || r);
3600
- return r;
3601
- }, Ue = (s, t, e) => t.has(s) || ke("Cannot " + e), d = (s, t, e) => (Ue(s, t, "read from private field"), e ? e.call(s) : t.get(s)), D = (s, t, e) => t.has(s) ? ke("Cannot add the same private member more than once") : t instanceof WeakSet ? t.add(s) : t.set(s, e), E = (s, t, e, i) => (Ue(s, t, "write to private field"), t.set(s, e), e), p, _, Rt, j, O, k, mt, It, gt, q, rt, Pt, At, Ot;
3602
- let kt = class extends ti {
3603
- constructor() {
3604
- super(...arguments), this.name = "Reffy", this.displayMode = "fullscreen", D(this, p), D(this, _), D(this, Rt), D(this, j), D(this, O), D(this, k), D(this, mt, 3e5), D(this, It), D(this, gt), D(this, q), D(this, rt), D(this, Pt), D(this, At), D(this, Ot), this.handleGlobalPointerDown = (s) => {
3605
- !this.contains(s.target) && !this.renderRoot.contains(s.target) && this.clearContextMenu();
3606
- };
3607
- }
3608
- get singleImageMenuOptions() {
3609
- return d(this, Pt);
3610
- }
3611
- get multiImageMenuOptions() {
3612
- return d(this, At);
3613
- }
3614
- get canvasImageMenuOptions() {
3615
- return d(this, Ot);
3616
- }
3617
- get canvas() {
3618
- return d(this, p);
3619
- }
3620
- get onCanvasChange() {
3621
- return d(this, rt);
3622
- }
3623
- set onCanvasChange(s) {
3624
- E(this, rt, s);
3625
- }
3626
- get eventHub() {
3627
- return d(this, _);
3628
- }
3629
- get rootDiv() {
3630
- return d(this, q);
3631
- }
3632
- // Lifecycle
3633
- connectedCallback() {
3634
- super.connectedCallback(), this.handleGlobalPointerDown = this.handleGlobalPointerDown.bind(this), document.addEventListener(
3635
- "pointerdown",
3636
- this.handleGlobalPointerDown,
3637
- !0
3638
- );
3639
- }
3640
- disconnectedCallback() {
3641
- document.removeEventListener(
3642
- "pointerdown",
3643
- this.handleGlobalPointerDown,
3644
- !0
3645
- ), d(this, Rt)?.disconnect(), E(this, Rt, void 0), d(this, p).destroy(), super.disconnectedCallback();
3646
- }
3647
- firstUpdated(s) {
3648
- try {
3649
- this.initCanvas();
3650
- } catch (t) {
3651
- throw console.error(t), t;
3652
- }
3653
- }
3654
- updated(s) {
3655
- if (!(s.has("width") || s.has("height") || s.has("displayMode"))) return;
3656
- const e = d(this, q), i = this.renderRoot.querySelector(
3657
- "canvas"
3658
- );
3659
- e && i && this.resizeCanvas(e, i);
3660
- }
3661
- async initCanvas() {
3662
- await this.warmUpStorage(), E(this, j, new Xi()), E(this, _, new ii());
3663
- const s = document.createElement("div");
3664
- s.style.overflow = "hidden", this.renderRoot.appendChild(s), E(this, q, s);
3665
- const t = document.createElement("canvas");
3666
- 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 = rs.bind(this), this.clearContextMenu = ns.bind(this), this.isContextMenuActive = as.bind(this), this.getContainerSize = this.getContainerSize.bind(this), s.contains(t) || s.appendChild(t), this.registerSignal(), E(this, p, new zt(
3667
- t,
3668
- d(this, j),
3669
- d(this, _),
3670
- this.debounceSaveToCanvasStorage,
3671
- this.saveImageFileMetadata,
3672
- this.getContainerSize
3673
- ));
3674
- try {
3675
- await this.restoreStateFromCanvasStorage();
3676
- } catch {
3677
- console.error("Failed to restore canvas");
3678
- }
3679
- this.resizeCanvas(s, t);
3680
- const e = os.bind(this)();
3681
- E(this, Pt, hs.bind(this)(
3682
- e.options
3683
- )), E(this, Ot, ds.bind(this)()), E(this, At, cs.bind(this)(
3684
- e.options
3685
- )), this.dispatchEvent(new Event("load"));
3686
- const i = new si();
3687
- i.showPanel(0), this.renderRoot.contains(i.dom) || this.renderRoot.appendChild(i.dom);
3688
- const r = () => {
3689
- i && i.update(), d(this, p).render(), requestAnimationFrame(r);
3690
- };
3691
- r();
3692
- }
3693
- normalizeCssSize(s) {
3694
- if (!s) return s;
3695
- const t = String(s).trim();
3696
- return /^\d+$/.test(t) ? `${t}px` : t;
3697
- }
3698
- resizeCanvas(s, t) {
3699
- 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";
3700
- const e = window.devicePixelRatio || 1;
3701
- let i = window.screen.width, r = window.screen.height;
3702
- const n = Math.round(i * e), a = Math.round(r * e);
3703
- (t.width !== n || t.height !== a) && (t.width = n, t.height = a), t.style.width = `${i}px`, t.style.height = `${r}px`;
3704
- const o = s.getBoundingClientRect();
3705
- this.canvas.camera.viewportX = o.x, this.canvas.camera.viewportY = o.y, this.canvas.camera.state.setHeight(o.height), this.canvas.camera.state.setWidth(o.width);
3706
- }
3707
- // Register signal
3708
- registerSignal() {
3709
- d(this, _).on(tt.start, bs.bind(this), "spinner"), d(this, _).on(tt.done, Cs.bind(this)), d(this, _).on(H.Open, this.addContextMenu), d(this, _).on(H.Close, this.clearContextMenu), d(this, _).on(N.Change, () => {
3710
- d(this, rt) && d(this, rt).call(this);
3711
- }), d(this, _).on(et.Save, this.saveToCanvasStorage), d(this, _).on(et.SaveCompleted, () => {
3712
- }), d(this, _).on(
3713
- et.SaveFailed,
3714
- () => console.error("Failed to Save!")
3715
- );
3716
- }
3717
- // need to check if this is good practice
3718
- async warmUpStorage() {
3719
- d(this, O) || E(this, O, new St());
3720
- try {
3721
- await d(this, O).readAll();
3722
- } catch (s) {
3723
- console.error("Storage warm-up failed", s);
3724
- }
3725
- }
3726
- /**
3727
- * @returns An array containing the width and height of the container
3728
- */
3729
- getContainerSize() {
3730
- if (!d(this, q)) return;
3731
- const s = d(this, q).getBoundingClientRect();
3732
- return [s.width, s.height];
3733
- }
3734
- // Storage & Persistence
3735
- /**
3736
- * @param storage Canvas storage stores the positions of all the renderables
3737
- * @param saveFrequency How often should auto save execute
3738
- */
3739
- assignCanvasStorage(s, t = d(this, mt)) {
3740
- E(this, k, s), E(this, mt, t), d(this, gt) && clearInterval(d(this, gt)), E(this, gt, setInterval(
3741
- this.saveToCanvasStorage,
3742
- d(this, mt)
3743
- ));
3744
- }
3745
- /**
3746
- * @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.
3747
- */
3748
- assignFileStorage(s) {
3749
- E(this, O, s);
3750
- }
3751
- /**
3752
- * Duplicate images will not be written to the database
3753
- * @param dataURL
3754
- * @returns The unique ID that the image has been logged with. This is a hashed version of the image data URL
3755
- */
3756
- async saveImageFileMetadata(s) {
3757
- d(this, O) || E(this, O, new St());
3758
- try {
3759
- const t = await Kt(s);
3760
- return await d(this, O).checkIfImageStored(t) ? t : await d(this, O).write(s);
3761
- } catch (t) {
3762
- console.error(t);
3763
- }
3764
- }
3765
- /**
3766
- * @param fileId Retrieves the file metadata
3767
- * @returns
3768
- */
3769
- async getImageFileMetadata(s) {
3770
- d(this, O) || E(this, O, new St());
3771
- try {
3772
- return await d(this, O).read(s);
3773
- } catch (t) {
3774
- console.error(t);
3775
- }
3776
- }
3777
- /**
3778
- * @returns All file metadata saved in connected storage
3779
- */
3780
- async getAllImageFileMetdata() {
3781
- d(this, O) || E(this, O, new St());
3782
- try {
3783
- return await d(this, O).readAll();
3784
- } catch (s) {
3785
- console.error(s);
3786
- }
3787
- }
3788
- /**
3789
- * Schedule the auto save to the canvas storage based on timer
3790
- */
3791
- debounceSaveToCanvasStorage(s = 1e3) {
3792
- d(this, k) || E(this, k, new Yt(this.name)), clearTimeout(d(this, It)), E(this, It, setTimeout(this.saveToCanvasStorage, s));
3793
- }
3794
- async saveToCanvasStorage() {
3795
- d(this, k) || E(this, k, new Yt(this.name)), d(this, k).write(jt(d(this, p))).then(() => d(this, _).emit(et.SaveCompleted)).catch(() => d(this, _).emit(et.SaveFailed));
3796
- }
3797
- async restoreStateFromCanvasStorage() {
3798
- d(this, k) || E(this, k, new Yt(this.name));
3799
- const s = await d(this, k).read(), t = JSON.parse(s);
3800
- t && await Vt(t, d(this, p), this.getImageFileMetadata);
3801
- }
3802
- // Canvas API
3803
- togglePointerMode() {
3804
- d(this, p) && d(this, p).changeMode();
3805
- }
3806
- toggleGrid() {
3807
- d(this, p) && d(this, p).toggleGrid();
3808
- }
3809
- zoomIn() {
3810
- d(this, p) && d(this, p).updateZoomByFixedAmount(-1);
3811
- }
3812
- zoomOut() {
3813
- d(this, p) && d(this, p).updateZoomByFixedAmount();
3814
- }
3815
- async addImages(s) {
3816
- if (!d(this, p)) return;
3817
- const t = d(this, p).getBoundingClientRect(), e = t.left + t.width / 2, i = t.top + t.height / 2, [r, n] = wt(e, i, d(this, p)), a = await li(
3818
- s,
3819
- (o) => d(this, p).addImageToCanvas(o, r, n, 1, 1, !0)
3820
- );
3821
- d(this, j).push(Bt(d(this, p), a));
3822
- }
3823
- async removeImage(s) {
3824
- if (!d(this, p)) return;
3825
- const t = d(this, p).getChild(s);
3826
- d(this, p).removeChild(t), d(this, j).push(gi(d(this, p), t));
3827
- }
3828
- /**
3829
- * @param url Currently only accept base64 url and the image is automatically added to screen center
3830
- */
3831
- async addImageFromUrl(s) {
3832
- if (!d(this, p)) return;
3833
- const t = d(this, p).getBoundingClientRect(), e = t.left + t.width / 2, i = t.top + t.height / 2, [r, n] = wt(e, i, d(this, p)), a = await d(this, p).addImageToCanvas(s, r, n, 1, 1, !0);
3834
- d(this, j).push(Bt(d(this, p), [a]));
3835
- }
3836
- async copyImage() {
3837
- d(this, p) && await _e(d(this, p).getSelected());
3838
- }
3839
- async pasteImage(s) {
3840
- d(this, p) && await Re(s.clientX, s.clientY, d(this, p), d(this, j), !1);
3841
- }
3842
- flipVertical() {
3843
- d(this, p) && d(this, p).selectionManager.flip("vertical");
3844
- }
3845
- flipHorizontal() {
3846
- d(this, p) && d(this, p).selectionManager.flip("horizontal");
3847
- }
3848
- align(s) {
3849
- d(this, p) && d(this, p).selectionManager.alignSelection(s);
3850
- }
3851
- normalizeSelection(s, t) {
3852
- d(this, p) && d(this, p).selectionManager.normalize(s, t);
3853
- }
3854
- sendShapeToNewZOrder(s) {
3855
- d(this, p) && d(this, p).setShapeZOrder(s);
3856
- }
3857
- deleteSelectedImages() {
3858
- d(this, p) && d(this, p).selectionManager.deleteSelected(d(this, p));
3859
- }
3860
- async exportCanvas(s = "infinite-canvas.json") {
3861
- if (!d(this, p)) return;
3862
- d(this, _).emit(tt.start, "spinner");
3863
- const t = await this.getAllImageFileMetdata(), e = jt(d(this, p), t);
3864
- ui(s, e), d(this, _).emit(tt.done);
3865
- }
3866
- async importCanvas(s) {
3867
- if (d(this, _).emit(tt.start, "spinner"), !d(this, p) || !s || s.length !== 1) return;
3868
- const t = s[0];
3869
- if (!t.type || !t.type.includes("json") && !t.name.toLowerCase().endsWith(".json"))
3870
- return;
3871
- const e = await fi(t);
3872
- await Vt(
3873
- e,
3874
- d(this, p),
3875
- this.getImageFileMetadata,
3876
- this.saveImageFileMetadata
3877
- ), d(this, _).emit(et.Save), d(this, _).emit(tt.done);
3878
- }
3879
- clearCanvas() {
3880
- d(this, p) && d(this, p).clearChildren();
3881
- }
3882
- /**
3883
- * A non-reactive method that captures the number of images added to the canvas
3884
- */
3885
- getTotalNumberOfChildren() {
3886
- if (d(this, p))
3887
- return d(this, p).totalNumberOfChildren;
3888
- }
3889
- /**
3890
- * A non-reactive method that captures the number of images that are in camera
3891
- */
3892
- getNumberOfChildrenRendered() {
3893
- if (d(this, p))
3894
- return d(this, p).numberOfChildrenRendered;
3895
- }
3896
- };
3897
- p = /* @__PURE__ */ new WeakMap();
3898
- _ = /* @__PURE__ */ new WeakMap();
3899
- Rt = /* @__PURE__ */ new WeakMap();
3900
- j = /* @__PURE__ */ new WeakMap();
3901
- O = /* @__PURE__ */ new WeakMap();
3902
- k = /* @__PURE__ */ new WeakMap();
3903
- mt = /* @__PURE__ */ new WeakMap();
3904
- It = /* @__PURE__ */ new WeakMap();
3905
- gt = /* @__PURE__ */ new WeakMap();
3906
- q = /* @__PURE__ */ new WeakMap();
3907
- rt = /* @__PURE__ */ new WeakMap();
3908
- Pt = /* @__PURE__ */ new WeakMap();
3909
- At = /* @__PURE__ */ new WeakMap();
3910
- Ot = /* @__PURE__ */ new WeakMap();
3911
- kt.properties = {
3912
- name: { type: String, reflect: !0 },
3913
- width: { type: String, reflect: !0 },
3914
- height: { type: String, reflect: !0 },
3915
- displayMode: { type: String, reflect: !0 }
3916
- };
3917
- kt.styles = Je`
3918
- :host {
3919
- position: relative;
3920
- overflow: hidden;
3921
- }
3922
-
3923
- .context-menu {
3924
- position: absolute;
3925
- background: white;
3926
- min-width: 180px;
3927
- background: var(--menu-bg, #fff);
3928
- border-radius: 6px;
3929
- border: 1px solid var(--menu-border, #9f9f9fff);
3930
- box-sizing: border-box;
3931
- padding: 6px 0;
3932
- display: flex;
3933
- gap: 2px;
3934
- flex-direction: column;
3935
- font-family: system-ui, sans-serif;
3936
- animation: fadeInMenu 0.13s cubic-bezier(0.4, 0, 0.2, 1);
3937
- overflow: scroll;
3938
- }
3939
-
3940
- @keyframes fadeInMenu {
3941
- from {
3942
- opacity: 0;
3943
- transform: translateY(8px);
3944
- }
3945
- to {
3946
- opacity: 1;
3947
- transform: none;
3948
- }
3949
- }
3950
-
3951
- .context-menu button {
3952
- all: unset;
3953
- display: flex;
3954
- align-items: center;
3955
- box-sizing: border-box;
3956
- width: 100%;
3957
- padding: 8px 18px;
3958
- font-size: 15px;
3959
- color: var(--menu-fg, #222);
3960
- background: none;
3961
- cursor: pointer;
3962
- transition:
3963
- background 0.1s,
3964
- color 0.1s;
3965
- user-select: none;
3966
- outline: none;
3967
- }
3968
-
3969
- .context-menu button:hover,
3970
- .context-menu button:focus-visible {
3971
- background: var(--menu-hover, #c7d5eaff);
3972
- color: var(--menu-accent, #155290ff);
3973
- }
3974
-
3975
- .context-menu button:active {
3976
- background: var(--menu-active, #e3eaf3);
3977
- }
3978
-
3979
- .context-menu button[disabled] {
3980
- color: #aaa;
3981
- cursor: not-allowed;
3982
- background: none;
3983
- }
3984
-
3985
- .context-menu-divider {
3986
- height: 1px;
3987
- background: var(--menu-divider, #c7d5eaff);
3988
- margin: 6px 12px;
3989
- border: none;
3990
- }
3991
-
3992
- canvas {
3993
- width: 100%;
3994
- height: 100%;
3995
- outline: none;
3996
- padding: 0;
3997
- margin: 0;
3998
- touch-action: none;
3999
- display: block;
4000
- }
4001
-
4002
- .canvas-loader {
4003
- position: absolute;
4004
- top: 0;
4005
- left: 0;
4006
- display: flex;
4007
- flex-direction: column;
4008
- align-items: center;
4009
- justify-content: center;
4010
- background: rgba(255, 255, 255, 0.7);
4011
- z-index: 1000;
4012
- pointer-events: all;
4013
- }
4014
-
4015
- .canvas-loader-spinner {
4016
- width: 48px;
4017
- height: 48px;
4018
- border: 6px solid #e0e0e0;
4019
- border-top: 6px solid #1976d2;
4020
- border-radius: 50%;
4021
- animation: canvas-loader-spin 1s linear infinite;
4022
- margin-bottom: 16px;
4023
- }
4024
-
4025
- @keyframes canvas-loader-spin {
4026
- 0% {
4027
- transform: rotate(0deg);
4028
- }
4029
- 100% {
4030
- transform: rotate(360deg);
4031
- }
4032
- }
4033
-
4034
- .canvas-loader-message {
4035
- font-size: 1.1rem;
4036
- color: #333;
4037
- background: rgba(255, 255, 255, 0.9);
4038
- padding: 8px 16px;
4039
- border-radius: 4px;
4040
- margin-top: 8px;
4041
- text-align: center;
4042
- max-width: 80%;
4043
- word-break: break-word;
4044
- }
4045
- `;
4046
- kt = Ms([
4047
- Hi("infinite-canvas")
4048
- ], kt);
4049
- class We {
4050
- constructor(t) {
4051
- if (!t) throw new Error("InfiniteCanvasElement is required");
4052
- 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);
4053
- }
4054
- static async forElement(t) {
4055
- let e;
4056
- if (typeof t == "string" ? (await customElements.whenDefined("infinite-canvas"), e = document.querySelector(
4057
- t
4058
- )) : e = t, !e) throw new Error("infinite-canvas element not found");
4059
- return e.canvas || await new Promise(
4060
- (i) => e.addEventListener("load", () => i(), { once: !0 })
4061
- ), new We(e);
4062
- }
4063
- /**
4064
- * Without assigning storage, the canvas will not save any data
4065
- * @param storage
4066
- * @param saveFrequency How often auto save occurs in ms
4067
- */
4068
- assignCanvasStorage(t, e = 3e3) {
4069
- return this.el.assignCanvasStorage(t, e), this;
4070
- }
4071
- async zoomIn() {
4072
- console.log("zooming"), this.el.zoomIn();
4073
- }
4074
- async zoomOut() {
4075
- this.el.zoomOut();
4076
- }
4077
- async toggleMode() {
4078
- this.el.togglePointerMode();
4079
- }
4080
- async addImageFromLocal(t) {
4081
- if (!(!t || t.length === 0)) {
4082
- for (let e = 0; e < t.length; e++) {
4083
- const i = t[e];
4084
- if (!i || !i.type || !i.type.startsWith("image/"))
4085
- throw new Error(
4086
- "Only specific image files are supported. Please select image files only."
4087
- );
4088
- }
4089
- await this.el.addImages(t);
4090
- }
4091
- }
4092
- async exportCanvas(t) {
4093
- this.el.exportCanvas(t);
4094
- }
4095
- async importCanvas(t) {
4096
- !t || t.length !== 1 || await this.el.importCanvas(t);
4097
- }
4098
- async clearCanvas() {
4099
- this.el.clearCanvas();
4100
- }
4101
- }
4102
- export {
4103
- Wi as Camera,
4104
- zt as Canvas,
4105
- We as InfiniteCanvasAPI,
4106
- kt as InfiniteCanvasElement,
4107
- Ui as ZOOM_MAX,
4108
- ki as ZOOM_MIN
4109
- };
4110
- //# sourceMappingURL=index.js.map