@lancercomet/zoom-pan 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,225 +1,221 @@
1
- # ZoomPan
2
-
3
- A lightweight **canvas viewport control library** for 2D applications.
4
- Provides smooth **panning**, **zooming**, **pinch-to-zoom**, and **inertia** behaviors.
5
-
6
- ## Features
7
-
8
- - Mouse pan & wheel zoom
9
- - Touch pan & pinch-to-zoom (always works, even in drawing mode)
10
- - Pen/stylus support for drawing apps
11
- - Layer-based rendering system
12
- - Built-in undo/redo support
13
- - Document bounds with margins
14
-
15
- ## Installation
16
-
17
- ```bash
18
- npm install @lancercomet/zoom-pan
19
- ```
20
-
21
- ## Quick Start
22
-
23
- ### Image Viewer
24
-
25
- ```typescript
26
- import { ViewManager, ContentLayerManager, createInteractionPlugin } from '@lancercomet/zoom-pan'
27
-
28
- const layerManager = new ContentLayerManager()
29
-
30
- const view = new ViewManager(canvas, () => {
31
- layerManager.renderAllLayersIn(view)
32
- })
33
-
34
- view.registerLayerManager(layerManager)
35
- view.use(createInteractionPlugin())
36
-
37
- // Add an image
38
- await layerManager.createImageLayer({
39
- src: 'image.png',
40
- x: 0,
41
- y: 0
42
- })
43
- ```
44
-
45
- ### Drawing App
46
-
47
- ```typescript
48
- import {
49
- ViewManager,
50
- ContentLayerManager,
51
- CanvasLayer,
52
- HistoryManager,
53
- createInteractionPlugin,
54
- createDocumentPlugin,
55
- createSnapshotCommand
56
- } from '@lancercomet/zoom-pan'
57
-
58
- const layerManager = new ContentLayerManager()
59
- const historyManager = new HistoryManager({ maxHistorySize: 50 })
60
-
61
- const view = new ViewManager(canvas, () => {
62
- layerManager.renderAllLayersIn(view)
63
- })
64
-
65
- view.registerLayerManager(layerManager)
66
-
67
- // Interaction plugin: controls pan/zoom
68
- // - Touch gestures (pan/pinch) always work
69
- // - Mouse/pen pan controlled by setPanEnabled()
70
- const interaction = view.use(createInteractionPlugin())
71
-
72
- // Document plugin: sets canvas bounds
73
- const doc = view.use(createDocumentPlugin({
74
- rect: { x: 0, y: 0, width: 1200, height: 800 },
75
- margins: { left: 50, right: 50, top: 50, bottom: 50 }
76
- }))
77
- doc.zoomToFit()
78
-
79
- // Create drawable layer
80
- const drawLayer = new CanvasLayer({
81
- width: 1200,
82
- height: 800
83
- })
84
- layerManager.addLayer(drawLayer)
85
-
86
- // Switch to drawing mode (disable mouse/pen pan, touch still works)
87
- interaction.setPanEnabled(false)
88
-
89
- // Drawing with undo support
90
- let snapshotBefore: ImageData | null = null
91
-
92
- canvas.onpointerdown = (e) => {
93
- if (e.pointerType === 'touch') return // Let plugin handle touch
94
-
95
- const { wx, wy } = view.toWorld(e.offsetX, e.offsetY)
96
- snapshotBefore = drawLayer.captureSnapshot()
97
- drawLayer.beginStroke(wx, wy)
98
- }
99
-
100
- canvas.onpointermove = (e) => {
101
- if (e.pointerType === 'touch') return
102
- if (e.buttons !== 1) return
103
-
104
- const { wx, wy } = view.toWorld(e.offsetX, e.offsetY)
105
- drawLayer.stroke(wx, wy, '#000', 10, e.pressure, 'brush')
106
- view.requestRender()
107
- }
108
-
109
- canvas.onpointerup = () => {
110
- drawLayer.endStroke()
111
- const snapshotAfter = drawLayer.captureSnapshot()
112
- const cmd = createSnapshotCommand(drawLayer, snapshotBefore, snapshotAfter)
113
- if (cmd) historyManager.addCommand(cmd)
114
- }
115
-
116
- // Undo/Redo
117
- document.onkeydown = (e) => {
118
- if (e.ctrlKey && e.key === 'z') historyManager.undo()
119
- if (e.ctrlKey && e.key === 'y') historyManager.redo()
120
- }
121
- ```
122
-
123
- ## Core Concepts
124
-
125
- ### ViewManager
126
-
127
- The main viewport controller. Handles coordinate transformation and rendering.
128
-
129
- ```typescript
130
- const view = new ViewManager(canvas, renderFn, {
131
- minZoom: 0.2,
132
- maxZoom: 10,
133
- background: '#fff'
134
- })
135
-
136
- // Coordinate conversion
137
- const { wx, wy } = view.toWorld(screenX, screenY)
138
- const { sx, sy } = view.toScreen(worldX, worldY)
139
-
140
- // Programmatic zoom
141
- view.zoomToAtScreen(anchorX, anchorY, 2.0)
142
- view.zoomByFactorAtScreen(anchorX, anchorY, 1.5)
143
- ```
144
-
145
- ### InteractionPlugin
146
-
147
- Handles user input for pan and zoom.
148
-
149
- ```typescript
150
- const interaction = view.use(createInteractionPlugin())
151
-
152
- // Pan enabled affects mouse/pen only
153
- // Touch gestures (single-finger pan, two-finger pinch) always work
154
- interaction.setPanEnabled(true) // Mouse/pen can pan
155
- interaction.setPanEnabled(false) // Mouse/pen cannot pan (for drawing mode)
156
-
157
- interaction.setZoomEnabled(true) // Wheel zoom & pinch zoom enabled
158
- ```
159
-
160
- ### DocumentPlugin
161
-
162
- Defines document bounds and provides pan clamping.
163
-
164
- ```typescript
165
- const doc = view.use(createDocumentPlugin({
166
- rect: { x: 0, y: 0, width: 1200, height: 800 },
167
- margins: { left: 50, right: 50, top: 50, bottom: 50 },
168
- drawBorder: true,
169
- background: '#f0f0f0',
170
- shadow: { blur: 20, color: 'rgba(0,0,0,0.3)', offsetX: 0, offsetY: 5 }
171
- }))
172
-
173
- doc.zoomToFit() // Fit document to viewport
174
- doc.setPanClampMode('minVisible') // 'margin' | 'minVisible'
175
- ```
176
-
177
- ### Layer System
178
-
179
- ```typescript
180
- // Content layers (world space)
181
- const contentManager = new ContentLayerManager()
182
- view.registerLayerManager(contentManager)
183
-
184
- // Canvas layer for drawing
185
- const layer = new CanvasLayer({ width: 1200, height: 800 })
186
- contentManager.addLayer(layer)
187
-
188
- // Image layer
189
- const imgLayer = await contentManager.createImageLayer({ src: 'image.png' })
190
-
191
- // Remove layer (destroys it)
192
- contentManager.removeLayer(layer.id)
193
-
194
- // Detach layer (keeps it for undo)
195
- contentManager.detachLayer(layer.id)
196
- ```
197
-
198
- ### History (Undo/Redo)
199
-
200
- ```typescript
201
- const history = new HistoryManager({ maxHistorySize: 50 })
202
-
203
- // Snapshot-based undo for drawing
204
- const before = layer.captureSnapshot()
205
- // ... draw ...
206
- const after = layer.captureSnapshot()
207
- const cmd = createSnapshotCommand(layer, before, after)
208
- if (cmd) history.addCommand(cmd)
209
-
210
- // Layer commands
211
- import { CreateLayerCommand, DeleteLayerCommand } from '@lancercomet/zoom-pan'
212
-
213
- history.undo()
214
- history.redo()
215
- history.canUndo()
216
- history.canRedo()
217
- ```
218
-
219
- ## Examples
220
-
221
- See `examples/` folder:
222
-
223
- - **`examples/viewer/`** - Simple image viewer
224
- - **`examples/painter/`** - Full drawing app with brush, eraser, layers, undo/redo
225
- - **`examples/doc/`** - Document mode demo with background and shadow
1
+ # ZoomPan
2
+
3
+ A lightweight **canvas viewport control library** for 2D applications.
4
+ Provides smooth **panning**, **zooming**, **pinch-to-zoom**, and **inertia** behaviors.
5
+
6
+ ## Features
7
+
8
+ - Mouse pan & wheel zoom
9
+ - Touch pan & pinch-to-zoom (always works, even in drawing mode)
10
+ - Pen/stylus support for drawing apps
11
+ - Layer-based rendering system
12
+ - Built-in undo/redo support
13
+ - Document bounds with margins
14
+
15
+ ## Installation
16
+
17
+ ```bash
18
+ npm install @lancercomet/zoom-pan
19
+ ```
20
+
21
+ ## Quick Start
22
+
23
+ ### Image Viewer
24
+
25
+ ```typescript
26
+ import { ViewManager, ContentLayerManager, createInteractionPlugin } from '@lancercomet/zoom-pan'
27
+
28
+ const layerManager = new ContentLayerManager()
29
+
30
+ const view = new ViewManager(canvas)
31
+
32
+ view.registerLayerManager(layerManager)
33
+ view.use(createInteractionPlugin())
34
+
35
+ // Add an image
36
+ await layerManager.createImageLayer({
37
+ src: 'image.png',
38
+ x: 0,
39
+ y: 0
40
+ })
41
+ ```
42
+
43
+ ### Drawing App
44
+
45
+ ```typescript
46
+ import {
47
+ ViewManager,
48
+ ContentLayerManager,
49
+ CanvasLayer,
50
+ HistoryManager,
51
+ createInteractionPlugin,
52
+ createBoundsPlugin,
53
+ createSnapshotCommand
54
+ } from '@lancercomet/zoom-pan'
55
+
56
+ const layerManager = new ContentLayerManager()
57
+ const historyManager = new HistoryManager({ maxHistorySize: 50 })
58
+
59
+ const view = new ViewManager(canvas)
60
+
61
+ view.registerLayerManager(layerManager)
62
+
63
+ // Interaction plugin: controls pan/zoom
64
+ // - Touch gestures (pan/pinch) always work
65
+ // - Mouse/pen pan controlled by setPanEnabled()
66
+ const interaction = view.use(createInteractionPlugin())
67
+
68
+ // Document plugin: sets canvas bounds
69
+ const doc = view.use(createBoundsPlugin({
70
+ rect: { x: 0, y: 0, width: 1200, height: 800 },
71
+ margins: { left: 50, right: 50, top: 50, bottom: 50 }
72
+ }))
73
+ doc.zoomToFit()
74
+
75
+ // Create drawable layer
76
+ const drawLayer = new CanvasLayer({
77
+ width: 1200,
78
+ height: 800
79
+ })
80
+ layerManager.addLayer(drawLayer)
81
+
82
+ // Switch to drawing mode (disable mouse/pen pan, touch still works)
83
+ interaction.setPanEnabled(false)
84
+
85
+ // Drawing with undo support
86
+ let snapshotBefore: ImageData | null = null
87
+
88
+ canvas.onpointerdown = (e) => {
89
+ if (e.pointerType === 'touch') return // Let plugin handle touch
90
+
91
+ const { wx, wy } = view.toWorld(e.offsetX, e.offsetY)
92
+ snapshotBefore = drawLayer.captureSnapshot()
93
+ drawLayer.beginStroke(wx, wy)
94
+ }
95
+
96
+ canvas.onpointermove = (e) => {
97
+ if (e.pointerType === 'touch') return
98
+ if (e.buttons !== 1) return
99
+
100
+ const { wx, wy } = view.toWorld(e.offsetX, e.offsetY)
101
+ drawLayer.stroke(wx, wy, '#000', 10, e.pressure, 'brush')
102
+ view.requestRender()
103
+ }
104
+
105
+ canvas.onpointerup = () => {
106
+ drawLayer.endStroke()
107
+ const snapshotAfter = drawLayer.captureSnapshot()
108
+ const cmd = createSnapshotCommand(drawLayer, snapshotBefore, snapshotAfter)
109
+ if (cmd) historyManager.addCommand(cmd)
110
+ }
111
+
112
+ // Undo/Redo
113
+ document.onkeydown = (e) => {
114
+ if (e.ctrlKey && e.key === 'z') historyManager.undo()
115
+ if (e.ctrlKey && e.key === 'y') historyManager.redo()
116
+ }
117
+ ```
118
+
119
+ ## Core Concepts
120
+
121
+ ### ViewManager
122
+
123
+ The main viewport controller. Handles coordinate transformation and rendering.
124
+
125
+ ```typescript
126
+ const view = new ViewManager(canvas, {
127
+ minZoom: 0.2,
128
+ maxZoom: 10,
129
+ background: '#fff'
130
+ })
131
+
132
+ // Coordinate conversion
133
+ const { wx, wy } = view.toWorld(screenX, screenY)
134
+ const { sx, sy } = view.toScreen(worldX, worldY)
135
+
136
+ // Programmatic zoom
137
+ view.zoomToAtScreen(anchorX, anchorY, 2.0)
138
+ view.zoomByFactorAtScreen(anchorX, anchorY, 1.5)
139
+ ```
140
+
141
+ ### InteractionPlugin
142
+
143
+ Handles user input for pan and zoom.
144
+
145
+ ```typescript
146
+ const interaction = view.use(createInteractionPlugin())
147
+
148
+ // Pan enabled affects mouse/pen only
149
+ // Touch gestures (single-finger pan, two-finger pinch) always work
150
+ interaction.setPanEnabled(true) // Mouse/pen can pan
151
+ interaction.setPanEnabled(false) // Mouse/pen cannot pan (for drawing mode)
152
+
153
+ interaction.setZoomEnabled(true) // Wheel zoom & pinch zoom enabled
154
+ ```
155
+
156
+ ### BoundsPlugin
157
+
158
+ Defines document bounds and provides pan clamping.
159
+
160
+ ```typescript
161
+ const doc = view.use(createBoundsPlugin({
162
+ rect: { x: 0, y: 0, width: 1200, height: 800 },
163
+ margins: { left: 50, right: 50, top: 50, bottom: 50 },
164
+ drawBorder: true,
165
+ background: '#f0f0f0',
166
+ shadow: { blur: 20, color: 'rgba(0,0,0,0.3)', offsetX: 0, offsetY: 5 }
167
+ }))
168
+
169
+ doc.zoomToFit() // Fit document to viewport
170
+ doc.setPanClampMode('minVisible') // 'margin' | 'minVisible'
171
+ ```
172
+
173
+ ### Layer System
174
+
175
+ ```typescript
176
+ // Content layers (world space)
177
+ const contentManager = new ContentLayerManager()
178
+ view.registerLayerManager(contentManager)
179
+
180
+ // Canvas layer for drawing
181
+ const layer = new CanvasLayer({ width: 1200, height: 800 })
182
+ contentManager.addLayer(layer)
183
+
184
+ // Image layer
185
+ const imgLayer = await contentManager.createImageLayer({ src: 'image.png' })
186
+
187
+ // Remove layer (destroys it)
188
+ contentManager.removeLayer(layer.id)
189
+
190
+ // Detach layer (keeps it for undo)
191
+ contentManager.detachLayer(layer.id)
192
+ ```
193
+
194
+ ### History (Undo/Redo)
195
+
196
+ ```typescript
197
+ const history = new HistoryManager({ maxHistorySize: 50 })
198
+
199
+ // Snapshot-based undo for drawing
200
+ const before = layer.captureSnapshot()
201
+ // ... draw ...
202
+ const after = layer.captureSnapshot()
203
+ const cmd = createSnapshotCommand(layer, before, after)
204
+ if (cmd) history.addCommand(cmd)
205
+
206
+ // Layer commands
207
+ import { CreateLayerCommand, DeleteLayerCommand } from '@lancercomet/zoom-pan'
208
+
209
+ history.undo()
210
+ history.redo()
211
+ history.canUndo()
212
+ history.canRedo()
213
+ ```
214
+
215
+ ## Examples
216
+
217
+ See `examples/` folder:
218
+
219
+ - **`examples/viewer/`** - Simple image viewer
220
+ - **`examples/painter/`** - Full drawing app with brush, eraser, layers, undo/redo
221
+ - **`examples/doc/`** - Document mode demo with background and shadow
@@ -10,6 +10,10 @@ interface ViewManagerOption {
10
10
  approachKPan?: number;
11
11
  autoResize?: boolean;
12
12
  background?: string | null;
13
+ /**
14
+ * Custom render function. If not provided, all registered LayerManagers will be rendered automatically.
15
+ */
16
+ render?: RenderFn;
13
17
  }
14
18
  declare class ViewManager {
15
19
  readonly canvas: HTMLCanvasElement;
@@ -39,12 +43,18 @@ declare class ViewManager {
39
43
  private LOG_MAX;
40
44
  private _targetTx;
41
45
  private _targetTy;
46
+ private _isAnimatingTransform;
42
47
  private _updateCallbacks;
43
48
  private _beforeRenderCallbacks;
44
49
  private _afterRenderCallbacks;
45
50
  get zoom(): number;
46
51
  get minZoom(): number;
47
52
  get maxZoom(): number;
53
+ /**
54
+ * Returns true when a programmatic animation (like zoomToFit) is in progress.
55
+ * During this time, user interactions should be ignored.
56
+ */
57
+ get isAnimating(): boolean;
48
58
  private _dpr;
49
59
  get dpr(): number;
50
60
  /**
@@ -134,6 +144,7 @@ declare class ViewManager {
134
144
  setTransform(zoom: number, tx: number, ty: number): void;
135
145
  /**
136
146
  * Set full transform with smooth animation.
147
+ * During the animation, user interactions are ignored.
137
148
  */
138
149
  setTransformSmooth(zoom: number, tx: number, ty: number): void;
139
150
  private _ensureOffscreenSizeLike;
@@ -212,7 +223,7 @@ declare class ViewManager {
212
223
  * Destroy and cleanup.
213
224
  */
214
225
  destroy(): void;
215
- constructor(canvas: HTMLCanvasElement, render: RenderFn, options?: ViewManagerOption);
226
+ constructor(canvas: HTMLCanvasElement, options?: ViewManagerOption);
216
227
  }
217
228
  export { ViewManager };
218
229
  export type { ViewManagerOption, RenderFn, UpdateCallback, RenderCallback };
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- "use strict";function t(t,e,i,s){return new(i||(i=Promise))(function(n,h){function a(t){try{r(s.next(t))}catch(t){h(t)}}function o(t){try{r(s.throw(t))}catch(t){h(t)}}function r(t){var e;t.done?n(t.value):(e=t.value,e instanceof i?e:new i(function(t){t(e)})).then(a,o)}r((s=s.apply(t,e||[])).next())})}function e(t,e,i,s){if("a"===i&&!s)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof e?t!==e||!s:!e.has(t))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===i?s:"a"===i?s.call(t):s?s.value:e.get(t)}function i(t,e,i,s,n){if("m"===s)throw new TypeError("Private method is not writable");if("a"===s&&!n)throw new TypeError("Private accessor was defined without a setter");if("function"==typeof e?t!==e||!n:!e.has(t))throw new TypeError("Cannot write private member to an object whose class did not declare it");return"a"===s?n.call(t,i):n?n.value=i:e.set(t,i),i}"function"==typeof SuppressedError&&SuppressedError;const s=(e,i)=>t(void 0,void 0,void 0,function*(){return new Promise((t,s)=>{const n=new Image;"string"==typeof e?(void 0!==i&&(n.crossOrigin=i),n.src=e):n.src=URL.createObjectURL(e),n.onload=()=>{t(n)},n.onerror=()=>{s(new Error("Image load failed"))}})}),n=(t,e,i)=>Math.min(Math.max(t,e),i);let h=0;class a{constructor(t,e,i="world"){this.space="world",this.visible=!0,this.opacity=1,this.blend="source-over",this.name=t,this.id=`layer_${e}_${++h}`,this.type=e,this.space=i}}class o extends a{beginStroke(t,e){const{lx:i,ly:s}=this.toLocalPoint(t,e);this._lastX=i,this._lastY=s,this._drawing=!0}stroke(t,e,i,s,n=1,h="brush"){if(!this._drawing)return;const{lx:a,ly:o}=this.toLocalPoint(t,e);this.context.beginPath(),this.context.moveTo(this._lastX,this._lastY),this.context.lineTo(a,o),"eraser"===h?(this.context.globalCompositeOperation="destination-out",this.context.strokeStyle="rgba(0, 0, 0, 1)"):(this.context.globalCompositeOperation="source-over",this.context.strokeStyle=i),this.context.lineWidth=s*n,this.context.lineCap="round",this.context.lineJoin="round",this.context.stroke(),this.context.closePath(),this._lastX=a,this._lastY=o}endStroke(){this._drawing=!1}isDrawing(){return this._drawing}captureSnapshot(t){try{if(t){const{x:e,y:i,width:s,height:n}=t,h=Math.max(0,Math.floor(e)),a=Math.max(0,Math.floor(i)),o=Math.min(this.canvas.width-h,Math.ceil(s)),r=Math.min(this.canvas.height-a,Math.ceil(n));return o<=0||r<=0?null:this.context.getImageData(h,a,o,r)}return this.context.getImageData(0,0,this.canvas.width,this.canvas.height)}catch(t){return null}}restoreSnapshot(t,e){var i,s;const n=null!==(i=null==e?void 0:e.x)&&void 0!==i?i:0,h=null!==(s=null==e?void 0:e.y)&&void 0!==s?s:0;this.context.putImageData(t,n,h)}clearRegion(t){t?this.context.clearRect(t.x,t.y,t.width,t.height):this.context.clearRect(0,0,this.canvas.width,this.canvas.height)}requestRedraw(){var t;null===(t=this._redraw)||void 0===t||t.call(this,this.context,this.canvas)}drawImage(t,e,i,s,n){this.context.drawImage(t,e,i,null!=s?s:t.width,null!=n?n:t.height)}hitTest(t,e){const{lx:i,ly:s}=this.toLocalPoint(t,e);return i>=0&&i<=this.canvas.width&&s>=0&&s<=this.canvas.height}toLocalPoint(t,e){const i=t-this.x,s=e-this.y,n=Math.cos(-this.rotation),h=Math.sin(-this.rotation),a=i*h+s*n,o=(i*n-s*h)/this.scale,r=a/this.scale;return{lx:o+("center"===this.anchor?this.canvas.width/2:0),ly:r+("center"===this.anchor?this.canvas.height/2:0)}}render(t,e){if(!this.visible)return;const i=this.canvas.width*this.scale,s=this.canvas.height*this.scale,n="center"===this.anchor?-i/2:0,h="center"===this.anchor?-s/2:0;t.save(),t.globalAlpha=this.opacity,t.globalCompositeOperation=this.blend,t.translate(this.x,this.y),t.rotate(this.rotation),t.drawImage(this.canvas,n,h,i,s),t.restore()}cropTo(t){const e=Math.max(1,Math.floor(t.width)),i=Math.max(1,Math.floor(t.height));if(e===this.canvas.width&&i===this.canvas.height)return;const s=this._cloneCanvas(),n=Math.min(s.width,e),h=Math.min(s.height,i);this._setCanvasSize(e,i),n>0&&h>0&&this.context.drawImage(s,0,0,n,h,0,0,n,h)}resizeTo(t){const e=Math.max(1,Math.floor(t.width)),i=Math.max(1,Math.floor(t.height));if(e===this.canvas.width&&i===this.canvas.height)return;const s=this._cloneCanvas();this._setCanvasSize(e,i),s.width>0&&s.height>0&&this.context.drawImage(s,0,0,s.width,s.height,0,0,e,i)}_cloneCanvas(){const t=document.createElement("canvas");if(t.width=this.canvas.width,t.height=this.canvas.height,0===t.width||0===t.height)return t;const e=t.getContext("2d");if(!e)throw new Error("Offscreen 2D context unavailable");return e.drawImage(this.canvas,0,0),t}_setCanvasSize(t,e){this.canvas.width=t,this.canvas.height=e,this.context.setTransform(1,0,0,1,0,0),this.context.clearRect(0,0,t,e)}destroy(){this.canvas.width=0,this.canvas.height=0}constructor(t){var e,i;if(super(t.name||"","canvas",null!==(e=t.space)&&void 0!==e?e:"world"),this.x=0,this.y=0,this.scale=1,this.rotation=0,this.anchor="topLeft",this._drawing=!1,this._lastX=0,this._lastY=0,"canvas"in t&&t.canvas)this.canvas=t.canvas;else{const e=t;this.canvas=document.createElement("canvas"),this.canvas.width=e.width,this.canvas.height=e.height}const s=this.canvas.getContext("2d",{willReadFrequently:!0});if(!s)throw new Error("Offscreen 2D context unavailable");this.context=s,this.x=t.x||0,this.y=t.y||0,this.scale=null!==(i=t.scale)&&void 0!==i?i:1,this.rotation=t.rotation||0,t.anchor&&(this.anchor=t.anchor),this._redraw=t.redraw,this._redraw&&this._redraw(this.context,this.canvas)}}var r;class c extends o{static fromImage(e){return t(this,void 0,void 0,function*(){var t,n,h,a,o,_,l,d;const u=yield s(e.src,e.crossOrigin),g=null!==(t=e.width)&&void 0!==t?t:u.naturalWidth,p=null!==(n=e.height)&&void 0!==n?n:u.naturalHeight,v=new c({name:e.name,space:null!==(h=e.space)&&void 0!==h?h:"world",x:null!==(a=e.x)&&void 0!==a?a:0,y:null!==(o=e.y)&&void 0!==o?o:0,scale:null!==(_=e.scale)&&void 0!==_?_:1,rotation:null!==(l=e.rotation)&&void 0!==l?l:0,anchor:null!==(d=e.anchor)&&void 0!==d?d:"topLeft",width:g,height:p});return v.context.clearRect(0,0,v.canvas.width,v.canvas.height),v.context.drawImage(u,0,0,g,p),"string"!=typeof e.src&&i(v,r,u.src.startsWith("blob:")?u.src:null,"f"),v})}setSource(n,h){return t(this,void 0,void 0,function*(){const t=yield s(n,h);if(this.canvas.width=t.naturalWidth,this.canvas.height=t.naturalHeight,this.context.setTransform(1,0,0,1,0,0),this.context.clearRect(0,0,this.canvas.width,this.canvas.height),this.context.drawImage(t,0,0),e(this,r,"f")){try{URL.revokeObjectURL(e(this,r,"f"))}catch(t){}i(this,r,null,"f")}"string"!=typeof n&&i(this,r,t.src.startsWith("blob:")?t.src:null,"f")})}paint(t){t(this.context,this.canvas)}getImageData(t=0,e=0,i=this.canvas.width,s=this.canvas.height){return this.context.getImageData(t,e,i,s)}putImageData(t,e=0,i=0){this.context.putImageData(t,e,i)}toDataURL(t="image/png",e){return this.canvas.toDataURL(t,e)}toImageBitmap(t){return createImageBitmap(this.canvas,null!=t?t:{})}destroy(){var t;if(null===(t=super.destroy)||void 0===t||t.call(this),e(this,r,"f")){try{URL.revokeObjectURL(e(this,r,"f"))}catch(t){}i(this,r,null,"f")}}constructor(t){var e,i;super({name:t.name,space:null!==(e=t.space)&&void 0!==e?e:"world",x:t.x,y:t.y,scale:t.scale,rotation:t.rotation,anchor:null!==(i=t.anchor)&&void 0!==i?i:"topLeft",width:t.width,height:t.height}),r.set(this,null),this.type="bitmap"}}r=new WeakMap;class _{constructor(){this._worldLayers=[],this._screenLayers=[]}_renderAllLayersIn(t,e){e.save(),t.applyWorldTransform(e);for(const i of this._worldLayers)!i.visible||i.opacity<=0||(e.save(),i.render(e,t),e.restore());e.restore(),e.save(),t.applyScreenTransform(e);for(const i of this._screenLayers)!i.visible||i.opacity<=0||(e.save(),i.render(e,t),e.restore());e.restore()}addLayer(t,e){const i="world"===t.space?this._worldLayers:this._screenLayers;return"number"==typeof e&&e>=0&&e<i.length?(i.splice(e,0,t),t.id):(i.push(t),t.id)}createImageLayer(e){return t(this,void 0,void 0,function*(){const t=yield c.fromImage(e);return this.addLayer(t),t})}createCanvasLayer(t){const e=new o(t);return this.addLayer(e),e}removeLayer(t){var e,i,s,n;const h=this._worldLayers.findIndex(e=>e.id===t);if(h>=0)return null===(i=(e=this._worldLayers[h]).destroy)||void 0===i||i.call(e),void this._worldLayers.splice(h,1);const a=this._screenLayers.findIndex(e=>e.id===t);a>=0&&(null===(n=(s=this._screenLayers[a]).destroy)||void 0===n||n.call(s),this._screenLayers.splice(a,1))}detachLayer(t){const e=this._worldLayers.findIndex(e=>e.id===t);if(e>=0)return void this._worldLayers.splice(e,1);const i=this._screenLayers.findIndex(e=>e.id===t);i>=0&&this._screenLayers.splice(i,1)}moveLayer(t,e){const i=this._worldLayers.findIndex(e=>e.id===t);if(i>=0){const[t]=this._worldLayers.splice(i,1),s=Math.max(0,Math.min(e,this._worldLayers.length));return void this._worldLayers.splice(s,0,t)}const s=this._screenLayers.findIndex(e=>e.id===t);if(s>=0){const[t]=this._screenLayers.splice(s,1),i=Math.max(0,Math.min(e,this._screenLayers.length));this._screenLayers.splice(i,0,t)}}reorderLayers(t){const e=[];for(const i of t){const t=this._worldLayers.find(t=>t.id===i);t&&e.push(t)}for(const i of this._worldLayers)t.includes(i.id)||e.push(i);this._worldLayers=e}getLayer(t){return this._worldLayers.find(e=>e.id===t)||this._screenLayers.find(e=>e.id===t)}getAllLayers(t){return t?("world"===t?this._worldLayers:this._screenLayers).slice():[...this._worldLayers,...this._screenLayers]}hitTest(t,e,i="world"){const s=this.getAllLayers(i);for(let i=s.length-1;i>=0;i--){const n=s[i];if(n.hitTest&&n.hitTest(t,e))return n}}destroy(){var t;for(const e of[...this._worldLayers,...this._screenLayers])null===(t=e.destroy)||void 0===t||t.call(e);this._worldLayers=[],this._screenLayers=[]}}class l{constructor(t){this.name="interaction",this._view=null,this._dragging=!1,this._vx=0,this._vy=0,this._lastMoveTs=0,this._activePointerId=null,this._lastPointerX=0,this._lastPointerY=0,this._touchPointers=new Map,this._isTouchPanning=!1,this._isPinching=!1,this._lastPinchDistance=0,this._lastPinchCenterX=0,this._lastPinchCenterY=0,this._lastTouchX=0,this._lastTouchY=0,this._onDownBound=t=>this._onPointerDown(t),this._onMoveBound=t=>this._onPointerMove(t),this._onUpBound=t=>this._onPointerUp(t),this._onCancelBound=t=>this._onPointerCancel(t),this._onWheelBound=t=>this._onWheel(t),this._onUpdate=t=>{if(!this._view)return;const{friction:e,stopSpeed:i}=this._options,s=Math.hypot(this._vx,this._vy)>=i;if(!(this._dragging||this._isTouchPanning||this._isPinching)&&s){const s=this._vx*t,n=this._vy*t;this._view.panBy(s,n),this._vx*=e,this._vy*=e,Math.hypot(this._vx,this._vy)<i&&(this._vx=0,this._vy=0)}},this._options=Object.assign({panEnabled:!0,zoomEnabled:!0,friction:.92,stopSpeed:.02,emaAlpha:.25,idleNoInertiaMs:120,wheelSensitivity:.0015},t),this._panEnabled=this._options.panEnabled,this._zoomEnabled=this._options.zoomEnabled}install(t){this._view=t;const e=t.canvas;e.style.touchAction="none",e.addEventListener("wheel",this._onWheelBound,{passive:!1}),e.addEventListener("pointerdown",this._onDownBound),window.addEventListener("pointermove",this._onMoveBound),window.addEventListener("pointerup",this._onUpBound),window.addEventListener("pointercancel",this._onCancelBound),t.onUpdate(this._onUpdate)}destroy(){if(!this._view)return;const t=this._view.canvas;t.removeEventListener("wheel",this._onWheelBound),t.removeEventListener("pointerdown",this._onDownBound),window.removeEventListener("pointermove",this._onMoveBound),window.removeEventListener("pointerup",this._onUpBound),window.removeEventListener("pointercancel",this._onCancelBound),this._touchPointers.clear(),this._isPinching=!1,this._isTouchPanning=!1,this._view.offUpdate(this._onUpdate),this._view=null}isPanEnabled(){return this._panEnabled}isZoomEnabled(){return this._zoomEnabled}setPanEnabled(t){this._panEnabled!==t&&(this._panEnabled=t,t||null===this._activePointerId||(this._dragging=!1,this._vx=0,this._vy=0))}setZoomEnabled(t){this._zoomEnabled!==t&&(this._zoomEnabled=t,!t&&this._isPinching&&this._endPinch())}setWheelSensitivity(t){this._options.wheelSensitivity=t}isDragging(){return this._dragging||this._isTouchPanning||this._isPinching}_onPointerDown(t){var e;if("touch"!==t.pointerType){if(("mouse"!==t.pointerType||0===t.button)&&this._panEnabled&&null===this._activePointerId){t.preventDefault(),this._dragging=!0,this._vx=0,this._vy=0,this._lastMoveTs=performance.now(),this._activePointerId=t.pointerId,this._lastPointerX=t.clientX,this._lastPointerY=t.clientY;try{null===(e=this._view)||void 0===e||e.canvas.setPointerCapture(t.pointerId)}catch(t){}}}else this._onTouchDown(t)}_onPointerMove(t){if("touch"===t.pointerType)return void this._onTouchMove(t);if(t.pointerId!==this._activePointerId)return;if(!this._dragging||!this._panEnabled||!this._view)return;const e=performance.now(),i=Math.max(1,e-(this._lastMoveTs||e-16));this._lastMoveTs=e;const s=t.clientX-this._lastPointerX,n=t.clientY-this._lastPointerY;this._lastPointerX=t.clientX,this._lastPointerY=t.clientY,this._view.panBy(s,n);const h=this._options.emaAlpha,a=s/i,o=n/i;this._vx=(1-h)*this._vx+h*a,this._vy=(1-h)*this._vy+h*o}_onPointerUp(t){if("touch"===t.pointerType)return void this._onTouchUp(t);if(t.pointerId!==this._activePointerId)return;if(!this._dragging)return;this._dragging=!1;const e=performance.now(),i=this._lastMoveTs?e-this._lastMoveTs:1/0;if(null!=this._activePointerId&&this._view){try{this._view.canvas.releasePointerCapture(this._activePointerId)}catch(t){}this._activePointerId=null}if(i>=this._options.idleNoInertiaMs)this._vx=0,this._vy=0;else{const t=Math.pow(this._options.friction,i/16);this._vx*=t,this._vy*=t}Math.hypot(this._vx,this._vy)<this._options.stopSpeed&&(this._vx=0,this._vy=0)}_onPointerCancel(t){"touch"!==t.pointerType?t.pointerId===this._activePointerId&&(this._dragging=!1,this._vx=0,this._vy=0,this._activePointerId=null):this._onTouchCancel(t)}_onTouchDown(t){if(t.preventDefault(),this._touchPointers.set(t.pointerId,{x:t.clientX,y:t.clientY}),2===this._touchPointers.size&&this._zoomEnabled)return this._isTouchPanning=!1,void this._startPinch();1===this._touchPointers.size&&(this._isTouchPanning=!0,this._vx=0,this._vy=0,this._lastMoveTs=performance.now(),this._lastTouchX=t.clientX,this._lastTouchY=t.clientY)}_onTouchMove(t){if(this._touchPointers.has(t.pointerId))if(this._touchPointers.set(t.pointerId,{x:t.clientX,y:t.clientY}),this._isPinching&&2===this._touchPointers.size)this._handlePinchMove();else if(this._isTouchPanning&&1===this._touchPointers.size&&this._view){const e=performance.now(),i=Math.max(1,e-(this._lastMoveTs||e-16));this._lastMoveTs=e;const s=t.clientX-this._lastTouchX,n=t.clientY-this._lastTouchY;this._lastTouchX=t.clientX,this._lastTouchY=t.clientY,this._view.panBy(s,n);const h=this._options.emaAlpha,a=s/i,o=n/i;this._vx=(1-h)*this._vx+h*a,this._vy=(1-h)*this._vy+h*o}}_onTouchUp(t){if(this._touchPointers.delete(t.pointerId),this._isPinching){if(this._endPinch(),1===this._touchPointers.size){const[[,t]]=this._touchPointers.entries();this._isTouchPanning=!0,this._lastTouchX=t.x,this._lastTouchY=t.y,this._vx=0,this._vy=0,this._lastMoveTs=performance.now()}}else if(this._isTouchPanning&&0===this._touchPointers.size){this._isTouchPanning=!1;const t=performance.now(),e=this._lastMoveTs?t-this._lastMoveTs:1/0;if(e>=this._options.idleNoInertiaMs)this._vx=0,this._vy=0;else{const t=Math.pow(this._options.friction,e/16);this._vx*=t,this._vy*=t}Math.hypot(this._vx,this._vy)<this._options.stopSpeed&&(this._vx=0,this._vy=0)}}_onTouchCancel(t){this._touchPointers.delete(t.pointerId),this._isPinching&&this._endPinch(),0===this._touchPointers.size&&(this._isTouchPanning=!1,this._vx=0,this._vy=0)}_startPinch(){this._isPinching=!0;const[t,e]=Array.from(this._touchPointers.values());this._lastPinchDistance=Math.hypot(e.x-t.x,e.y-t.y),this._lastPinchCenterX=(t.x+e.x)/2,this._lastPinchCenterY=(t.y+e.y)/2}_handlePinchMove(){if(!this._view||!this._zoomEnabled)return;const t=Array.from(this._touchPointers.values());if(2!==t.length)return;const[e,i]=t,s=Math.hypot(i.x-e.x,i.y-e.y),n=(e.x+i.x)/2,h=(e.y+i.y)/2;if(this._lastPinchDistance>0){const t=s/this._lastPinchDistance,e=this._view.canvas.getBoundingClientRect(),i=n-e.left,a=h-e.top;this._view.zoomByFactorAtScreen(i,a,t);const o=n-this._lastPinchCenterX,r=h-this._lastPinchCenterY;this._view.panBy(o,r)}this._lastPinchDistance=s,this._lastPinchCenterX=n,this._lastPinchCenterY=h}_endPinch(){this._isPinching=!1,this._lastPinchDistance=0,this._lastPinchCenterX=0,this._lastPinchCenterY=0}_getLineHeightPx(){if(!this._view)return 16;const t=getComputedStyle(this._view.canvas).lineHeight;if(!t||"normal"===t)return 16;const e=parseFloat(t);return Number.isFinite(e)?e:16}_normalizeWheelDelta(t){if(!this._view)return 0;let e=t.deltaY;if(1===t.deltaMode)e*=this._getLineHeightPx();else if(2===t.deltaMode){e*=this._view.canvas.clientHeight||window.innerHeight||800}return e}_onWheel(t){if(!this._zoomEnabled||!this._view)return;t.preventDefault(),t.stopPropagation();const e=this._normalizeWheelDelta(t),i=this._view.canvas.getBoundingClientRect(),s=t.clientX-i.left,n=t.clientY-i.top;let h=-e*this._options.wheelSensitivity;t.ctrlKey||t.metaKey?h*=1.6:t.shiftKey&&(h*=.6),this._view.zoomByLogAtScreen(s,n,h)}}class d{constructor(t){var e,i,s,n,h;this.name="document",this._view=null,this._enabled=!1,this._x=0,this._y=0,this._width=0,this._height=0,this._marginL=0,this._marginR=0,this._marginT=0,this._marginB=0,this._panClampMode="minVisible",this._background=null,this._shadow=null,this._onUpdate=()=>{this._enabled&&this._view&&this._clampPan()},this._onBeforeRender=t=>{var e,i,s,n,h;this._enabled&&this._view&&(this._shadow?(t.save(),t.shadowColor=null!==(e=this._shadow.color)&&void 0!==e?e:d._defaultShadow.color,t.shadowBlur=null!==(i=this._shadow.blur)&&void 0!==i?i:d._defaultShadow.blur,t.shadowOffsetX=null!==(s=this._shadow.offsetX)&&void 0!==s?s:d._defaultShadow.offsetX,t.shadowOffsetY=null!==(n=this._shadow.offsetY)&&void 0!==n?n:d._defaultShadow.offsetY,t.fillStyle=null!==(h=this._background)&&void 0!==h?h:"#ffffff",t.fillRect(this._x,this._y,this._width,this._height),t.restore()):this._background&&(t.save(),t.fillStyle=this._background,t.fillRect(this._x,this._y,this._width,this._height),t.restore()),t.save(),t.beginPath(),t.rect(this._x,this._y,this._width,this._height),t.clip())},this._onAfterRender=t=>{if(this._enabled&&this._view&&(t.restore(),this._options.drawBorder)){const e=this._view.zoom;t.save(),t.lineWidth=1/e,t.strokeStyle="#cfcfcf",t.strokeRect(this._x,this._y,this._width,this._height),t.restore()}},this._options=Object.assign({rect:{x:0,y:0,width:0,height:0},margins:{},drawBorder:!1,minVisiblePx:30,panClampMode:"minVisible",background:null,shadow:!1},t),(null==t?void 0:t.rect)&&(this._enabled=!0,this._x=t.rect.x,this._y=t.rect.y,this._width=t.rect.width,this._height=t.rect.height),(null==t?void 0:t.margins)&&(this._marginL=null!==(e=t.margins.left)&&void 0!==e?e:0,this._marginR=null!==(i=t.margins.right)&&void 0!==i?i:0,this._marginT=null!==(s=t.margins.top)&&void 0!==s?s:0,this._marginB=null!==(n=t.margins.bottom)&&void 0!==n?n:0),this._panClampMode=this._options.panClampMode,this._background=null!==(h=this._options.background)&&void 0!==h?h:null,!0===this._options.shadow?this._shadow=Object.assign({},d._defaultShadow):this._options.shadow&&"object"==typeof this._options.shadow&&(this._shadow=Object.assign(Object.assign({},d._defaultShadow),this._options.shadow))}install(t){this._view=t,t.onUpdate(this._onUpdate),t.onBeforeRender(this._onBeforeRender),t.onAfterRender(this._onAfterRender)}destroy(){this._view&&(this._view.offUpdate(this._onUpdate),this._view.offBeforeRender(this._onBeforeRender),this._view.offAfterRender(this._onAfterRender),this._view=null)}isEnabled(){return this._enabled}getRect(){return{x:this._x,y:this._y,width:this._width,height:this._height}}setRect(t,e,i,s){this._enabled=!0,this._x=t,this._y=e,this._width=i,this._height=s}clearRect(){this._enabled=!1}setMargins(t){var e,i,s,n;this._marginL=null!==(e=t.left)&&void 0!==e?e:this._marginL,this._marginR=null!==(i=t.right)&&void 0!==i?i:this._marginR,this._marginT=null!==(s=t.top)&&void 0!==s?s:this._marginT,this._marginB=null!==(n=t.bottom)&&void 0!==n?n:this._marginB}getMargins(){return{left:this._marginL,right:this._marginR,top:this._marginT,bottom:this._marginB}}setPanClampMode(t){this._panClampMode=t}getPanClampMode(){return this._panClampMode}cropTo(t){this._doResize("crop",t)}resizeTo(t){this._doResize("resize",t)}zoomToFit(t="contain",e=!0){if(!this._enabled||!this._view)return;const i=this._view.dpr,s=this._view.canvas.width/i,n=this._view.canvas.height/i,h=Math.max(1,s-(this._marginL+this._marginR)),a=Math.max(1,n-(this._marginT+this._marginB));let o;const r=h/this._width,c=a/this._height;o="contain"===t?Math.min(r,c):"cover"===t?Math.max(r,c):"fitWidth"===t?r:c,o=Math.min(this._view.maxZoom,Math.max(this._view.minZoom,o));const _=this._marginL+(h-o*this._width)/2,l=this._marginT+(a-o*this._height)/2,d=_-o*this._x,u=l-o*this._y;e?this._view.setTransformSmooth(o,d,u):this._view.setTransform(o,d,u)}isPointInDocument(t,e){return!this._enabled||t>=this._x&&t<=this._x+this._width&&e>=this._y&&e<=this._y+this._height}get background(){return this._background}setBackground(t){var e;this._background=t,null===(e=this._view)||void 0===e||e.requestRender()}get shadow(){return this._shadow?Object.assign({},this._shadow):null}setShadow(t){var e;this._shadow=!0===t?Object.assign({},d._defaultShadow):t&&"object"==typeof t?Object.assign(Object.assign({},d._defaultShadow),t):null,null===(e=this._view)||void 0===e||e.requestRender()}_clampPan(){if(!this._view)return;const{zoom:t,tx:e,ty:i}=this._view.getTransform(),s=t,n=this._view.dpr,h=this._view.canvas.width/n,a=this._view.canvas.height/n,o=this._x,r=this._y,c=this._x+this._width,_=this._y+this._height;let l=e,d=i;if("margin"===this._panClampMode){const t=this._marginL-s*o,n=h-this._marginR-s*c,u=this._marginT-s*r,g=a-this._marginB-s*_,p=Math.max(1,h-(this._marginL+this._marginR)),v=Math.max(1,a-(this._marginT+this._marginB));l=s*this._width<=p?this._marginL+(p-s*this._width)/2-s*this._x:Math.min(t,Math.max(n,e)),d=s*this._height<=v?this._marginT+(v-s*this._height)/2-s*this._y:Math.min(u,Math.max(g,i))}else if("minVisible"===this._panClampMode){const t=s*this._width,n=s*this._height,u=Math.min(this._options.minVisiblePx,t),g=Math.min(this._options.minVisiblePx,n),p=h-u-s*o,v=u-s*c,m=a-g-s*r,y=g-s*_;l=v<=p?Math.min(p,Math.max(v,e)):(v+p)/2,d=y<=m?Math.min(m,Math.max(y,i)):(y+m)/2}l===e&&d===i||this._view.setPan(l,d)}_doResize(t,e){if(!this._view)return;const i=Math.max(1,Math.floor(e.width)),s=Math.max(1,Math.floor(e.height)),n={width:i,height:s},h=this._view.getLayerManagers();for(const e of h){const i=e.getAllLayers("world");for(const e of i){const i=e;"function"==typeof i.cropTo&&"function"==typeof i.resizeTo&&("crop"===t?i.cropTo(n):i.resizeTo(n))}}this._width=i,this._height=s,this._enabled&&this._clampPan()}}d._defaultShadow={color:"rgba(0, 0, 0, 0.3)",blur:20,offsetX:0,offsetY:4};class u{constructor(t,e,i,s){this.type="snapshot",this._isExecuted=!0,this._target=t,this._beforeData=e,this._afterData=i,this._region=null==s?void 0:s.region}execute(){if(this._isExecuted)return;const t=this._region?{x:this._region.x,y:this._region.y}:void 0;this._target.restoreSnapshot(this._afterData,t),this._isExecuted=!0}undo(){if(!this._isExecuted)return;const t=this._region?{x:this._region.x,y:this._region.y}:void 0;this._target.restoreSnapshot(this._beforeData,t),this._isExecuted=!1}canMerge(){return!1}merge(){return this}}exports.BitmapLayer=c,exports.CanvasLayer=o,exports.ContentLayerManager=class extends _{constructor(){super(...arguments),this._compositeCache=null,this._compositeCacheCtx=null,this._compositeDirty=!0,this._lastCacheWidth=0,this._lastCacheHeight=0,this._cachedBoundsMinX=0,this._cachedBoundsMinY=0}markDirty(){this._compositeDirty=!0}addLayer(t,e){return this._compositeDirty=!0,super.addLayer(t,e)}removeLayer(t){this._compositeDirty=!0,super.removeLayer(t)}detachLayer(t){this._compositeDirty=!0,super.detachLayer(t)}removeAllLayers(t){var e,i;if(!t||"world"===t){for(const t of this._worldLayers)null===(e=t.destroy)||void 0===e||e.call(t);this._worldLayers=[]}if(!t||"screen"===t){for(const t of this._screenLayers)null===(i=t.destroy)||void 0===i||i.call(t);this._screenLayers=[]}}moveLayer(t,e){this._compositeDirty=!0,super.moveLayer(t,e)}renderAllLayersIn(t){const e=t.contentContext,i=this._worldLayers;0!==i.length&&(this._compositeDirty&&this._rebuildCompositeCache(i),this._compositeCache&&this._compositeCacheCtx&&e.drawImage(this._compositeCache,this._cachedBoundsMinX,this._cachedBoundsMinY))}_rebuildCompositeCache(t){let e=0,i=0,s=0,n=0,h=!1;for(const a of t){const t=a,o=t.canvas.width*t.scale,r=t.canvas.height*t.scale,c="center"===t.anchor?-o/2:0,_="center"===t.anchor?-r/2:0,l=Math.cos(t.rotation),d=Math.sin(t.rotation),u=[{x:c,y:_},{x:c+o,y:_},{x:c,y:_+r},{x:c+o,y:_+r}];let g=1/0,p=1/0,v=-1/0,m=-1/0;for(const e of u){const i=e.x*l-e.y*d+t.x,s=e.x*d+e.y*l+t.y;g=Math.min(g,i),p=Math.min(p,s),v=Math.max(v,i),m=Math.max(m,s)}h?(e=Math.min(e,g),i=Math.min(i,p),s=Math.max(s,v),n=Math.max(n,m)):(e=g,i=p,s=v,n=m,h=!0)}if(!h)return void(this._compositeDirty=!1);const a=Math.ceil(s-e),o=Math.ceil(n-i);this._compositeCache||(this._compositeCache=document.createElement("canvas"),this._compositeCacheCtx=this._compositeCache.getContext("2d",{alpha:!0})),this._lastCacheWidth===a&&this._lastCacheHeight===o||(this._compositeCache.width=a,this._compositeCache.height=o,this._lastCacheWidth=a,this._lastCacheHeight=o),this._cachedBoundsMinX=e,this._cachedBoundsMinY=i;const r=this._compositeCacheCtx;r.clearRect(0,0,a,o),r.save(),r.translate(-e,-i);for(const e of t)!e.visible||e.opacity<=0||(r.save(),e.render(r),r.restore());r.restore(),this._compositeDirty=!1}destroy(){super.destroy(),this._compositeCache=null,this._compositeCacheCtx=null}},exports.CreateLayerCommand=class{constructor(t){this.type="create-layer",this._layer=t.layer,this._layerManager=t.layerManager,this._insertIndex=t.insertIndex,this._previousSelectedId=t.previousSelectedId,this._getLayerList=t.getLayerList,this._setSelectedId=t.setSelectedId}execute(){this._layerManager.addLayer(this._layer,this._insertIndex);this._getLayerList().splice(this._insertIndex,0,this._layer),this._setSelectedId(this._layer.id)}undo(){this._layerManager.detachLayer(this._layer.id);const t=this._getLayerList(),e=t.findIndex(t=>t.id===this._layer.id);e>-1&&t.splice(e,1),this._setSelectedId(this._previousSelectedId)}},exports.DeleteLayerCommand=class{constructor(t){this.type="delete-layer",this._layer=t.layer,this._layerManager=t.layerManager,this._originalIndex=t.originalIndex,this._previousSelectedId=t.previousSelectedId,this._newSelectedId=t.newSelectedId,this._getLayerList=t.getLayerList,this._setSelectedId=t.setSelectedId}execute(){this._layerManager.detachLayer(this._layer.id);const t=this._getLayerList(),e=t.findIndex(t=>t.id===this._layer.id);e>-1&&t.splice(e,1),this._setSelectedId(this._newSelectedId)}undo(){this._layerManager.addLayer(this._layer,this._originalIndex);this._getLayerList().splice(this._originalIndex,0,this._layer),this._setSelectedId(this._previousSelectedId)}},exports.DocumentPlugin=d,exports.HistoryManager=class{executeCommand(t){t.execute(),this.addCommand(t)}addCommand(t){var e,i;this._redoStack=[];const s=this._undoStack[this._undoStack.length-1];if(s&&(null===(e=s.canMerge)||void 0===e?void 0:e.call(s,t))&&s.merge){const e=null!==(i=s.merge(t))&&void 0!==i?i:s;return void(e!==s&&(this._undoStack[this._undoStack.length-1]=e))}this._undoStack.push(t),this._undoStack.length>this._maxHistorySize&&this._undoStack.shift()}undo(){if(0===this._undoStack.length)return null;const t=this._undoStack.pop();return t.undo(),this._redoStack.push(t),t}redo(){if(0===this._redoStack.length)return null;const t=this._redoStack.pop();return t.execute(),this._undoStack.push(t),t}canUndo(){return this._undoStack.length>0}canRedo(){return this._redoStack.length>0}clear(){this._undoStack=[],this._redoStack=[]}setMaxHistorySize(t){this._maxHistorySize=Math.max(1,t),this._undoStack.length>this._maxHistorySize&&(this._undoStack=this._undoStack.slice(-this._maxHistorySize))}constructor(t){var e,i,s;this._undoStack=[],this._redoStack=[],this._maxHistorySize=null!==(e=null==t?void 0:t.maxHistorySize)&&void 0!==e?e:50,this._undoStack=null!==(i=null==t?void 0:t.undoStack)&&void 0!==i?i:[],this._redoStack=null!==(s=null==t?void 0:t.redoStack)&&void 0!==s?s:[]}},exports.InteractionPlugin=l,exports.LayerBase=a,exports.LayerManagerBase=_,exports.SnapshotCommand=u,exports.TopScreenLayerManager=class extends _{renderAllLayersIn(t){const e=t.topScreenContext;this._renderAllLayersIn(t,e)}},exports.ViewManager=class{get zoom(){return Math.exp(this._currentLogZ)}get minZoom(){return this._options.minZoom}get maxZoom(){return this._options.maxZoom}get dpr(){return this._dpr}use(t){return this._plugins.has(t.name)?(console.warn(`Plugin "${t.name}" is already installed.`),t):(this._plugins.set(t.name,t),t.install(this),t)}unuse(t){const e=this._plugins.get(t);e&&(e.destroy(),this._plugins.delete(t))}getPlugin(t){return this._plugins.get(t)}onUpdate(t){this._updateCallbacks.add(t)}offUpdate(t){this._updateCallbacks.delete(t)}onBeforeRender(t){this._beforeRenderCallbacks.add(t)}offBeforeRender(t){this._beforeRenderCallbacks.delete(t)}onAfterRender(t){this._afterRenderCallbacks.add(t)}offAfterRender(t){this._afterRenderCallbacks.delete(t)}requestRender(){this._needsRender=!0}_clampLog(t){return n(t,this.LOG_MIN,this.LOG_MAX)}_setTargetLogZoomAtScreen(t,e,i){Number.isFinite(i)&&(this._anchorX=t,this._anchorY=e,this._targetLogZ=this._clampLog(i),this._needsRender=!0)}zoomToAtScreen(t,e,i){this._setTargetLogZoomAtScreen(t,e,Math.log(i))}zoomToAtScreenRaw(t,e,i){if(!Number.isFinite(i))return;const s=Math.max(1e-8,this._options.minZoom),h=this._options.maxZoom,a=n(i,s,h),o=Math.exp(this._currentLogZ),r=a;if(!Number.isFinite(o)||o<=0)return;if(Math.abs(r-o)<1e-12)return;const c=Math.log(a);this._currentLogZ=c,this._targetLogZ=c;const _=r/o;this._tx=t-(t-this._tx)*_,this._ty=e-(e-this._ty)*_,this._needsRender=!0}zoomToAtWorld(t,e,i){const{x:s,y:n}=this.toScreen(t,e);this.zoomToAtScreen(s,n,i)}zoomByFactorAtScreen(t,e,i){if(i<=0||!Number.isFinite(i))return;const s=Math.log(i);this._setTargetLogZoomAtScreen(t,e,this._targetLogZ+s)}zoomByLogAtScreen(t,e,i){this._setTargetLogZoomAtScreen(t,e,this._targetLogZ+i)}zoomByFactorAtWorld(t,e,i){const{x:s,y:n}=this.toScreen(t,e);this.zoomByFactorAtScreen(s,n,i)}panBy(t,e){this._tx+=t,this._ty+=e,this._needsRender=!0}setPan(t,e){this._tx=t,this._ty=e,this._needsRender=!0}setTransform(t,e,i){const s=n(t,this._options.minZoom,this._options.maxZoom);this._currentLogZ=Math.log(s),this._targetLogZ=this._currentLogZ,this._tx=e,this._ty=i,this._targetTx=null,this._targetTy=null,this._needsRender=!0}setTransformSmooth(t,e,i){const s=n(t,this._options.minZoom,this._options.maxZoom);this._targetLogZ=Math.log(s),this._targetTx=e,this._targetTy=i,this._needsRender=!0}_ensureOffscreenSizeLike(t,e){t.width===e.width&&t.height===e.height||(t.width=e.width,t.height=e.height)}_loop(){if(this._isResizing)return void(this._raf=requestAnimationFrame(()=>this._loop()));const t=performance.now(),e=Math.max(1,t-this._lastFrameTs);this._lastFrameTs=t;const{approachKZoom:i}=this._options,s=Math.exp(this._currentLogZ),n=this._targetLogZ-this._currentLogZ,h=Math.abs(n)>1e-6;if(h){const t=1-Math.exp(-i*e);this._currentLogZ+=n*t}const a=Math.exp(this._currentLogZ);if(a!==s){const t=this._anchorX,e=this._anchorY,i=a/s;this._tx=t-(t-this._tx)*i,this._ty=e-(e-this._ty)*i}let o=!1;if(null!==this._targetTx&&null!==this._targetTy){const t=1-Math.exp(-this._options.approachKPan*e),i=this._targetTx-this._tx,s=this._targetTy-this._ty;o=Math.abs(i)>.5||Math.abs(s)>.5,o?(this._tx+=i*t,this._ty+=s*t):(this._tx=this._targetTx,this._ty=this._targetTy,this._targetTx=null,this._targetTy=null)}if(this._isResetting){const t=1-Math.exp(-this._options.approachKPan*e);this._tx+=(0-this._tx)*t,this._ty+=(0-this._ty)*t;const i=Math.abs(this._currentLogZ)<.001&&Math.abs(this._targetLogZ)<1e-6,s=Math.abs(this._tx)<.5&&Math.abs(this._ty)<.5;i&&s&&(this._currentLogZ=0,this._targetLogZ=0,this._tx=0,this._ty=0,this._isResetting=!1)}for(const t of this._updateCallbacks)t(e);if(!(this._needsRender||h||o||this._isResetting))return void(this._raf=requestAnimationFrame(()=>this._loop()));this._needsRender=!1;const r=this.contentCanvas,c=this.contentContext,_=this.topScreenCanvas,l=this.topScreenContext,d=this.canvas,u=this.context;this._ensureOffscreenSizeLike(r,d),this._ensureOffscreenSizeLike(_,d),c.setTransform(1,0,0,1,0,0),l.setTransform(1,0,0,1,0,0),u.setTransform(1,0,0,1,0,0);const g=this._options.background;"string"==typeof g&&""!==g.trim()&&"transparent"!==g.toLowerCase()?(u.fillStyle=g,u.fillRect(0,0,d.width,d.height)):u.clearRect(0,0,d.width,d.height),c.clearRect(0,0,r.width,r.height),l.clearRect(0,0,_.width,_.height),c.setTransform(this._dpr*a,0,0,this._dpr*a,this._dpr*this._tx,this._dpr*this._ty);for(const t of this._beforeRenderCallbacks)t(c);this._render(this);for(const t of this._afterRenderCallbacks)t(c);u.drawImage(r,0,0),u.drawImage(_,0,0),this._raf=requestAnimationFrame(()=>this._loop())}applyWorldTransform(t){const e=Math.exp(this._currentLogZ);t.setTransform(this._dpr*e,0,0,this._dpr*e,this._dpr*this._tx,this._dpr*this._ty)}applyScreenTransform(t){t.setTransform(this._dpr,0,0,this._dpr,0,0)}getPixelColorAtScreen(t,e){const i=Math.floor(t*this._dpr),s=Math.floor(e*this._dpr);if(i<0||s<0||i>=this.canvas.width||s>=this.canvas.height)return{r:0,g:0,b:0,a:0,rgba:"rgba(0,0,0,0)",hex:"#000000"};const n=this.contentContext.getImageData(i,s,1,1).data,h=n[0],a=n[1],o=n[2],r=n[3]/255,c=t=>t.toString(16).padStart(2,"0"),_=`#${c(h)}${c(a)}${c(o)}`;return{r:h,g:a,b:o,a:r,rgba:`rgba(${h},${a},${o},${r.toFixed(3)})`,hex:_}}getPixelColorAtWorld(t,e){const{x:i,y:s}=this.toScreen(t,e);return this.getPixelColorAtScreen(i,s)}registerLayerManager(t){t&&(this._layerManagers.includes(t)||(this._layerManagers.push(t),this._needsRender=!0))}unregisterLayerManager(t){const e=this._layerManagers.indexOf(t);e>=0&&(this._layerManagers.splice(e,1),this._needsRender=!0)}getLayerManagers(){return[...this._layerManagers]}resetSmooth(){this._isResetting=!0,this._targetLogZ=0,this._needsRender=!0}resetInstant(){this._currentLogZ=0,this._targetLogZ=0,this._tx=0,this._ty=0,this._needsRender=!0}toWorld(t,e){const i=Math.exp(this._currentLogZ);return{wx:(t-this._tx)/i,wy:(e-this._ty)/i}}toScreen(t,e){const i=Math.exp(this._currentLogZ);return{x:t*i+this._tx,y:e*i+this._ty}}getTransform(){return{zoom:Math.exp(this._currentLogZ),tx:this._tx,ty:this._ty}}getViewportBounds(){const t=Math.exp(this._currentLogZ),e=this.canvas.width/this._dpr,i=this.canvas.height/this._dpr,s=-this._tx/t,n=-this._ty/t,h=(e-this._tx)/t,a=(i-this._ty)/t;return{left:s,top:n,right:h,bottom:a,width:h-s,height:a-n}}setZoomRange(t,e){this._options.minZoom=t,this._options.maxZoom=e,this.LOG_MIN=Math.log(t),this.LOG_MAX=Math.log(e),this._targetLogZ=Math.min(this.LOG_MAX,Math.max(this.LOG_MIN,this._targetLogZ))}resizeToParent(){this._isResizing=!0;const t=(this.canvas.parentElement||this.canvas).getBoundingClientRect();this._dpr=Math.max(1,window.devicePixelRatio||1);const e=Math.max(1,Math.round(t.width)),i=Math.max(1,Math.round(t.height));this.canvas.width=Math.round(e*this._dpr),this.canvas.height=Math.round(i*this._dpr),this.canvas.style.width=`${e}px`,this.canvas.style.height=`${i}px`,this._ensureOffscreenSizeLike(this.contentCanvas,this.canvas),this._ensureOffscreenSizeLike(this.topScreenCanvas,this.canvas),clearTimeout(this._resizeReleaseTimer),this._resizeReleaseTimer=window.setTimeout(()=>{this._isResizing=!1},50)}destroy(){cancelAnimationFrame(this._raf);for(const t of this._plugins.values())t.destroy();this._plugins.clear(),this._resizeObserver&&this._resizeObserver.disconnect(),this._layerManagers=[],this._updateCallbacks.clear(),this._beforeRenderCallbacks.clear(),this._afterRenderCallbacks.clear()}constructor(t,e,i){this._layerManagers=[],this._plugins=new Map,this._isResetting=!1,this._isResizing=!1,this._needsRender=!0,this._raf=0,this._lastFrameTs=performance.now(),this._tx=0,this._ty=0,this._anchorX=0,this._anchorY=0,this._currentLogZ=Math.log(1),this._targetLogZ=Math.log(1),this._targetTx=null,this._targetTy=null,this._updateCallbacks=new Set,this._beforeRenderCallbacks=new Set,this._afterRenderCallbacks=new Set,this._dpr=Math.max(1,window.devicePixelRatio||1);const s=t.getContext("2d",{willReadFrequently:!0,alpha:!0});if(!s)throw new Error("2D context not available");this.canvas=t,this.context=s,this._render=e,this.contentCanvas=document.createElement("canvas"),this.contentCanvas.width=t.width,this.contentCanvas.height=t.height,this.contentContext=this.contentCanvas.getContext("2d",{alpha:!0,willReadFrequently:!0}),this.topScreenCanvas=document.createElement("canvas"),this.topScreenCanvas.width=t.width,this.topScreenCanvas.height=t.height,this.topScreenContext=this.topScreenCanvas.getContext("2d",{alpha:!0}),this._options=Object.assign({minZoom:.5,maxZoom:10,approachKZoom:.022,approachKPan:.022,autoResize:!0,background:"#fff"},i),this.LOG_MIN=Math.log(this._options.minZoom),this.LOG_MAX=Math.log(this._options.maxZoom),this._options.autoResize&&(this._resizeObserver=new ResizeObserver(()=>this.resizeToParent()),this._resizeObserver.observe(this.canvas.parentElement||this.canvas)),this.resizeToParent(),this._lastFrameTs=performance.now(),this._raf=requestAnimationFrame(()=>this._loop())}},exports.createDocumentPlugin=function(t){return new d(t)},exports.createInteractionPlugin=function(t){return new l(t)},exports.createSnapshotCommand=function(t,e,i,s){return e&&i?new u(t,e,i,s):null};
1
+ "use strict";function t(t,e,i,s){return new(i||(i=Promise))(function(n,h){function a(t){try{r(s.next(t))}catch(t){h(t)}}function o(t){try{r(s.throw(t))}catch(t){h(t)}}function r(t){var e;t.done?n(t.value):(e=t.value,e instanceof i?e:new i(function(t){t(e)})).then(a,o)}r((s=s.apply(t,e||[])).next())})}function e(t,e,i,s){if("a"===i&&!s)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof e?t!==e||!s:!e.has(t))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===i?s:"a"===i?s.call(t):s?s.value:e.get(t)}function i(t,e,i,s,n){if("m"===s)throw new TypeError("Private method is not writable");if("a"===s&&!n)throw new TypeError("Private accessor was defined without a setter");if("function"==typeof e?t!==e||!n:!e.has(t))throw new TypeError("Cannot write private member to an object whose class did not declare it");return"a"===s?n.call(t,i):n?n.value=i:e.set(t,i),i}"function"==typeof SuppressedError&&SuppressedError;const s=(e,i)=>t(void 0,void 0,void 0,function*(){return new Promise((t,s)=>{const n=new Image;"string"==typeof e?(void 0!==i&&(n.crossOrigin=i),n.src=e):n.src=URL.createObjectURL(e),n.onload=()=>{t(n)},n.onerror=()=>{s(new Error("Image load failed"))}})}),n=(t,e,i)=>Math.min(Math.max(t,e),i);let h=0;class a{constructor(t,e,i="world"){this.space="world",this.visible=!0,this.opacity=1,this.blend="source-over",this.name=t,this.id=`layer_${e}_${++h}`,this.type=e,this.space=i}}class o extends a{beginStroke(t,e){const{lx:i,ly:s}=this.toLocalPoint(t,e);this._lastX=i,this._lastY=s,this._drawing=!0}stroke(t,e,i,s,n=1,h="brush"){if(!this._drawing)return;const{lx:a,ly:o}=this.toLocalPoint(t,e);this.context.beginPath(),this.context.moveTo(this._lastX,this._lastY),this.context.lineTo(a,o),"eraser"===h?(this.context.globalCompositeOperation="destination-out",this.context.strokeStyle="rgba(0, 0, 0, 1)"):(this.context.globalCompositeOperation="source-over",this.context.strokeStyle=i),this.context.lineWidth=s*n,this.context.lineCap="round",this.context.lineJoin="round",this.context.stroke(),this.context.closePath(),this._lastX=a,this._lastY=o}endStroke(){this._drawing=!1}isDrawing(){return this._drawing}captureSnapshot(t){try{if(t){const{x:e,y:i,width:s,height:n}=t,h=Math.max(0,Math.floor(e)),a=Math.max(0,Math.floor(i)),o=Math.min(this.canvas.width-h,Math.ceil(s)),r=Math.min(this.canvas.height-a,Math.ceil(n));return o<=0||r<=0?null:this.context.getImageData(h,a,o,r)}return this.context.getImageData(0,0,this.canvas.width,this.canvas.height)}catch(t){return null}}restoreSnapshot(t,e){var i,s;const n=null!==(i=null==e?void 0:e.x)&&void 0!==i?i:0,h=null!==(s=null==e?void 0:e.y)&&void 0!==s?s:0;this.context.putImageData(t,n,h)}clearRegion(t){t?this.context.clearRect(t.x,t.y,t.width,t.height):this.context.clearRect(0,0,this.canvas.width,this.canvas.height)}requestRedraw(){var t;null===(t=this._redraw)||void 0===t||t.call(this,this.context,this.canvas)}drawImage(t,e,i,s,n){this.context.drawImage(t,e,i,null!=s?s:t.width,null!=n?n:t.height)}hitTest(t,e){const{lx:i,ly:s}=this.toLocalPoint(t,e);return i>=0&&i<=this.canvas.width&&s>=0&&s<=this.canvas.height}toLocalPoint(t,e){const i=t-this.x,s=e-this.y,n=Math.cos(-this.rotation),h=Math.sin(-this.rotation),a=i*h+s*n,o=(i*n-s*h)/this.scale,r=a/this.scale;return{lx:o+("center"===this.anchor?this.canvas.width/2:0),ly:r+("center"===this.anchor?this.canvas.height/2:0)}}render(t,e){if(!this.visible)return;const i=this.canvas.width*this.scale,s=this.canvas.height*this.scale,n="center"===this.anchor?-i/2:0,h="center"===this.anchor?-s/2:0;t.save(),t.globalAlpha=this.opacity,t.globalCompositeOperation=this.blend,t.translate(this.x,this.y),t.rotate(this.rotation),t.drawImage(this.canvas,n,h,i,s),t.restore()}cropTo(t){const e=Math.max(1,Math.floor(t.width)),i=Math.max(1,Math.floor(t.height));if(e===this.canvas.width&&i===this.canvas.height)return;const s=this._cloneCanvas(),n=Math.min(s.width,e),h=Math.min(s.height,i);this._setCanvasSize(e,i),n>0&&h>0&&this.context.drawImage(s,0,0,n,h,0,0,n,h)}resizeTo(t){const e=Math.max(1,Math.floor(t.width)),i=Math.max(1,Math.floor(t.height));if(e===this.canvas.width&&i===this.canvas.height)return;const s=this._cloneCanvas();this._setCanvasSize(e,i),s.width>0&&s.height>0&&this.context.drawImage(s,0,0,s.width,s.height,0,0,e,i)}_cloneCanvas(){const t=document.createElement("canvas");if(t.width=this.canvas.width,t.height=this.canvas.height,0===t.width||0===t.height)return t;const e=t.getContext("2d");if(!e)throw new Error("Offscreen 2D context unavailable");return e.drawImage(this.canvas,0,0),t}_setCanvasSize(t,e){this.canvas.width=t,this.canvas.height=e,this.context.setTransform(1,0,0,1,0,0),this.context.clearRect(0,0,t,e)}destroy(){this.canvas.width=0,this.canvas.height=0}constructor(t){var e,i;if(super(t.name||"","canvas",null!==(e=t.space)&&void 0!==e?e:"world"),this.x=0,this.y=0,this.scale=1,this.rotation=0,this.anchor="topLeft",this._drawing=!1,this._lastX=0,this._lastY=0,"canvas"in t&&t.canvas)this.canvas=t.canvas;else{const e=t;this.canvas=document.createElement("canvas"),this.canvas.width=e.width,this.canvas.height=e.height}const s=this.canvas.getContext("2d",{willReadFrequently:!0});if(!s)throw new Error("Offscreen 2D context unavailable");this.context=s,this.x=t.x||0,this.y=t.y||0,this.scale=null!==(i=t.scale)&&void 0!==i?i:1,this.rotation=t.rotation||0,t.anchor&&(this.anchor=t.anchor),this._redraw=t.redraw,this._redraw&&this._redraw(this.context,this.canvas)}}var r;class c extends o{static fromImage(e){return t(this,void 0,void 0,function*(){var t,n,h,a,o,_,l,d;const u=yield s(e.src,e.crossOrigin),g=null!==(t=e.width)&&void 0!==t?t:u.naturalWidth,v=null!==(n=e.height)&&void 0!==n?n:u.naturalHeight,p=new c({name:e.name,space:null!==(h=e.space)&&void 0!==h?h:"world",x:null!==(a=e.x)&&void 0!==a?a:0,y:null!==(o=e.y)&&void 0!==o?o:0,scale:null!==(_=e.scale)&&void 0!==_?_:1,rotation:null!==(l=e.rotation)&&void 0!==l?l:0,anchor:null!==(d=e.anchor)&&void 0!==d?d:"topLeft",width:g,height:v});return p.context.clearRect(0,0,p.canvas.width,p.canvas.height),p.context.drawImage(u,0,0,g,v),"string"!=typeof e.src&&i(p,r,u.src.startsWith("blob:")?u.src:null,"f"),p})}setSource(n,h){return t(this,void 0,void 0,function*(){const t=yield s(n,h);if(this.canvas.width=t.naturalWidth,this.canvas.height=t.naturalHeight,this.context.setTransform(1,0,0,1,0,0),this.context.clearRect(0,0,this.canvas.width,this.canvas.height),this.context.drawImage(t,0,0),e(this,r,"f")){try{URL.revokeObjectURL(e(this,r,"f"))}catch(t){}i(this,r,null,"f")}"string"!=typeof n&&i(this,r,t.src.startsWith("blob:")?t.src:null,"f")})}paint(t){t(this.context,this.canvas)}getImageData(t=0,e=0,i=this.canvas.width,s=this.canvas.height){return this.context.getImageData(t,e,i,s)}putImageData(t,e=0,i=0){this.context.putImageData(t,e,i)}toDataURL(t="image/png",e){return this.canvas.toDataURL(t,e)}toImageBitmap(t){return createImageBitmap(this.canvas,null!=t?t:{})}destroy(){var t;if(null===(t=super.destroy)||void 0===t||t.call(this),e(this,r,"f")){try{URL.revokeObjectURL(e(this,r,"f"))}catch(t){}i(this,r,null,"f")}}constructor(t){var e,i;super({name:t.name,space:null!==(e=t.space)&&void 0!==e?e:"world",x:t.x,y:t.y,scale:t.scale,rotation:t.rotation,anchor:null!==(i=t.anchor)&&void 0!==i?i:"topLeft",width:t.width,height:t.height}),r.set(this,null),this.type="bitmap"}}r=new WeakMap;class _{constructor(){this._worldLayers=[],this._screenLayers=[]}_renderAllLayersIn(t,e){e.save(),t.applyWorldTransform(e);for(const i of this._worldLayers)!i.visible||i.opacity<=0||(e.save(),i.render(e,t),e.restore());e.restore(),e.save(),t.applyScreenTransform(e);for(const i of this._screenLayers)!i.visible||i.opacity<=0||(e.save(),i.render(e,t),e.restore());e.restore()}renderAllLayersIn(t){const e=t.contentContext;this._renderAllLayersIn(t,e)}addLayer(t,e){const i="world"===t.space?this._worldLayers:this._screenLayers;return"number"==typeof e&&e>=0&&e<i.length?(i.splice(e,0,t),t.id):(i.push(t),t.id)}createImageLayer(e){return t(this,void 0,void 0,function*(){const t=yield c.fromImage(e);return this.addLayer(t),t})}createCanvasLayer(t){const e=new o(t);return this.addLayer(e),e}removeLayer(t){var e,i,s,n;const h=this._worldLayers.findIndex(e=>e.id===t);if(h>=0)return null===(i=(e=this._worldLayers[h]).destroy)||void 0===i||i.call(e),void this._worldLayers.splice(h,1);const a=this._screenLayers.findIndex(e=>e.id===t);a>=0&&(null===(n=(s=this._screenLayers[a]).destroy)||void 0===n||n.call(s),this._screenLayers.splice(a,1))}detachLayer(t){const e=this._worldLayers.findIndex(e=>e.id===t);if(e>=0)return void this._worldLayers.splice(e,1);const i=this._screenLayers.findIndex(e=>e.id===t);i>=0&&this._screenLayers.splice(i,1)}moveLayer(t,e){const i=this._worldLayers.findIndex(e=>e.id===t);if(i>=0){const[t]=this._worldLayers.splice(i,1),s=Math.max(0,Math.min(e,this._worldLayers.length));return void this._worldLayers.splice(s,0,t)}const s=this._screenLayers.findIndex(e=>e.id===t);if(s>=0){const[t]=this._screenLayers.splice(s,1),i=Math.max(0,Math.min(e,this._screenLayers.length));this._screenLayers.splice(i,0,t)}}reorderLayers(t){const e=[];for(const i of t){const t=this._worldLayers.find(t=>t.id===i);t&&e.push(t)}for(const i of this._worldLayers)t.includes(i.id)||e.push(i);this._worldLayers=e}getLayer(t){return this._worldLayers.find(e=>e.id===t)||this._screenLayers.find(e=>e.id===t)}getAllLayers(t){return t?("world"===t?this._worldLayers:this._screenLayers).slice():[...this._worldLayers,...this._screenLayers]}hitTest(t,e,i="world"){const s=this.getAllLayers(i);for(let i=s.length-1;i>=0;i--){const n=s[i];if(n.hitTest&&n.hitTest(t,e))return n}}destroy(){var t;for(const e of[...this._worldLayers,...this._screenLayers])null===(t=e.destroy)||void 0===t||t.call(e);this._worldLayers=[],this._screenLayers=[]}}class l{constructor(t){this.name="interaction",this._view=null,this._dragging=!1,this._vx=0,this._vy=0,this._lastMoveTs=0,this._activePointerId=null,this._lastPointerX=0,this._lastPointerY=0,this._touchPointers=new Map,this._isTouchPanning=!1,this._isPinching=!1,this._lastPinchDistance=0,this._lastPinchCenterX=0,this._lastPinchCenterY=0,this._lastTouchX=0,this._lastTouchY=0,this._onDownBound=t=>this._onPointerDown(t),this._onMoveBound=t=>this._onPointerMove(t),this._onUpBound=t=>this._onPointerUp(t),this._onCancelBound=t=>this._onPointerCancel(t),this._onWheelBound=t=>this._onWheel(t),this._onUpdate=t=>{if(!this._view)return;const{friction:e,stopSpeed:i}=this._options,s=Math.hypot(this._vx,this._vy)>=i;if(!(this._dragging||this._isTouchPanning||this._isPinching)&&s){const s=this._vx*t,n=this._vy*t;this._view.panBy(s,n),this._vx*=e,this._vy*=e,Math.hypot(this._vx,this._vy)<i&&(this._vx=0,this._vy=0)}},this._options=Object.assign({panEnabled:!0,zoomEnabled:!0,friction:.92,stopSpeed:.02,emaAlpha:.25,idleNoInertiaMs:120,wheelSensitivity:.0015},t),this._panEnabled=this._options.panEnabled,this._zoomEnabled=this._options.zoomEnabled}install(t){this._view=t;const e=t.canvas;e.style.touchAction="none",e.addEventListener("wheel",this._onWheelBound,{passive:!1}),e.addEventListener("pointerdown",this._onDownBound),window.addEventListener("pointermove",this._onMoveBound),window.addEventListener("pointerup",this._onUpBound),window.addEventListener("pointercancel",this._onCancelBound),t.onUpdate(this._onUpdate)}destroy(){if(!this._view)return;const t=this._view.canvas;t.removeEventListener("wheel",this._onWheelBound),t.removeEventListener("pointerdown",this._onDownBound),window.removeEventListener("pointermove",this._onMoveBound),window.removeEventListener("pointerup",this._onUpBound),window.removeEventListener("pointercancel",this._onCancelBound),this._touchPointers.clear(),this._isPinching=!1,this._isTouchPanning=!1,this._view.offUpdate(this._onUpdate),this._view=null}isPanEnabled(){return this._panEnabled}isZoomEnabled(){return this._zoomEnabled}setPanEnabled(t){this._panEnabled!==t&&(this._panEnabled=t,t||null===this._activePointerId||(this._dragging=!1,this._vx=0,this._vy=0))}setZoomEnabled(t){this._zoomEnabled!==t&&(this._zoomEnabled=t,!t&&this._isPinching&&this._endPinch())}setWheelSensitivity(t){this._options.wheelSensitivity=t}isDragging(){return this._dragging||this._isTouchPanning||this._isPinching}_onPointerDown(t){var e,i;if(!(null===(e=this._view)||void 0===e?void 0:e.isAnimating))if("touch"!==t.pointerType){if(("mouse"!==t.pointerType||0===t.button)&&this._panEnabled&&null===this._activePointerId){t.preventDefault(),this._dragging=!0,this._vx=0,this._vy=0,this._lastMoveTs=performance.now(),this._activePointerId=t.pointerId,this._lastPointerX=t.clientX,this._lastPointerY=t.clientY;try{null===(i=this._view)||void 0===i||i.canvas.setPointerCapture(t.pointerId)}catch(t){}}}else this._onTouchDown(t)}_onPointerMove(t){var e;if(null===(e=this._view)||void 0===e?void 0:e.isAnimating)return;if("touch"===t.pointerType)return void this._onTouchMove(t);if(t.pointerId!==this._activePointerId)return;if(!this._dragging||!this._panEnabled||!this._view)return;const i=performance.now(),s=Math.max(1,i-(this._lastMoveTs||i-16));this._lastMoveTs=i;const n=t.clientX-this._lastPointerX,h=t.clientY-this._lastPointerY;this._lastPointerX=t.clientX,this._lastPointerY=t.clientY,this._view.panBy(n,h);const a=this._options.emaAlpha,o=n/s,r=h/s;this._vx=(1-a)*this._vx+a*o,this._vy=(1-a)*this._vy+a*r}_onPointerUp(t){if("touch"===t.pointerType)return void this._onTouchUp(t);if(t.pointerId!==this._activePointerId)return;if(!this._dragging)return;this._dragging=!1;const e=performance.now(),i=this._lastMoveTs?e-this._lastMoveTs:1/0;if(null!=this._activePointerId&&this._view){try{this._view.canvas.releasePointerCapture(this._activePointerId)}catch(t){}this._activePointerId=null}if(i>=this._options.idleNoInertiaMs)this._vx=0,this._vy=0;else{const t=Math.pow(this._options.friction,i/16);this._vx*=t,this._vy*=t}Math.hypot(this._vx,this._vy)<this._options.stopSpeed&&(this._vx=0,this._vy=0)}_onPointerCancel(t){"touch"!==t.pointerType?t.pointerId===this._activePointerId&&(this._dragging=!1,this._vx=0,this._vy=0,this._activePointerId=null):this._onTouchCancel(t)}_onTouchDown(t){if(t.preventDefault(),this._touchPointers.set(t.pointerId,{x:t.clientX,y:t.clientY}),2===this._touchPointers.size&&this._zoomEnabled)return this._isTouchPanning=!1,void this._startPinch();1===this._touchPointers.size&&(this._isTouchPanning=!0,this._vx=0,this._vy=0,this._lastMoveTs=performance.now(),this._lastTouchX=t.clientX,this._lastTouchY=t.clientY)}_onTouchMove(t){if(this._touchPointers.has(t.pointerId))if(this._touchPointers.set(t.pointerId,{x:t.clientX,y:t.clientY}),this._isPinching&&2===this._touchPointers.size)this._handlePinchMove();else if(this._isTouchPanning&&1===this._touchPointers.size&&this._view){const e=performance.now(),i=Math.max(1,e-(this._lastMoveTs||e-16));this._lastMoveTs=e;const s=t.clientX-this._lastTouchX,n=t.clientY-this._lastTouchY;this._lastTouchX=t.clientX,this._lastTouchY=t.clientY,this._view.panBy(s,n);const h=this._options.emaAlpha,a=s/i,o=n/i;this._vx=(1-h)*this._vx+h*a,this._vy=(1-h)*this._vy+h*o}}_onTouchUp(t){if(this._touchPointers.delete(t.pointerId),this._isPinching){if(this._endPinch(),1===this._touchPointers.size){const[[,t]]=this._touchPointers.entries();this._isTouchPanning=!0,this._lastTouchX=t.x,this._lastTouchY=t.y,this._vx=0,this._vy=0,this._lastMoveTs=performance.now()}}else if(this._isTouchPanning&&0===this._touchPointers.size){this._isTouchPanning=!1;const t=performance.now(),e=this._lastMoveTs?t-this._lastMoveTs:1/0;if(e>=this._options.idleNoInertiaMs)this._vx=0,this._vy=0;else{const t=Math.pow(this._options.friction,e/16);this._vx*=t,this._vy*=t}Math.hypot(this._vx,this._vy)<this._options.stopSpeed&&(this._vx=0,this._vy=0)}}_onTouchCancel(t){this._touchPointers.delete(t.pointerId),this._isPinching&&this._endPinch(),0===this._touchPointers.size&&(this._isTouchPanning=!1,this._vx=0,this._vy=0)}_startPinch(){this._isPinching=!0;const[t,e]=Array.from(this._touchPointers.values());this._lastPinchDistance=Math.hypot(e.x-t.x,e.y-t.y),this._lastPinchCenterX=(t.x+e.x)/2,this._lastPinchCenterY=(t.y+e.y)/2}_handlePinchMove(){if(!this._view||!this._zoomEnabled)return;const t=Array.from(this._touchPointers.values());if(2!==t.length)return;const[e,i]=t,s=Math.hypot(i.x-e.x,i.y-e.y),n=(e.x+i.x)/2,h=(e.y+i.y)/2;if(this._lastPinchDistance>0){const t=s/this._lastPinchDistance,e=this._view.canvas.getBoundingClientRect(),i=n-e.left,a=h-e.top;this._view.zoomByFactorAtScreen(i,a,t);const o=n-this._lastPinchCenterX,r=h-this._lastPinchCenterY;this._view.panBy(o,r)}this._lastPinchDistance=s,this._lastPinchCenterX=n,this._lastPinchCenterY=h}_endPinch(){this._isPinching=!1,this._lastPinchDistance=0,this._lastPinchCenterX=0,this._lastPinchCenterY=0}_getLineHeightPx(){if(!this._view)return 16;const t=getComputedStyle(this._view.canvas).lineHeight;if(!t||"normal"===t)return 16;const e=parseFloat(t);return Number.isFinite(e)?e:16}_normalizeWheelDelta(t){if(!this._view)return 0;let e=t.deltaY;if(1===t.deltaMode)e*=this._getLineHeightPx();else if(2===t.deltaMode){e*=this._view.canvas.clientHeight||window.innerHeight||800}return e}_onWheel(t){var e;if(null===(e=this._view)||void 0===e?void 0:e.isAnimating)return;if(!this._zoomEnabled||!this._view)return;t.preventDefault(),t.stopPropagation();const i=this._normalizeWheelDelta(t),s=this._view.canvas.getBoundingClientRect(),n=t.clientX-s.left,h=t.clientY-s.top;let a=-i*this._options.wheelSensitivity;t.ctrlKey||t.metaKey?a*=1.6:t.shiftKey&&(a*=.6),this._view.zoomByLogAtScreen(n,h,a)}}class d{constructor(t){var e,i,s,n,h;this.name="bounds",this._view=null,this._enabled=!1,this._x=0,this._y=0,this._width=0,this._height=0,this._marginL=0,this._marginR=0,this._marginT=0,this._marginB=0,this._panClampMode="minVisible",this._background=null,this._shadow=null,this._onUpdate=()=>{this._enabled&&this._view&&this._clampPan()},this._onBeforeRender=t=>{var e,i,s,n,h;this._enabled&&this._view&&(this._shadow?(t.save(),t.shadowColor=null!==(e=this._shadow.color)&&void 0!==e?e:d._defaultShadow.color,t.shadowBlur=null!==(i=this._shadow.blur)&&void 0!==i?i:d._defaultShadow.blur,t.shadowOffsetX=null!==(s=this._shadow.offsetX)&&void 0!==s?s:d._defaultShadow.offsetX,t.shadowOffsetY=null!==(n=this._shadow.offsetY)&&void 0!==n?n:d._defaultShadow.offsetY,t.fillStyle=null!==(h=this._background)&&void 0!==h?h:"#ffffff",t.fillRect(this._x,this._y,this._width,this._height),t.restore()):this._background&&(t.save(),t.fillStyle=this._background,t.fillRect(this._x,this._y,this._width,this._height),t.restore()),t.save(),t.beginPath(),t.rect(this._x,this._y,this._width,this._height),t.clip())},this._onAfterRender=t=>{if(this._enabled&&this._view&&(t.restore(),this._options.drawBorder)){const e=this._view.zoom;t.save(),t.lineWidth=1/e,t.strokeStyle="#cfcfcf",t.strokeRect(this._x,this._y,this._width,this._height),t.restore()}},this._options=Object.assign({rect:{x:0,y:0,width:0,height:0},margins:{},drawBorder:!1,minVisiblePx:30,panClampMode:"minVisible",background:null,shadow:!1},t),(null==t?void 0:t.rect)&&(this._enabled=!0,this._x=t.rect.x,this._y=t.rect.y,this._width=t.rect.width,this._height=t.rect.height),(null==t?void 0:t.margins)&&(this._marginL=null!==(e=t.margins.left)&&void 0!==e?e:0,this._marginR=null!==(i=t.margins.right)&&void 0!==i?i:0,this._marginT=null!==(s=t.margins.top)&&void 0!==s?s:0,this._marginB=null!==(n=t.margins.bottom)&&void 0!==n?n:0),this._panClampMode=this._options.panClampMode,this._background=null!==(h=this._options.background)&&void 0!==h?h:null,!0===this._options.shadow?this._shadow=Object.assign({},d._defaultShadow):this._options.shadow&&"object"==typeof this._options.shadow&&(this._shadow=Object.assign(Object.assign({},d._defaultShadow),this._options.shadow))}install(t){this._view=t,t.onUpdate(this._onUpdate),t.onBeforeRender(this._onBeforeRender),t.onAfterRender(this._onAfterRender)}destroy(){this._view&&(this._view.offUpdate(this._onUpdate),this._view.offBeforeRender(this._onBeforeRender),this._view.offAfterRender(this._onAfterRender),this._view=null)}isEnabled(){return this._enabled}getRect(){return{x:this._x,y:this._y,width:this._width,height:this._height}}setRect(t,e,i,s){this._enabled=!0,this._x=t,this._y=e,this._width=i,this._height=s}clearRect(){this._enabled=!1}setMargins(t){var e,i,s,n;this._marginL=null!==(e=t.left)&&void 0!==e?e:this._marginL,this._marginR=null!==(i=t.right)&&void 0!==i?i:this._marginR,this._marginT=null!==(s=t.top)&&void 0!==s?s:this._marginT,this._marginB=null!==(n=t.bottom)&&void 0!==n?n:this._marginB}getMargins(){return{left:this._marginL,right:this._marginR,top:this._marginT,bottom:this._marginB}}setPanClampMode(t){this._panClampMode=t}getPanClampMode(){return this._panClampMode}cropTo(t){this._doResize("crop",t)}resizeTo(t){this._doResize("resize",t)}zoomToFit(t){var e,i,s;const n=null!==(e=null==t?void 0:t.mode)&&void 0!==e?e:"contain",h=null===(i=null==t?void 0:t.animate)||void 0===i||i,a=null!==(s=null==t?void 0:t.maxScale)&&void 0!==s?s:1/0;if(!this._enabled||!this._view)return;const o=this._view.dpr,r=this._view.canvas.width/o,c=this._view.canvas.height/o,_=Math.max(1,r-(this._marginL+this._marginR)),l=Math.max(1,c-(this._marginT+this._marginB));let d;const u=_/this._width,g=l/this._height;d="contain"===n?Math.min(u,g):"cover"===n?Math.max(u,g):"fitWidth"===n?u:g,d=Math.min(d,a),d=Math.min(this._view.maxZoom,Math.max(this._view.minZoom,d));const v=this._marginL+(_-d*this._width)/2,p=this._marginT+(l-d*this._height)/2,m=v-d*this._x,y=p-d*this._y;h?this._view.setTransformSmooth(d,m,y):this._view.setTransform(d,m,y)}isPointInBounds(t,e){return!this._enabled||t>=this._x&&t<=this._x+this._width&&e>=this._y&&e<=this._y+this._height}get background(){return this._background}setBackground(t){var e;this._background=t,null===(e=this._view)||void 0===e||e.requestRender()}get shadow(){return this._shadow?Object.assign({},this._shadow):null}setShadow(t){var e;this._shadow=!0===t?Object.assign({},d._defaultShadow):t&&"object"==typeof t?Object.assign(Object.assign({},d._defaultShadow),t):null,null===(e=this._view)||void 0===e||e.requestRender()}_clampPan(){if(!this._view)return;const{zoom:t,tx:e,ty:i}=this._view.getTransform(),s=t,n=this._view.dpr,h=this._view.canvas.width/n,a=this._view.canvas.height/n,o=this._x,r=this._y,c=this._x+this._width,_=this._y+this._height;let l=e,d=i;if("margin"===this._panClampMode){const t=this._marginL-s*o,n=h-this._marginR-s*c,u=this._marginT-s*r,g=a-this._marginB-s*_,v=Math.max(1,h-(this._marginL+this._marginR)),p=Math.max(1,a-(this._marginT+this._marginB));l=s*this._width<=v?this._marginL+(v-s*this._width)/2-s*this._x:Math.min(t,Math.max(n,e)),d=s*this._height<=p?this._marginT+(p-s*this._height)/2-s*this._y:Math.min(u,Math.max(g,i))}else if("minVisible"===this._panClampMode){const t=s*this._width,n=s*this._height,u=Math.min(this._options.minVisiblePx,t),g=Math.min(this._options.minVisiblePx,n),v=h-u-s*o,p=u-s*c,m=a-g-s*r,y=g-s*_;l=p<=v?Math.min(v,Math.max(p,e)):(p+v)/2,d=y<=m?Math.min(m,Math.max(y,i)):(y+m)/2}l===e&&d===i||this._view.setPan(l,d)}_doResize(t,e){if(!this._view)return;const i=Math.max(1,Math.floor(e.width)),s=Math.max(1,Math.floor(e.height)),n={width:i,height:s},h=this._view.getLayerManagers();for(const e of h){const i=e.getAllLayers("world");for(const e of i){const i=e;"function"==typeof i.cropTo&&"function"==typeof i.resizeTo&&("crop"===t?i.cropTo(n):i.resizeTo(n))}}this._width=i,this._height=s,this._enabled&&this._clampPan()}}d._defaultShadow={color:"rgba(0, 0, 0, 0.3)",blur:20,offsetX:0,offsetY:4};class u{constructor(t,e,i,s){this.type="snapshot",this._isExecuted=!0,this._target=t,this._beforeData=e,this._afterData=i,this._region=null==s?void 0:s.region}execute(){if(this._isExecuted)return;const t=this._region?{x:this._region.x,y:this._region.y}:void 0;this._target.restoreSnapshot(this._afterData,t),this._isExecuted=!0}undo(){if(!this._isExecuted)return;const t=this._region?{x:this._region.x,y:this._region.y}:void 0;this._target.restoreSnapshot(this._beforeData,t),this._isExecuted=!1}canMerge(){return!1}merge(){return this}}exports.BitmapLayer=c,exports.BoundsPlugin=d,exports.CanvasLayer=o,exports.ContentLayerManager=class extends _{constructor(){super(...arguments),this._compositeCache=null,this._compositeCacheCtx=null,this._compositeDirty=!0,this._lastCacheWidth=0,this._lastCacheHeight=0,this._cachedBoundsMinX=0,this._cachedBoundsMinY=0}markDirty(){this._compositeDirty=!0}addLayer(t,e){return this._compositeDirty=!0,super.addLayer(t,e)}removeLayer(t){this._compositeDirty=!0,super.removeLayer(t)}detachLayer(t){this._compositeDirty=!0,super.detachLayer(t)}removeAllLayers(t){var e,i;if(!t||"world"===t){for(const t of this._worldLayers)null===(e=t.destroy)||void 0===e||e.call(t);this._worldLayers=[]}if(!t||"screen"===t){for(const t of this._screenLayers)null===(i=t.destroy)||void 0===i||i.call(t);this._screenLayers=[]}}moveLayer(t,e){this._compositeDirty=!0,super.moveLayer(t,e)}renderAllLayersIn(t){const e=t.contentContext,i=this._worldLayers;0!==i.length&&(this._compositeDirty&&this._rebuildCompositeCache(i),this._compositeCache&&this._compositeCacheCtx&&e.drawImage(this._compositeCache,this._cachedBoundsMinX,this._cachedBoundsMinY))}_rebuildCompositeCache(t){let e=0,i=0,s=0,n=0,h=!1;for(const a of t){const t=a,o=t.canvas.width*t.scale,r=t.canvas.height*t.scale,c="center"===t.anchor?-o/2:0,_="center"===t.anchor?-r/2:0,l=Math.cos(t.rotation),d=Math.sin(t.rotation),u=[{x:c,y:_},{x:c+o,y:_},{x:c,y:_+r},{x:c+o,y:_+r}];let g=1/0,v=1/0,p=-1/0,m=-1/0;for(const e of u){const i=e.x*l-e.y*d+t.x,s=e.x*d+e.y*l+t.y;g=Math.min(g,i),v=Math.min(v,s),p=Math.max(p,i),m=Math.max(m,s)}h?(e=Math.min(e,g),i=Math.min(i,v),s=Math.max(s,p),n=Math.max(n,m)):(e=g,i=v,s=p,n=m,h=!0)}if(!h)return void(this._compositeDirty=!1);const a=Math.ceil(s-e),o=Math.ceil(n-i);this._compositeCache||(this._compositeCache=document.createElement("canvas"),this._compositeCacheCtx=this._compositeCache.getContext("2d",{alpha:!0})),this._lastCacheWidth===a&&this._lastCacheHeight===o||(this._compositeCache.width=a,this._compositeCache.height=o,this._lastCacheWidth=a,this._lastCacheHeight=o),this._cachedBoundsMinX=e,this._cachedBoundsMinY=i;const r=this._compositeCacheCtx;r.clearRect(0,0,a,o),r.save(),r.translate(-e,-i);for(const e of t)!e.visible||e.opacity<=0||(r.save(),e.render(r),r.restore());r.restore(),this._compositeDirty=!1}destroy(){super.destroy(),this._compositeCache=null,this._compositeCacheCtx=null}},exports.CreateLayerCommand=class{constructor(t){this.type="create-layer",this._layer=t.layer,this._layerManager=t.layerManager,this._insertIndex=t.insertIndex,this._previousSelectedId=t.previousSelectedId,this._getLayerList=t.getLayerList,this._setSelectedId=t.setSelectedId}execute(){this._layerManager.addLayer(this._layer,this._insertIndex);this._getLayerList().splice(this._insertIndex,0,this._layer),this._setSelectedId(this._layer.id)}undo(){this._layerManager.detachLayer(this._layer.id);const t=this._getLayerList(),e=t.findIndex(t=>t.id===this._layer.id);e>-1&&t.splice(e,1),this._setSelectedId(this._previousSelectedId)}},exports.DeleteLayerCommand=class{constructor(t){this.type="delete-layer",this._layer=t.layer,this._layerManager=t.layerManager,this._originalIndex=t.originalIndex,this._previousSelectedId=t.previousSelectedId,this._newSelectedId=t.newSelectedId,this._getLayerList=t.getLayerList,this._setSelectedId=t.setSelectedId}execute(){this._layerManager.detachLayer(this._layer.id);const t=this._getLayerList(),e=t.findIndex(t=>t.id===this._layer.id);e>-1&&t.splice(e,1),this._setSelectedId(this._newSelectedId)}undo(){this._layerManager.addLayer(this._layer,this._originalIndex);this._getLayerList().splice(this._originalIndex,0,this._layer),this._setSelectedId(this._previousSelectedId)}},exports.HistoryManager=class{executeCommand(t){t.execute(),this.addCommand(t)}addCommand(t){var e,i;this._redoStack.splice(0,this._redoStack.length);const s=this._undoStack[this._undoStack.length-1];if(s&&(null===(e=s.canMerge)||void 0===e?void 0:e.call(s,t))&&s.merge){const e=null!==(i=s.merge(t))&&void 0!==i?i:s;return void(e!==s&&(this._undoStack[this._undoStack.length-1]=e))}this._undoStack.push(t),this._undoStack.length>this._maxHistorySize&&this._undoStack.shift()}undo(){if(0===this._undoStack.length)return null;const t=this._undoStack.pop();return t.undo(),this._redoStack.push(t),t}redo(){if(0===this._redoStack.length)return null;const t=this._redoStack.pop();return t.execute(),this._undoStack.push(t),t}canUndo(){return this._undoStack.length>0}canRedo(){return this._redoStack.length>0}clear(){this._undoStack.splice(0,this._undoStack.length),this._redoStack.splice(0,this._redoStack.length)}setMaxHistorySize(t){if(this._maxHistorySize=Math.max(1,t),this._undoStack.length>this._maxHistorySize){const t=this._undoStack.length-this._maxHistorySize;this._undoStack.splice(0,t)}}constructor(t){var e,i,s;this._undoStack=[],this._redoStack=[],this._maxHistorySize=null!==(e=null==t?void 0:t.maxHistorySize)&&void 0!==e?e:50,this._undoStack=null!==(i=null==t?void 0:t.undoStack)&&void 0!==i?i:[],this._redoStack=null!==(s=null==t?void 0:t.redoStack)&&void 0!==s?s:[]}},exports.InteractionPlugin=l,exports.LayerBase=a,exports.LayerManagerBase=_,exports.SnapshotCommand=u,exports.TopScreenLayerManager=class extends _{renderAllLayersIn(t){const e=t.topScreenContext;this._renderAllLayersIn(t,e)}},exports.ViewManager=class{get zoom(){return Math.exp(this._currentLogZ)}get minZoom(){return this._options.minZoom}get maxZoom(){return this._options.maxZoom}get isAnimating(){return this._isAnimatingTransform}get dpr(){return this._dpr}use(t){return this._plugins.has(t.name)?(console.warn(`Plugin "${t.name}" is already installed.`),t):(this._plugins.set(t.name,t),t.install(this),t)}unuse(t){const e=this._plugins.get(t);e&&(e.destroy(),this._plugins.delete(t))}getPlugin(t){return this._plugins.get(t)}onUpdate(t){this._updateCallbacks.add(t)}offUpdate(t){this._updateCallbacks.delete(t)}onBeforeRender(t){this._beforeRenderCallbacks.add(t)}offBeforeRender(t){this._beforeRenderCallbacks.delete(t)}onAfterRender(t){this._afterRenderCallbacks.add(t)}offAfterRender(t){this._afterRenderCallbacks.delete(t)}requestRender(){this._needsRender=!0}_clampLog(t){return n(t,this.LOG_MIN,this.LOG_MAX)}_setTargetLogZoomAtScreen(t,e,i){Number.isFinite(i)&&(this._anchorX=t,this._anchorY=e,this._targetLogZ=this._clampLog(i),this._needsRender=!0)}zoomToAtScreen(t,e,i){this._setTargetLogZoomAtScreen(t,e,Math.log(i))}zoomToAtScreenRaw(t,e,i){if(!Number.isFinite(i))return;const s=Math.max(1e-8,this._options.minZoom),h=this._options.maxZoom,a=n(i,s,h),o=Math.exp(this._currentLogZ),r=a;if(!Number.isFinite(o)||o<=0)return;if(Math.abs(r-o)<1e-12)return;const c=Math.log(a);this._currentLogZ=c,this._targetLogZ=c;const _=r/o;this._tx=t-(t-this._tx)*_,this._ty=e-(e-this._ty)*_,this._needsRender=!0}zoomToAtWorld(t,e,i){const{x:s,y:n}=this.toScreen(t,e);this.zoomToAtScreen(s,n,i)}zoomByFactorAtScreen(t,e,i){if(i<=0||!Number.isFinite(i))return;const s=Math.log(i);this._setTargetLogZoomAtScreen(t,e,this._targetLogZ+s)}zoomByLogAtScreen(t,e,i){this._setTargetLogZoomAtScreen(t,e,this._targetLogZ+i)}zoomByFactorAtWorld(t,e,i){const{x:s,y:n}=this.toScreen(t,e);this.zoomByFactorAtScreen(s,n,i)}panBy(t,e){this._tx+=t,this._ty+=e,this._needsRender=!0}setPan(t,e){this._tx=t,this._ty=e,this._needsRender=!0}setTransform(t,e,i){const s=n(t,this._options.minZoom,this._options.maxZoom);this._currentLogZ=Math.log(s),this._targetLogZ=this._currentLogZ,this._tx=e,this._ty=i,this._targetTx=null,this._targetTy=null,this._needsRender=!0}setTransformSmooth(t,e,i){const s=n(t,this._options.minZoom,this._options.maxZoom);this._targetLogZ=Math.log(s),this._targetTx=e,this._targetTy=i,this._isAnimatingTransform=!0,this._needsRender=!0}_ensureOffscreenSizeLike(t,e){t.width===e.width&&t.height===e.height||(t.width=e.width,t.height=e.height)}_loop(){if(this._isResizing)return void(this._raf=requestAnimationFrame(()=>this._loop()));const t=performance.now(),e=Math.max(1,t-this._lastFrameTs);this._lastFrameTs=t;const{approachKZoom:i}=this._options,s=Math.exp(this._currentLogZ),n=this._targetLogZ-this._currentLogZ,h=Math.abs(n)>1e-6;if(h){const t=1-Math.exp(-i*e);this._currentLogZ+=n*t}const a=Math.exp(this._currentLogZ);if(a!==s){const t=this._anchorX,e=this._anchorY,i=a/s;this._tx=t-(t-this._tx)*i,this._ty=e-(e-this._ty)*i}let o=!1;if(null!==this._targetTx&&null!==this._targetTy){const t=1-Math.exp(-this._options.approachKPan*e),i=this._targetTx-this._tx,s=this._targetTy-this._ty;o=Math.abs(i)>.5||Math.abs(s)>.5,o?(this._tx+=i*t,this._ty+=s*t):(this._tx=this._targetTx,this._ty=this._targetTy,this._targetTx=null,this._targetTy=null)}if(this._isAnimatingTransform){const t=Math.abs(this._targetLogZ-this._currentLogZ)<1e-5,e=null===this._targetTx&&null===this._targetTy;t&&e&&(this._isAnimatingTransform=!1)}if(this._isResetting){const t=1-Math.exp(-this._options.approachKPan*e);this._tx+=(0-this._tx)*t,this._ty+=(0-this._ty)*t;const i=Math.abs(this._currentLogZ)<.001&&Math.abs(this._targetLogZ)<1e-6,s=Math.abs(this._tx)<.5&&Math.abs(this._ty)<.5;i&&s&&(this._currentLogZ=0,this._targetLogZ=0,this._tx=0,this._ty=0,this._isResetting=!1)}for(const t of this._updateCallbacks)t(e);if(!(this._needsRender||h||o||this._isResetting))return void(this._raf=requestAnimationFrame(()=>this._loop()));this._needsRender=!1;const r=this.contentCanvas,c=this.contentContext,_=this.topScreenCanvas,l=this.topScreenContext,d=this.canvas,u=this.context;this._ensureOffscreenSizeLike(r,d),this._ensureOffscreenSizeLike(_,d),c.setTransform(1,0,0,1,0,0),l.setTransform(1,0,0,1,0,0),u.setTransform(1,0,0,1,0,0);const g=this._options.background;"string"==typeof g&&""!==g.trim()&&"transparent"!==g.toLowerCase()?(u.fillStyle=g,u.fillRect(0,0,d.width,d.height)):u.clearRect(0,0,d.width,d.height),c.clearRect(0,0,r.width,r.height),l.clearRect(0,0,_.width,_.height),c.setTransform(this._dpr*a,0,0,this._dpr*a,this._dpr*this._tx,this._dpr*this._ty);for(const t of this._beforeRenderCallbacks)t(c);if(this._render)this._render(this);else for(const t of this._layerManagers)t.renderAllLayersIn(this);for(const t of this._afterRenderCallbacks)t(c);u.drawImage(r,0,0),u.drawImage(_,0,0),this._raf=requestAnimationFrame(()=>this._loop())}applyWorldTransform(t){const e=Math.exp(this._currentLogZ);t.setTransform(this._dpr*e,0,0,this._dpr*e,this._dpr*this._tx,this._dpr*this._ty)}applyScreenTransform(t){t.setTransform(this._dpr,0,0,this._dpr,0,0)}getPixelColorAtScreen(t,e){const i=Math.floor(t*this._dpr),s=Math.floor(e*this._dpr);if(i<0||s<0||i>=this.canvas.width||s>=this.canvas.height)return{r:0,g:0,b:0,a:0,rgba:"rgba(0,0,0,0)",hex:"#000000"};const n=this.contentContext.getImageData(i,s,1,1).data,h=n[0],a=n[1],o=n[2],r=n[3]/255,c=t=>t.toString(16).padStart(2,"0"),_=`#${c(h)}${c(a)}${c(o)}`;return{r:h,g:a,b:o,a:r,rgba:`rgba(${h},${a},${o},${r.toFixed(3)})`,hex:_}}getPixelColorAtWorld(t,e){const{x:i,y:s}=this.toScreen(t,e);return this.getPixelColorAtScreen(i,s)}registerLayerManager(t){t&&(this._layerManagers.includes(t)||(this._layerManagers.push(t),this._needsRender=!0))}unregisterLayerManager(t){const e=this._layerManagers.indexOf(t);e>=0&&(this._layerManagers.splice(e,1),this._needsRender=!0)}getLayerManagers(){return[...this._layerManagers]}resetSmooth(){this._isResetting=!0,this._targetLogZ=0,this._needsRender=!0}resetInstant(){this._currentLogZ=0,this._targetLogZ=0,this._tx=0,this._ty=0,this._needsRender=!0}toWorld(t,e){const i=Math.exp(this._currentLogZ);return{wx:(t-this._tx)/i,wy:(e-this._ty)/i}}toScreen(t,e){const i=Math.exp(this._currentLogZ);return{x:t*i+this._tx,y:e*i+this._ty}}getTransform(){return{zoom:Math.exp(this._currentLogZ),tx:this._tx,ty:this._ty}}getViewportBounds(){const t=Math.exp(this._currentLogZ),e=this.canvas.width/this._dpr,i=this.canvas.height/this._dpr,s=-this._tx/t,n=-this._ty/t,h=(e-this._tx)/t,a=(i-this._ty)/t;return{left:s,top:n,right:h,bottom:a,width:h-s,height:a-n}}setZoomRange(t,e){this._options.minZoom=t,this._options.maxZoom=e,this.LOG_MIN=Math.log(t),this.LOG_MAX=Math.log(e),this._targetLogZ=Math.min(this.LOG_MAX,Math.max(this.LOG_MIN,this._targetLogZ))}resizeToParent(){this._isResizing=!0;const t=(this.canvas.parentElement||this.canvas).getBoundingClientRect();this._dpr=Math.max(1,window.devicePixelRatio||1);const e=Math.max(1,Math.round(t.width)),i=Math.max(1,Math.round(t.height));this.canvas.width=Math.round(e*this._dpr),this.canvas.height=Math.round(i*this._dpr),this.canvas.style.width=`${e}px`,this.canvas.style.height=`${i}px`,this._ensureOffscreenSizeLike(this.contentCanvas,this.canvas),this._ensureOffscreenSizeLike(this.topScreenCanvas,this.canvas),clearTimeout(this._resizeReleaseTimer),this._resizeReleaseTimer=window.setTimeout(()=>{this._isResizing=!1},50)}destroy(){cancelAnimationFrame(this._raf);for(const t of this._plugins.values())t.destroy();this._plugins.clear(),this._resizeObserver&&this._resizeObserver.disconnect(),this._layerManagers=[],this._updateCallbacks.clear(),this._beforeRenderCallbacks.clear(),this._afterRenderCallbacks.clear()}constructor(t,e){var i;this._layerManagers=[],this._plugins=new Map,this._isResetting=!1,this._isResizing=!1,this._needsRender=!0,this._raf=0,this._lastFrameTs=performance.now(),this._tx=0,this._ty=0,this._anchorX=0,this._anchorY=0,this._currentLogZ=Math.log(1),this._targetLogZ=Math.log(1),this._targetTx=null,this._targetTy=null,this._isAnimatingTransform=!1,this._updateCallbacks=new Set,this._beforeRenderCallbacks=new Set,this._afterRenderCallbacks=new Set,this._dpr=Math.max(1,window.devicePixelRatio||1);const s=t.getContext("2d",{willReadFrequently:!0,alpha:!0});if(!s)throw new Error("2D context not available");this.canvas=t,this.context=s,this._render=null!==(i=null==e?void 0:e.render)&&void 0!==i?i:null,this.contentCanvas=document.createElement("canvas"),this.contentCanvas.width=t.width,this.contentCanvas.height=t.height,this.contentContext=this.contentCanvas.getContext("2d",{alpha:!0,willReadFrequently:!0}),this.topScreenCanvas=document.createElement("canvas"),this.topScreenCanvas.width=t.width,this.topScreenCanvas.height=t.height,this.topScreenContext=this.topScreenCanvas.getContext("2d",{alpha:!0}),this._options=Object.assign({minZoom:.5,maxZoom:10,approachKZoom:.022,approachKPan:.022,autoResize:!0,background:"#fff"},e),this.LOG_MIN=Math.log(this._options.minZoom),this.LOG_MAX=Math.log(this._options.maxZoom),this._options.autoResize&&(this._resizeObserver=new ResizeObserver(()=>this.resizeToParent()),this._resizeObserver.observe(this.canvas.parentElement||this.canvas)),this.resizeToParent(),this._lastFrameTs=performance.now(),this._raf=requestAnimationFrame(()=>this._loop())}},exports.createBoundsPlugin=function(t){return new d(t)},exports.createInteractionPlugin=function(t){return new l(t)},exports.createSnapshotCommand=function(t,e,i,s){return e&&i?new u(t,e,i,s):null};
@@ -1 +1 @@
1
- function t(t,e,i,s){return new(i||(i=Promise))(function(n,h){function o(t){try{r(s.next(t))}catch(t){h(t)}}function a(t){try{r(s.throw(t))}catch(t){h(t)}}function r(t){var e;t.done?n(t.value):(e=t.value,e instanceof i?e:new i(function(t){t(e)})).then(o,a)}r((s=s.apply(t,e||[])).next())})}function e(t,e,i,s){if("a"===i&&!s)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof e?t!==e||!s:!e.has(t))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===i?s:"a"===i?s.call(t):s?s.value:e.get(t)}function i(t,e,i,s,n){if("m"===s)throw new TypeError("Private method is not writable");if("a"===s&&!n)throw new TypeError("Private accessor was defined without a setter");if("function"==typeof e?t!==e||!n:!e.has(t))throw new TypeError("Cannot write private member to an object whose class did not declare it");return"a"===s?n.call(t,i):n?n.value=i:e.set(t,i),i}"function"==typeof SuppressedError&&SuppressedError;const s=(e,i)=>t(void 0,void 0,void 0,function*(){return new Promise((t,s)=>{const n=new Image;"string"==typeof e?(void 0!==i&&(n.crossOrigin=i),n.src=e):n.src=URL.createObjectURL(e),n.onload=()=>{t(n)},n.onerror=()=>{s(new Error("Image load failed"))}})}),n=(t,e,i)=>Math.min(Math.max(t,e),i);class h{get zoom(){return Math.exp(this._currentLogZ)}get minZoom(){return this._options.minZoom}get maxZoom(){return this._options.maxZoom}get dpr(){return this._dpr}use(t){return this._plugins.has(t.name)?(console.warn(`Plugin "${t.name}" is already installed.`),t):(this._plugins.set(t.name,t),t.install(this),t)}unuse(t){const e=this._plugins.get(t);e&&(e.destroy(),this._plugins.delete(t))}getPlugin(t){return this._plugins.get(t)}onUpdate(t){this._updateCallbacks.add(t)}offUpdate(t){this._updateCallbacks.delete(t)}onBeforeRender(t){this._beforeRenderCallbacks.add(t)}offBeforeRender(t){this._beforeRenderCallbacks.delete(t)}onAfterRender(t){this._afterRenderCallbacks.add(t)}offAfterRender(t){this._afterRenderCallbacks.delete(t)}requestRender(){this._needsRender=!0}_clampLog(t){return n(t,this.LOG_MIN,this.LOG_MAX)}_setTargetLogZoomAtScreen(t,e,i){Number.isFinite(i)&&(this._anchorX=t,this._anchorY=e,this._targetLogZ=this._clampLog(i),this._needsRender=!0)}zoomToAtScreen(t,e,i){this._setTargetLogZoomAtScreen(t,e,Math.log(i))}zoomToAtScreenRaw(t,e,i){if(!Number.isFinite(i))return;const s=Math.max(1e-8,this._options.minZoom),h=this._options.maxZoom,o=n(i,s,h),a=Math.exp(this._currentLogZ),r=o;if(!Number.isFinite(a)||a<=0)return;if(Math.abs(r-a)<1e-12)return;const c=Math.log(o);this._currentLogZ=c,this._targetLogZ=c;const _=r/a;this._tx=t-(t-this._tx)*_,this._ty=e-(e-this._ty)*_,this._needsRender=!0}zoomToAtWorld(t,e,i){const{x:s,y:n}=this.toScreen(t,e);this.zoomToAtScreen(s,n,i)}zoomByFactorAtScreen(t,e,i){if(i<=0||!Number.isFinite(i))return;const s=Math.log(i);this._setTargetLogZoomAtScreen(t,e,this._targetLogZ+s)}zoomByLogAtScreen(t,e,i){this._setTargetLogZoomAtScreen(t,e,this._targetLogZ+i)}zoomByFactorAtWorld(t,e,i){const{x:s,y:n}=this.toScreen(t,e);this.zoomByFactorAtScreen(s,n,i)}panBy(t,e){this._tx+=t,this._ty+=e,this._needsRender=!0}setPan(t,e){this._tx=t,this._ty=e,this._needsRender=!0}setTransform(t,e,i){const s=n(t,this._options.minZoom,this._options.maxZoom);this._currentLogZ=Math.log(s),this._targetLogZ=this._currentLogZ,this._tx=e,this._ty=i,this._targetTx=null,this._targetTy=null,this._needsRender=!0}setTransformSmooth(t,e,i){const s=n(t,this._options.minZoom,this._options.maxZoom);this._targetLogZ=Math.log(s),this._targetTx=e,this._targetTy=i,this._needsRender=!0}_ensureOffscreenSizeLike(t,e){t.width===e.width&&t.height===e.height||(t.width=e.width,t.height=e.height)}_loop(){if(this._isResizing)return void(this._raf=requestAnimationFrame(()=>this._loop()));const t=performance.now(),e=Math.max(1,t-this._lastFrameTs);this._lastFrameTs=t;const{approachKZoom:i}=this._options,s=Math.exp(this._currentLogZ),n=this._targetLogZ-this._currentLogZ,h=Math.abs(n)>1e-6;if(h){const t=1-Math.exp(-i*e);this._currentLogZ+=n*t}const o=Math.exp(this._currentLogZ);if(o!==s){const t=this._anchorX,e=this._anchorY,i=o/s;this._tx=t-(t-this._tx)*i,this._ty=e-(e-this._ty)*i}let a=!1;if(null!==this._targetTx&&null!==this._targetTy){const t=1-Math.exp(-this._options.approachKPan*e),i=this._targetTx-this._tx,s=this._targetTy-this._ty;a=Math.abs(i)>.5||Math.abs(s)>.5,a?(this._tx+=i*t,this._ty+=s*t):(this._tx=this._targetTx,this._ty=this._targetTy,this._targetTx=null,this._targetTy=null)}if(this._isResetting){const t=1-Math.exp(-this._options.approachKPan*e);this._tx+=(0-this._tx)*t,this._ty+=(0-this._ty)*t;const i=Math.abs(this._currentLogZ)<.001&&Math.abs(this._targetLogZ)<1e-6,s=Math.abs(this._tx)<.5&&Math.abs(this._ty)<.5;i&&s&&(this._currentLogZ=0,this._targetLogZ=0,this._tx=0,this._ty=0,this._isResetting=!1)}for(const t of this._updateCallbacks)t(e);if(!(this._needsRender||h||a||this._isResetting))return void(this._raf=requestAnimationFrame(()=>this._loop()));this._needsRender=!1;const r=this.contentCanvas,c=this.contentContext,_=this.topScreenCanvas,l=this.topScreenContext,d=this.canvas,u=this.context;this._ensureOffscreenSizeLike(r,d),this._ensureOffscreenSizeLike(_,d),c.setTransform(1,0,0,1,0,0),l.setTransform(1,0,0,1,0,0),u.setTransform(1,0,0,1,0,0);const g=this._options.background;"string"==typeof g&&""!==g.trim()&&"transparent"!==g.toLowerCase()?(u.fillStyle=g,u.fillRect(0,0,d.width,d.height)):u.clearRect(0,0,d.width,d.height),c.clearRect(0,0,r.width,r.height),l.clearRect(0,0,_.width,_.height),c.setTransform(this._dpr*o,0,0,this._dpr*o,this._dpr*this._tx,this._dpr*this._ty);for(const t of this._beforeRenderCallbacks)t(c);this._render(this);for(const t of this._afterRenderCallbacks)t(c);u.drawImage(r,0,0),u.drawImage(_,0,0),this._raf=requestAnimationFrame(()=>this._loop())}applyWorldTransform(t){const e=Math.exp(this._currentLogZ);t.setTransform(this._dpr*e,0,0,this._dpr*e,this._dpr*this._tx,this._dpr*this._ty)}applyScreenTransform(t){t.setTransform(this._dpr,0,0,this._dpr,0,0)}getPixelColorAtScreen(t,e){const i=Math.floor(t*this._dpr),s=Math.floor(e*this._dpr);if(i<0||s<0||i>=this.canvas.width||s>=this.canvas.height)return{r:0,g:0,b:0,a:0,rgba:"rgba(0,0,0,0)",hex:"#000000"};const n=this.contentContext.getImageData(i,s,1,1).data,h=n[0],o=n[1],a=n[2],r=n[3]/255,c=t=>t.toString(16).padStart(2,"0"),_=`#${c(h)}${c(o)}${c(a)}`;return{r:h,g:o,b:a,a:r,rgba:`rgba(${h},${o},${a},${r.toFixed(3)})`,hex:_}}getPixelColorAtWorld(t,e){const{x:i,y:s}=this.toScreen(t,e);return this.getPixelColorAtScreen(i,s)}registerLayerManager(t){t&&(this._layerManagers.includes(t)||(this._layerManagers.push(t),this._needsRender=!0))}unregisterLayerManager(t){const e=this._layerManagers.indexOf(t);e>=0&&(this._layerManagers.splice(e,1),this._needsRender=!0)}getLayerManagers(){return[...this._layerManagers]}resetSmooth(){this._isResetting=!0,this._targetLogZ=0,this._needsRender=!0}resetInstant(){this._currentLogZ=0,this._targetLogZ=0,this._tx=0,this._ty=0,this._needsRender=!0}toWorld(t,e){const i=Math.exp(this._currentLogZ);return{wx:(t-this._tx)/i,wy:(e-this._ty)/i}}toScreen(t,e){const i=Math.exp(this._currentLogZ);return{x:t*i+this._tx,y:e*i+this._ty}}getTransform(){return{zoom:Math.exp(this._currentLogZ),tx:this._tx,ty:this._ty}}getViewportBounds(){const t=Math.exp(this._currentLogZ),e=this.canvas.width/this._dpr,i=this.canvas.height/this._dpr,s=-this._tx/t,n=-this._ty/t,h=(e-this._tx)/t,o=(i-this._ty)/t;return{left:s,top:n,right:h,bottom:o,width:h-s,height:o-n}}setZoomRange(t,e){this._options.minZoom=t,this._options.maxZoom=e,this.LOG_MIN=Math.log(t),this.LOG_MAX=Math.log(e),this._targetLogZ=Math.min(this.LOG_MAX,Math.max(this.LOG_MIN,this._targetLogZ))}resizeToParent(){this._isResizing=!0;const t=(this.canvas.parentElement||this.canvas).getBoundingClientRect();this._dpr=Math.max(1,window.devicePixelRatio||1);const e=Math.max(1,Math.round(t.width)),i=Math.max(1,Math.round(t.height));this.canvas.width=Math.round(e*this._dpr),this.canvas.height=Math.round(i*this._dpr),this.canvas.style.width=`${e}px`,this.canvas.style.height=`${i}px`,this._ensureOffscreenSizeLike(this.contentCanvas,this.canvas),this._ensureOffscreenSizeLike(this.topScreenCanvas,this.canvas),clearTimeout(this._resizeReleaseTimer),this._resizeReleaseTimer=window.setTimeout(()=>{this._isResizing=!1},50)}destroy(){cancelAnimationFrame(this._raf);for(const t of this._plugins.values())t.destroy();this._plugins.clear(),this._resizeObserver&&this._resizeObserver.disconnect(),this._layerManagers=[],this._updateCallbacks.clear(),this._beforeRenderCallbacks.clear(),this._afterRenderCallbacks.clear()}constructor(t,e,i){this._layerManagers=[],this._plugins=new Map,this._isResetting=!1,this._isResizing=!1,this._needsRender=!0,this._raf=0,this._lastFrameTs=performance.now(),this._tx=0,this._ty=0,this._anchorX=0,this._anchorY=0,this._currentLogZ=Math.log(1),this._targetLogZ=Math.log(1),this._targetTx=null,this._targetTy=null,this._updateCallbacks=new Set,this._beforeRenderCallbacks=new Set,this._afterRenderCallbacks=new Set,this._dpr=Math.max(1,window.devicePixelRatio||1);const s=t.getContext("2d",{willReadFrequently:!0,alpha:!0});if(!s)throw new Error("2D context not available");this.canvas=t,this.context=s,this._render=e,this.contentCanvas=document.createElement("canvas"),this.contentCanvas.width=t.width,this.contentCanvas.height=t.height,this.contentContext=this.contentCanvas.getContext("2d",{alpha:!0,willReadFrequently:!0}),this.topScreenCanvas=document.createElement("canvas"),this.topScreenCanvas.width=t.width,this.topScreenCanvas.height=t.height,this.topScreenContext=this.topScreenCanvas.getContext("2d",{alpha:!0}),this._options=Object.assign({minZoom:.5,maxZoom:10,approachKZoom:.022,approachKPan:.022,autoResize:!0,background:"#fff"},i),this.LOG_MIN=Math.log(this._options.minZoom),this.LOG_MAX=Math.log(this._options.maxZoom),this._options.autoResize&&(this._resizeObserver=new ResizeObserver(()=>this.resizeToParent()),this._resizeObserver.observe(this.canvas.parentElement||this.canvas)),this.resizeToParent(),this._lastFrameTs=performance.now(),this._raf=requestAnimationFrame(()=>this._loop())}}let o=0;class a{constructor(t,e,i="world"){this.space="world",this.visible=!0,this.opacity=1,this.blend="source-over",this.name=t,this.id=`layer_${e}_${++o}`,this.type=e,this.space=i}}class r extends a{beginStroke(t,e){const{lx:i,ly:s}=this.toLocalPoint(t,e);this._lastX=i,this._lastY=s,this._drawing=!0}stroke(t,e,i,s,n=1,h="brush"){if(!this._drawing)return;const{lx:o,ly:a}=this.toLocalPoint(t,e);this.context.beginPath(),this.context.moveTo(this._lastX,this._lastY),this.context.lineTo(o,a),"eraser"===h?(this.context.globalCompositeOperation="destination-out",this.context.strokeStyle="rgba(0, 0, 0, 1)"):(this.context.globalCompositeOperation="source-over",this.context.strokeStyle=i),this.context.lineWidth=s*n,this.context.lineCap="round",this.context.lineJoin="round",this.context.stroke(),this.context.closePath(),this._lastX=o,this._lastY=a}endStroke(){this._drawing=!1}isDrawing(){return this._drawing}captureSnapshot(t){try{if(t){const{x:e,y:i,width:s,height:n}=t,h=Math.max(0,Math.floor(e)),o=Math.max(0,Math.floor(i)),a=Math.min(this.canvas.width-h,Math.ceil(s)),r=Math.min(this.canvas.height-o,Math.ceil(n));return a<=0||r<=0?null:this.context.getImageData(h,o,a,r)}return this.context.getImageData(0,0,this.canvas.width,this.canvas.height)}catch(t){return null}}restoreSnapshot(t,e){var i,s;const n=null!==(i=null==e?void 0:e.x)&&void 0!==i?i:0,h=null!==(s=null==e?void 0:e.y)&&void 0!==s?s:0;this.context.putImageData(t,n,h)}clearRegion(t){t?this.context.clearRect(t.x,t.y,t.width,t.height):this.context.clearRect(0,0,this.canvas.width,this.canvas.height)}requestRedraw(){var t;null===(t=this._redraw)||void 0===t||t.call(this,this.context,this.canvas)}drawImage(t,e,i,s,n){this.context.drawImage(t,e,i,null!=s?s:t.width,null!=n?n:t.height)}hitTest(t,e){const{lx:i,ly:s}=this.toLocalPoint(t,e);return i>=0&&i<=this.canvas.width&&s>=0&&s<=this.canvas.height}toLocalPoint(t,e){const i=t-this.x,s=e-this.y,n=Math.cos(-this.rotation),h=Math.sin(-this.rotation),o=i*h+s*n,a=(i*n-s*h)/this.scale,r=o/this.scale;return{lx:a+("center"===this.anchor?this.canvas.width/2:0),ly:r+("center"===this.anchor?this.canvas.height/2:0)}}render(t,e){if(!this.visible)return;const i=this.canvas.width*this.scale,s=this.canvas.height*this.scale,n="center"===this.anchor?-i/2:0,h="center"===this.anchor?-s/2:0;t.save(),t.globalAlpha=this.opacity,t.globalCompositeOperation=this.blend,t.translate(this.x,this.y),t.rotate(this.rotation),t.drawImage(this.canvas,n,h,i,s),t.restore()}cropTo(t){const e=Math.max(1,Math.floor(t.width)),i=Math.max(1,Math.floor(t.height));if(e===this.canvas.width&&i===this.canvas.height)return;const s=this._cloneCanvas(),n=Math.min(s.width,e),h=Math.min(s.height,i);this._setCanvasSize(e,i),n>0&&h>0&&this.context.drawImage(s,0,0,n,h,0,0,n,h)}resizeTo(t){const e=Math.max(1,Math.floor(t.width)),i=Math.max(1,Math.floor(t.height));if(e===this.canvas.width&&i===this.canvas.height)return;const s=this._cloneCanvas();this._setCanvasSize(e,i),s.width>0&&s.height>0&&this.context.drawImage(s,0,0,s.width,s.height,0,0,e,i)}_cloneCanvas(){const t=document.createElement("canvas");if(t.width=this.canvas.width,t.height=this.canvas.height,0===t.width||0===t.height)return t;const e=t.getContext("2d");if(!e)throw new Error("Offscreen 2D context unavailable");return e.drawImage(this.canvas,0,0),t}_setCanvasSize(t,e){this.canvas.width=t,this.canvas.height=e,this.context.setTransform(1,0,0,1,0,0),this.context.clearRect(0,0,t,e)}destroy(){this.canvas.width=0,this.canvas.height=0}constructor(t){var e,i;if(super(t.name||"","canvas",null!==(e=t.space)&&void 0!==e?e:"world"),this.x=0,this.y=0,this.scale=1,this.rotation=0,this.anchor="topLeft",this._drawing=!1,this._lastX=0,this._lastY=0,"canvas"in t&&t.canvas)this.canvas=t.canvas;else{const e=t;this.canvas=document.createElement("canvas"),this.canvas.width=e.width,this.canvas.height=e.height}const s=this.canvas.getContext("2d",{willReadFrequently:!0});if(!s)throw new Error("Offscreen 2D context unavailable");this.context=s,this.x=t.x||0,this.y=t.y||0,this.scale=null!==(i=t.scale)&&void 0!==i?i:1,this.rotation=t.rotation||0,t.anchor&&(this.anchor=t.anchor),this._redraw=t.redraw,this._redraw&&this._redraw(this.context,this.canvas)}}var c;class _ extends r{static fromImage(e){return t(this,void 0,void 0,function*(){var t,n,h,o,a,r,l,d;const u=yield s(e.src,e.crossOrigin),g=null!==(t=e.width)&&void 0!==t?t:u.naturalWidth,v=null!==(n=e.height)&&void 0!==n?n:u.naturalHeight,p=new _({name:e.name,space:null!==(h=e.space)&&void 0!==h?h:"world",x:null!==(o=e.x)&&void 0!==o?o:0,y:null!==(a=e.y)&&void 0!==a?a:0,scale:null!==(r=e.scale)&&void 0!==r?r:1,rotation:null!==(l=e.rotation)&&void 0!==l?l:0,anchor:null!==(d=e.anchor)&&void 0!==d?d:"topLeft",width:g,height:v});return p.context.clearRect(0,0,p.canvas.width,p.canvas.height),p.context.drawImage(u,0,0,g,v),"string"!=typeof e.src&&i(p,c,u.src.startsWith("blob:")?u.src:null,"f"),p})}setSource(n,h){return t(this,void 0,void 0,function*(){const t=yield s(n,h);if(this.canvas.width=t.naturalWidth,this.canvas.height=t.naturalHeight,this.context.setTransform(1,0,0,1,0,0),this.context.clearRect(0,0,this.canvas.width,this.canvas.height),this.context.drawImage(t,0,0),e(this,c,"f")){try{URL.revokeObjectURL(e(this,c,"f"))}catch(t){}i(this,c,null,"f")}"string"!=typeof n&&i(this,c,t.src.startsWith("blob:")?t.src:null,"f")})}paint(t){t(this.context,this.canvas)}getImageData(t=0,e=0,i=this.canvas.width,s=this.canvas.height){return this.context.getImageData(t,e,i,s)}putImageData(t,e=0,i=0){this.context.putImageData(t,e,i)}toDataURL(t="image/png",e){return this.canvas.toDataURL(t,e)}toImageBitmap(t){return createImageBitmap(this.canvas,null!=t?t:{})}destroy(){var t;if(null===(t=super.destroy)||void 0===t||t.call(this),e(this,c,"f")){try{URL.revokeObjectURL(e(this,c,"f"))}catch(t){}i(this,c,null,"f")}}constructor(t){var e,i;super({name:t.name,space:null!==(e=t.space)&&void 0!==e?e:"world",x:t.x,y:t.y,scale:t.scale,rotation:t.rotation,anchor:null!==(i=t.anchor)&&void 0!==i?i:"topLeft",width:t.width,height:t.height}),c.set(this,null),this.type="bitmap"}}c=new WeakMap;class l{constructor(){this._worldLayers=[],this._screenLayers=[]}_renderAllLayersIn(t,e){e.save(),t.applyWorldTransform(e);for(const i of this._worldLayers)!i.visible||i.opacity<=0||(e.save(),i.render(e,t),e.restore());e.restore(),e.save(),t.applyScreenTransform(e);for(const i of this._screenLayers)!i.visible||i.opacity<=0||(e.save(),i.render(e,t),e.restore());e.restore()}addLayer(t,e){const i="world"===t.space?this._worldLayers:this._screenLayers;return"number"==typeof e&&e>=0&&e<i.length?(i.splice(e,0,t),t.id):(i.push(t),t.id)}createImageLayer(e){return t(this,void 0,void 0,function*(){const t=yield _.fromImage(e);return this.addLayer(t),t})}createCanvasLayer(t){const e=new r(t);return this.addLayer(e),e}removeLayer(t){var e,i,s,n;const h=this._worldLayers.findIndex(e=>e.id===t);if(h>=0)return null===(i=(e=this._worldLayers[h]).destroy)||void 0===i||i.call(e),void this._worldLayers.splice(h,1);const o=this._screenLayers.findIndex(e=>e.id===t);o>=0&&(null===(n=(s=this._screenLayers[o]).destroy)||void 0===n||n.call(s),this._screenLayers.splice(o,1))}detachLayer(t){const e=this._worldLayers.findIndex(e=>e.id===t);if(e>=0)return void this._worldLayers.splice(e,1);const i=this._screenLayers.findIndex(e=>e.id===t);i>=0&&this._screenLayers.splice(i,1)}moveLayer(t,e){const i=this._worldLayers.findIndex(e=>e.id===t);if(i>=0){const[t]=this._worldLayers.splice(i,1),s=Math.max(0,Math.min(e,this._worldLayers.length));return void this._worldLayers.splice(s,0,t)}const s=this._screenLayers.findIndex(e=>e.id===t);if(s>=0){const[t]=this._screenLayers.splice(s,1),i=Math.max(0,Math.min(e,this._screenLayers.length));this._screenLayers.splice(i,0,t)}}reorderLayers(t){const e=[];for(const i of t){const t=this._worldLayers.find(t=>t.id===i);t&&e.push(t)}for(const i of this._worldLayers)t.includes(i.id)||e.push(i);this._worldLayers=e}getLayer(t){return this._worldLayers.find(e=>e.id===t)||this._screenLayers.find(e=>e.id===t)}getAllLayers(t){return t?("world"===t?this._worldLayers:this._screenLayers).slice():[...this._worldLayers,...this._screenLayers]}hitTest(t,e,i="world"){const s=this.getAllLayers(i);for(let i=s.length-1;i>=0;i--){const n=s[i];if(n.hitTest&&n.hitTest(t,e))return n}}destroy(){var t;for(const e of[...this._worldLayers,...this._screenLayers])null===(t=e.destroy)||void 0===t||t.call(e);this._worldLayers=[],this._screenLayers=[]}}class d extends l{constructor(){super(...arguments),this._compositeCache=null,this._compositeCacheCtx=null,this._compositeDirty=!0,this._lastCacheWidth=0,this._lastCacheHeight=0,this._cachedBoundsMinX=0,this._cachedBoundsMinY=0}markDirty(){this._compositeDirty=!0}addLayer(t,e){return this._compositeDirty=!0,super.addLayer(t,e)}removeLayer(t){this._compositeDirty=!0,super.removeLayer(t)}detachLayer(t){this._compositeDirty=!0,super.detachLayer(t)}removeAllLayers(t){var e,i;if(!t||"world"===t){for(const t of this._worldLayers)null===(e=t.destroy)||void 0===e||e.call(t);this._worldLayers=[]}if(!t||"screen"===t){for(const t of this._screenLayers)null===(i=t.destroy)||void 0===i||i.call(t);this._screenLayers=[]}}moveLayer(t,e){this._compositeDirty=!0,super.moveLayer(t,e)}renderAllLayersIn(t){const e=t.contentContext,i=this._worldLayers;0!==i.length&&(this._compositeDirty&&this._rebuildCompositeCache(i),this._compositeCache&&this._compositeCacheCtx&&e.drawImage(this._compositeCache,this._cachedBoundsMinX,this._cachedBoundsMinY))}_rebuildCompositeCache(t){let e=0,i=0,s=0,n=0,h=!1;for(const o of t){const t=o,a=t.canvas.width*t.scale,r=t.canvas.height*t.scale,c="center"===t.anchor?-a/2:0,_="center"===t.anchor?-r/2:0,l=Math.cos(t.rotation),d=Math.sin(t.rotation),u=[{x:c,y:_},{x:c+a,y:_},{x:c,y:_+r},{x:c+a,y:_+r}];let g=1/0,v=1/0,p=-1/0,m=-1/0;for(const e of u){const i=e.x*l-e.y*d+t.x,s=e.x*d+e.y*l+t.y;g=Math.min(g,i),v=Math.min(v,s),p=Math.max(p,i),m=Math.max(m,s)}h?(e=Math.min(e,g),i=Math.min(i,v),s=Math.max(s,p),n=Math.max(n,m)):(e=g,i=v,s=p,n=m,h=!0)}if(!h)return void(this._compositeDirty=!1);const o=Math.ceil(s-e),a=Math.ceil(n-i);this._compositeCache||(this._compositeCache=document.createElement("canvas"),this._compositeCacheCtx=this._compositeCache.getContext("2d",{alpha:!0})),this._lastCacheWidth===o&&this._lastCacheHeight===a||(this._compositeCache.width=o,this._compositeCache.height=a,this._lastCacheWidth=o,this._lastCacheHeight=a),this._cachedBoundsMinX=e,this._cachedBoundsMinY=i;const r=this._compositeCacheCtx;r.clearRect(0,0,o,a),r.save(),r.translate(-e,-i);for(const e of t)!e.visible||e.opacity<=0||(r.save(),e.render(r),r.restore());r.restore(),this._compositeDirty=!1}destroy(){super.destroy(),this._compositeCache=null,this._compositeCacheCtx=null}}class u extends l{renderAllLayersIn(t){const e=t.topScreenContext;this._renderAllLayersIn(t,e)}}class g{constructor(t){this.name="interaction",this._view=null,this._dragging=!1,this._vx=0,this._vy=0,this._lastMoveTs=0,this._activePointerId=null,this._lastPointerX=0,this._lastPointerY=0,this._touchPointers=new Map,this._isTouchPanning=!1,this._isPinching=!1,this._lastPinchDistance=0,this._lastPinchCenterX=0,this._lastPinchCenterY=0,this._lastTouchX=0,this._lastTouchY=0,this._onDownBound=t=>this._onPointerDown(t),this._onMoveBound=t=>this._onPointerMove(t),this._onUpBound=t=>this._onPointerUp(t),this._onCancelBound=t=>this._onPointerCancel(t),this._onWheelBound=t=>this._onWheel(t),this._onUpdate=t=>{if(!this._view)return;const{friction:e,stopSpeed:i}=this._options,s=Math.hypot(this._vx,this._vy)>=i;if(!(this._dragging||this._isTouchPanning||this._isPinching)&&s){const s=this._vx*t,n=this._vy*t;this._view.panBy(s,n),this._vx*=e,this._vy*=e,Math.hypot(this._vx,this._vy)<i&&(this._vx=0,this._vy=0)}},this._options=Object.assign({panEnabled:!0,zoomEnabled:!0,friction:.92,stopSpeed:.02,emaAlpha:.25,idleNoInertiaMs:120,wheelSensitivity:.0015},t),this._panEnabled=this._options.panEnabled,this._zoomEnabled=this._options.zoomEnabled}install(t){this._view=t;const e=t.canvas;e.style.touchAction="none",e.addEventListener("wheel",this._onWheelBound,{passive:!1}),e.addEventListener("pointerdown",this._onDownBound),window.addEventListener("pointermove",this._onMoveBound),window.addEventListener("pointerup",this._onUpBound),window.addEventListener("pointercancel",this._onCancelBound),t.onUpdate(this._onUpdate)}destroy(){if(!this._view)return;const t=this._view.canvas;t.removeEventListener("wheel",this._onWheelBound),t.removeEventListener("pointerdown",this._onDownBound),window.removeEventListener("pointermove",this._onMoveBound),window.removeEventListener("pointerup",this._onUpBound),window.removeEventListener("pointercancel",this._onCancelBound),this._touchPointers.clear(),this._isPinching=!1,this._isTouchPanning=!1,this._view.offUpdate(this._onUpdate),this._view=null}isPanEnabled(){return this._panEnabled}isZoomEnabled(){return this._zoomEnabled}setPanEnabled(t){this._panEnabled!==t&&(this._panEnabled=t,t||null===this._activePointerId||(this._dragging=!1,this._vx=0,this._vy=0))}setZoomEnabled(t){this._zoomEnabled!==t&&(this._zoomEnabled=t,!t&&this._isPinching&&this._endPinch())}setWheelSensitivity(t){this._options.wheelSensitivity=t}isDragging(){return this._dragging||this._isTouchPanning||this._isPinching}_onPointerDown(t){var e;if("touch"!==t.pointerType){if(("mouse"!==t.pointerType||0===t.button)&&this._panEnabled&&null===this._activePointerId){t.preventDefault(),this._dragging=!0,this._vx=0,this._vy=0,this._lastMoveTs=performance.now(),this._activePointerId=t.pointerId,this._lastPointerX=t.clientX,this._lastPointerY=t.clientY;try{null===(e=this._view)||void 0===e||e.canvas.setPointerCapture(t.pointerId)}catch(t){}}}else this._onTouchDown(t)}_onPointerMove(t){if("touch"===t.pointerType)return void this._onTouchMove(t);if(t.pointerId!==this._activePointerId)return;if(!this._dragging||!this._panEnabled||!this._view)return;const e=performance.now(),i=Math.max(1,e-(this._lastMoveTs||e-16));this._lastMoveTs=e;const s=t.clientX-this._lastPointerX,n=t.clientY-this._lastPointerY;this._lastPointerX=t.clientX,this._lastPointerY=t.clientY,this._view.panBy(s,n);const h=this._options.emaAlpha,o=s/i,a=n/i;this._vx=(1-h)*this._vx+h*o,this._vy=(1-h)*this._vy+h*a}_onPointerUp(t){if("touch"===t.pointerType)return void this._onTouchUp(t);if(t.pointerId!==this._activePointerId)return;if(!this._dragging)return;this._dragging=!1;const e=performance.now(),i=this._lastMoveTs?e-this._lastMoveTs:1/0;if(null!=this._activePointerId&&this._view){try{this._view.canvas.releasePointerCapture(this._activePointerId)}catch(t){}this._activePointerId=null}if(i>=this._options.idleNoInertiaMs)this._vx=0,this._vy=0;else{const t=Math.pow(this._options.friction,i/16);this._vx*=t,this._vy*=t}Math.hypot(this._vx,this._vy)<this._options.stopSpeed&&(this._vx=0,this._vy=0)}_onPointerCancel(t){"touch"!==t.pointerType?t.pointerId===this._activePointerId&&(this._dragging=!1,this._vx=0,this._vy=0,this._activePointerId=null):this._onTouchCancel(t)}_onTouchDown(t){if(t.preventDefault(),this._touchPointers.set(t.pointerId,{x:t.clientX,y:t.clientY}),2===this._touchPointers.size&&this._zoomEnabled)return this._isTouchPanning=!1,void this._startPinch();1===this._touchPointers.size&&(this._isTouchPanning=!0,this._vx=0,this._vy=0,this._lastMoveTs=performance.now(),this._lastTouchX=t.clientX,this._lastTouchY=t.clientY)}_onTouchMove(t){if(this._touchPointers.has(t.pointerId))if(this._touchPointers.set(t.pointerId,{x:t.clientX,y:t.clientY}),this._isPinching&&2===this._touchPointers.size)this._handlePinchMove();else if(this._isTouchPanning&&1===this._touchPointers.size&&this._view){const e=performance.now(),i=Math.max(1,e-(this._lastMoveTs||e-16));this._lastMoveTs=e;const s=t.clientX-this._lastTouchX,n=t.clientY-this._lastTouchY;this._lastTouchX=t.clientX,this._lastTouchY=t.clientY,this._view.panBy(s,n);const h=this._options.emaAlpha,o=s/i,a=n/i;this._vx=(1-h)*this._vx+h*o,this._vy=(1-h)*this._vy+h*a}}_onTouchUp(t){if(this._touchPointers.delete(t.pointerId),this._isPinching){if(this._endPinch(),1===this._touchPointers.size){const[[,t]]=this._touchPointers.entries();this._isTouchPanning=!0,this._lastTouchX=t.x,this._lastTouchY=t.y,this._vx=0,this._vy=0,this._lastMoveTs=performance.now()}}else if(this._isTouchPanning&&0===this._touchPointers.size){this._isTouchPanning=!1;const t=performance.now(),e=this._lastMoveTs?t-this._lastMoveTs:1/0;if(e>=this._options.idleNoInertiaMs)this._vx=0,this._vy=0;else{const t=Math.pow(this._options.friction,e/16);this._vx*=t,this._vy*=t}Math.hypot(this._vx,this._vy)<this._options.stopSpeed&&(this._vx=0,this._vy=0)}}_onTouchCancel(t){this._touchPointers.delete(t.pointerId),this._isPinching&&this._endPinch(),0===this._touchPointers.size&&(this._isTouchPanning=!1,this._vx=0,this._vy=0)}_startPinch(){this._isPinching=!0;const[t,e]=Array.from(this._touchPointers.values());this._lastPinchDistance=Math.hypot(e.x-t.x,e.y-t.y),this._lastPinchCenterX=(t.x+e.x)/2,this._lastPinchCenterY=(t.y+e.y)/2}_handlePinchMove(){if(!this._view||!this._zoomEnabled)return;const t=Array.from(this._touchPointers.values());if(2!==t.length)return;const[e,i]=t,s=Math.hypot(i.x-e.x,i.y-e.y),n=(e.x+i.x)/2,h=(e.y+i.y)/2;if(this._lastPinchDistance>0){const t=s/this._lastPinchDistance,e=this._view.canvas.getBoundingClientRect(),i=n-e.left,o=h-e.top;this._view.zoomByFactorAtScreen(i,o,t);const a=n-this._lastPinchCenterX,r=h-this._lastPinchCenterY;this._view.panBy(a,r)}this._lastPinchDistance=s,this._lastPinchCenterX=n,this._lastPinchCenterY=h}_endPinch(){this._isPinching=!1,this._lastPinchDistance=0,this._lastPinchCenterX=0,this._lastPinchCenterY=0}_getLineHeightPx(){if(!this._view)return 16;const t=getComputedStyle(this._view.canvas).lineHeight;if(!t||"normal"===t)return 16;const e=parseFloat(t);return Number.isFinite(e)?e:16}_normalizeWheelDelta(t){if(!this._view)return 0;let e=t.deltaY;if(1===t.deltaMode)e*=this._getLineHeightPx();else if(2===t.deltaMode){e*=this._view.canvas.clientHeight||window.innerHeight||800}return e}_onWheel(t){if(!this._zoomEnabled||!this._view)return;t.preventDefault(),t.stopPropagation();const e=this._normalizeWheelDelta(t),i=this._view.canvas.getBoundingClientRect(),s=t.clientX-i.left,n=t.clientY-i.top;let h=-e*this._options.wheelSensitivity;t.ctrlKey||t.metaKey?h*=1.6:t.shiftKey&&(h*=.6),this._view.zoomByLogAtScreen(s,n,h)}}function v(t){return new g(t)}class p{constructor(t){var e,i,s,n,h;this.name="document",this._view=null,this._enabled=!1,this._x=0,this._y=0,this._width=0,this._height=0,this._marginL=0,this._marginR=0,this._marginT=0,this._marginB=0,this._panClampMode="minVisible",this._background=null,this._shadow=null,this._onUpdate=()=>{this._enabled&&this._view&&this._clampPan()},this._onBeforeRender=t=>{var e,i,s,n,h;this._enabled&&this._view&&(this._shadow?(t.save(),t.shadowColor=null!==(e=this._shadow.color)&&void 0!==e?e:p._defaultShadow.color,t.shadowBlur=null!==(i=this._shadow.blur)&&void 0!==i?i:p._defaultShadow.blur,t.shadowOffsetX=null!==(s=this._shadow.offsetX)&&void 0!==s?s:p._defaultShadow.offsetX,t.shadowOffsetY=null!==(n=this._shadow.offsetY)&&void 0!==n?n:p._defaultShadow.offsetY,t.fillStyle=null!==(h=this._background)&&void 0!==h?h:"#ffffff",t.fillRect(this._x,this._y,this._width,this._height),t.restore()):this._background&&(t.save(),t.fillStyle=this._background,t.fillRect(this._x,this._y,this._width,this._height),t.restore()),t.save(),t.beginPath(),t.rect(this._x,this._y,this._width,this._height),t.clip())},this._onAfterRender=t=>{if(this._enabled&&this._view&&(t.restore(),this._options.drawBorder)){const e=this._view.zoom;t.save(),t.lineWidth=1/e,t.strokeStyle="#cfcfcf",t.strokeRect(this._x,this._y,this._width,this._height),t.restore()}},this._options=Object.assign({rect:{x:0,y:0,width:0,height:0},margins:{},drawBorder:!1,minVisiblePx:30,panClampMode:"minVisible",background:null,shadow:!1},t),(null==t?void 0:t.rect)&&(this._enabled=!0,this._x=t.rect.x,this._y=t.rect.y,this._width=t.rect.width,this._height=t.rect.height),(null==t?void 0:t.margins)&&(this._marginL=null!==(e=t.margins.left)&&void 0!==e?e:0,this._marginR=null!==(i=t.margins.right)&&void 0!==i?i:0,this._marginT=null!==(s=t.margins.top)&&void 0!==s?s:0,this._marginB=null!==(n=t.margins.bottom)&&void 0!==n?n:0),this._panClampMode=this._options.panClampMode,this._background=null!==(h=this._options.background)&&void 0!==h?h:null,!0===this._options.shadow?this._shadow=Object.assign({},p._defaultShadow):this._options.shadow&&"object"==typeof this._options.shadow&&(this._shadow=Object.assign(Object.assign({},p._defaultShadow),this._options.shadow))}install(t){this._view=t,t.onUpdate(this._onUpdate),t.onBeforeRender(this._onBeforeRender),t.onAfterRender(this._onAfterRender)}destroy(){this._view&&(this._view.offUpdate(this._onUpdate),this._view.offBeforeRender(this._onBeforeRender),this._view.offAfterRender(this._onAfterRender),this._view=null)}isEnabled(){return this._enabled}getRect(){return{x:this._x,y:this._y,width:this._width,height:this._height}}setRect(t,e,i,s){this._enabled=!0,this._x=t,this._y=e,this._width=i,this._height=s}clearRect(){this._enabled=!1}setMargins(t){var e,i,s,n;this._marginL=null!==(e=t.left)&&void 0!==e?e:this._marginL,this._marginR=null!==(i=t.right)&&void 0!==i?i:this._marginR,this._marginT=null!==(s=t.top)&&void 0!==s?s:this._marginT,this._marginB=null!==(n=t.bottom)&&void 0!==n?n:this._marginB}getMargins(){return{left:this._marginL,right:this._marginR,top:this._marginT,bottom:this._marginB}}setPanClampMode(t){this._panClampMode=t}getPanClampMode(){return this._panClampMode}cropTo(t){this._doResize("crop",t)}resizeTo(t){this._doResize("resize",t)}zoomToFit(t="contain",e=!0){if(!this._enabled||!this._view)return;const i=this._view.dpr,s=this._view.canvas.width/i,n=this._view.canvas.height/i,h=Math.max(1,s-(this._marginL+this._marginR)),o=Math.max(1,n-(this._marginT+this._marginB));let a;const r=h/this._width,c=o/this._height;a="contain"===t?Math.min(r,c):"cover"===t?Math.max(r,c):"fitWidth"===t?r:c,a=Math.min(this._view.maxZoom,Math.max(this._view.minZoom,a));const _=this._marginL+(h-a*this._width)/2,l=this._marginT+(o-a*this._height)/2,d=_-a*this._x,u=l-a*this._y;e?this._view.setTransformSmooth(a,d,u):this._view.setTransform(a,d,u)}isPointInDocument(t,e){return!this._enabled||t>=this._x&&t<=this._x+this._width&&e>=this._y&&e<=this._y+this._height}get background(){return this._background}setBackground(t){var e;this._background=t,null===(e=this._view)||void 0===e||e.requestRender()}get shadow(){return this._shadow?Object.assign({},this._shadow):null}setShadow(t){var e;this._shadow=!0===t?Object.assign({},p._defaultShadow):t&&"object"==typeof t?Object.assign(Object.assign({},p._defaultShadow),t):null,null===(e=this._view)||void 0===e||e.requestRender()}_clampPan(){if(!this._view)return;const{zoom:t,tx:e,ty:i}=this._view.getTransform(),s=t,n=this._view.dpr,h=this._view.canvas.width/n,o=this._view.canvas.height/n,a=this._x,r=this._y,c=this._x+this._width,_=this._y+this._height;let l=e,d=i;if("margin"===this._panClampMode){const t=this._marginL-s*a,n=h-this._marginR-s*c,u=this._marginT-s*r,g=o-this._marginB-s*_,v=Math.max(1,h-(this._marginL+this._marginR)),p=Math.max(1,o-(this._marginT+this._marginB));l=s*this._width<=v?this._marginL+(v-s*this._width)/2-s*this._x:Math.min(t,Math.max(n,e)),d=s*this._height<=p?this._marginT+(p-s*this._height)/2-s*this._y:Math.min(u,Math.max(g,i))}else if("minVisible"===this._panClampMode){const t=s*this._width,n=s*this._height,u=Math.min(this._options.minVisiblePx,t),g=Math.min(this._options.minVisiblePx,n),v=h-u-s*a,p=u-s*c,m=o-g-s*r,y=g-s*_;l=p<=v?Math.min(v,Math.max(p,e)):(p+v)/2,d=y<=m?Math.min(m,Math.max(y,i)):(y+m)/2}l===e&&d===i||this._view.setPan(l,d)}_doResize(t,e){if(!this._view)return;const i=Math.max(1,Math.floor(e.width)),s=Math.max(1,Math.floor(e.height)),n={width:i,height:s},h=this._view.getLayerManagers();for(const e of h){const i=e.getAllLayers("world");for(const e of i){const i=e;"function"==typeof i.cropTo&&"function"==typeof i.resizeTo&&("crop"===t?i.cropTo(n):i.resizeTo(n))}}this._width=i,this._height=s,this._enabled&&this._clampPan()}}function m(t){return new p(t)}p._defaultShadow={color:"rgba(0, 0, 0, 0.3)",blur:20,offsetX:0,offsetY:4};class y{constructor(t,e,i,s){this.type="snapshot",this._isExecuted=!0,this._target=t,this._beforeData=e,this._afterData=i,this._region=null==s?void 0:s.region}execute(){if(this._isExecuted)return;const t=this._region?{x:this._region.x,y:this._region.y}:void 0;this._target.restoreSnapshot(this._afterData,t),this._isExecuted=!0}undo(){if(!this._isExecuted)return;const t=this._region?{x:this._region.x,y:this._region.y}:void 0;this._target.restoreSnapshot(this._beforeData,t),this._isExecuted=!1}canMerge(){return!1}merge(){return this}}function f(t,e,i,s){return e&&i?new y(t,e,i,s):null}class w{constructor(t){this.type="create-layer",this._layer=t.layer,this._layerManager=t.layerManager,this._insertIndex=t.insertIndex,this._previousSelectedId=t.previousSelectedId,this._getLayerList=t.getLayerList,this._setSelectedId=t.setSelectedId}execute(){this._layerManager.addLayer(this._layer,this._insertIndex);this._getLayerList().splice(this._insertIndex,0,this._layer),this._setSelectedId(this._layer.id)}undo(){this._layerManager.detachLayer(this._layer.id);const t=this._getLayerList(),e=t.findIndex(t=>t.id===this._layer.id);e>-1&&t.splice(e,1),this._setSelectedId(this._previousSelectedId)}}class x{constructor(t){this.type="delete-layer",this._layer=t.layer,this._layerManager=t.layerManager,this._originalIndex=t.originalIndex,this._previousSelectedId=t.previousSelectedId,this._newSelectedId=t.newSelectedId,this._getLayerList=t.getLayerList,this._setSelectedId=t.setSelectedId}execute(){this._layerManager.detachLayer(this._layer.id);const t=this._getLayerList(),e=t.findIndex(t=>t.id===this._layer.id);e>-1&&t.splice(e,1),this._setSelectedId(this._newSelectedId)}undo(){this._layerManager.addLayer(this._layer,this._originalIndex);this._getLayerList().splice(this._originalIndex,0,this._layer),this._setSelectedId(this._previousSelectedId)}}class M{executeCommand(t){t.execute(),this.addCommand(t)}addCommand(t){var e,i;this._redoStack=[];const s=this._undoStack[this._undoStack.length-1];if(s&&(null===(e=s.canMerge)||void 0===e?void 0:e.call(s,t))&&s.merge){const e=null!==(i=s.merge(t))&&void 0!==i?i:s;return void(e!==s&&(this._undoStack[this._undoStack.length-1]=e))}this._undoStack.push(t),this._undoStack.length>this._maxHistorySize&&this._undoStack.shift()}undo(){if(0===this._undoStack.length)return null;const t=this._undoStack.pop();return t.undo(),this._redoStack.push(t),t}redo(){if(0===this._redoStack.length)return null;const t=this._redoStack.pop();return t.execute(),this._undoStack.push(t),t}canUndo(){return this._undoStack.length>0}canRedo(){return this._redoStack.length>0}clear(){this._undoStack=[],this._redoStack=[]}setMaxHistorySize(t){this._maxHistorySize=Math.max(1,t),this._undoStack.length>this._maxHistorySize&&(this._undoStack=this._undoStack.slice(-this._maxHistorySize))}constructor(t){var e,i,s;this._undoStack=[],this._redoStack=[],this._maxHistorySize=null!==(e=null==t?void 0:t.maxHistorySize)&&void 0!==e?e:50,this._undoStack=null!==(i=null==t?void 0:t.undoStack)&&void 0!==i?i:[],this._redoStack=null!==(s=null==t?void 0:t.redoStack)&&void 0!==s?s:[]}}export{_ as BitmapLayer,r as CanvasLayer,d as ContentLayerManager,w as CreateLayerCommand,x as DeleteLayerCommand,p as DocumentPlugin,M as HistoryManager,g as InteractionPlugin,a as LayerBase,l as LayerManagerBase,y as SnapshotCommand,u as TopScreenLayerManager,h as ViewManager,m as createDocumentPlugin,v as createInteractionPlugin,f as createSnapshotCommand};
1
+ function t(t,i,e,s){return new(e||(e=Promise))(function(n,h){function o(t){try{r(s.next(t))}catch(t){h(t)}}function a(t){try{r(s.throw(t))}catch(t){h(t)}}function r(t){var i;t.done?n(t.value):(i=t.value,i instanceof e?i:new e(function(t){t(i)})).then(o,a)}r((s=s.apply(t,i||[])).next())})}function i(t,i,e,s){if("a"===e&&!s)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof i?t!==i||!s:!i.has(t))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===e?s:"a"===e?s.call(t):s?s.value:i.get(t)}function e(t,i,e,s,n){if("m"===s)throw new TypeError("Private method is not writable");if("a"===s&&!n)throw new TypeError("Private accessor was defined without a setter");if("function"==typeof i?t!==i||!n:!i.has(t))throw new TypeError("Cannot write private member to an object whose class did not declare it");return"a"===s?n.call(t,e):n?n.value=e:i.set(t,e),e}"function"==typeof SuppressedError&&SuppressedError;const s=(i,e)=>t(void 0,void 0,void 0,function*(){return new Promise((t,s)=>{const n=new Image;"string"==typeof i?(void 0!==e&&(n.crossOrigin=e),n.src=i):n.src=URL.createObjectURL(i),n.onload=()=>{t(n)},n.onerror=()=>{s(new Error("Image load failed"))}})}),n=(t,i,e)=>Math.min(Math.max(t,i),e);class h{get zoom(){return Math.exp(this._currentLogZ)}get minZoom(){return this._options.minZoom}get maxZoom(){return this._options.maxZoom}get isAnimating(){return this._isAnimatingTransform}get dpr(){return this._dpr}use(t){return this._plugins.has(t.name)?(console.warn(`Plugin "${t.name}" is already installed.`),t):(this._plugins.set(t.name,t),t.install(this),t)}unuse(t){const i=this._plugins.get(t);i&&(i.destroy(),this._plugins.delete(t))}getPlugin(t){return this._plugins.get(t)}onUpdate(t){this._updateCallbacks.add(t)}offUpdate(t){this._updateCallbacks.delete(t)}onBeforeRender(t){this._beforeRenderCallbacks.add(t)}offBeforeRender(t){this._beforeRenderCallbacks.delete(t)}onAfterRender(t){this._afterRenderCallbacks.add(t)}offAfterRender(t){this._afterRenderCallbacks.delete(t)}requestRender(){this._needsRender=!0}_clampLog(t){return n(t,this.LOG_MIN,this.LOG_MAX)}_setTargetLogZoomAtScreen(t,i,e){Number.isFinite(e)&&(this._anchorX=t,this._anchorY=i,this._targetLogZ=this._clampLog(e),this._needsRender=!0)}zoomToAtScreen(t,i,e){this._setTargetLogZoomAtScreen(t,i,Math.log(e))}zoomToAtScreenRaw(t,i,e){if(!Number.isFinite(e))return;const s=Math.max(1e-8,this._options.minZoom),h=this._options.maxZoom,o=n(e,s,h),a=Math.exp(this._currentLogZ),r=o;if(!Number.isFinite(a)||a<=0)return;if(Math.abs(r-a)<1e-12)return;const c=Math.log(o);this._currentLogZ=c,this._targetLogZ=c;const _=r/a;this._tx=t-(t-this._tx)*_,this._ty=i-(i-this._ty)*_,this._needsRender=!0}zoomToAtWorld(t,i,e){const{x:s,y:n}=this.toScreen(t,i);this.zoomToAtScreen(s,n,e)}zoomByFactorAtScreen(t,i,e){if(e<=0||!Number.isFinite(e))return;const s=Math.log(e);this._setTargetLogZoomAtScreen(t,i,this._targetLogZ+s)}zoomByLogAtScreen(t,i,e){this._setTargetLogZoomAtScreen(t,i,this._targetLogZ+e)}zoomByFactorAtWorld(t,i,e){const{x:s,y:n}=this.toScreen(t,i);this.zoomByFactorAtScreen(s,n,e)}panBy(t,i){this._tx+=t,this._ty+=i,this._needsRender=!0}setPan(t,i){this._tx=t,this._ty=i,this._needsRender=!0}setTransform(t,i,e){const s=n(t,this._options.minZoom,this._options.maxZoom);this._currentLogZ=Math.log(s),this._targetLogZ=this._currentLogZ,this._tx=i,this._ty=e,this._targetTx=null,this._targetTy=null,this._needsRender=!0}setTransformSmooth(t,i,e){const s=n(t,this._options.minZoom,this._options.maxZoom);this._targetLogZ=Math.log(s),this._targetTx=i,this._targetTy=e,this._isAnimatingTransform=!0,this._needsRender=!0}_ensureOffscreenSizeLike(t,i){t.width===i.width&&t.height===i.height||(t.width=i.width,t.height=i.height)}_loop(){if(this._isResizing)return void(this._raf=requestAnimationFrame(()=>this._loop()));const t=performance.now(),i=Math.max(1,t-this._lastFrameTs);this._lastFrameTs=t;const{approachKZoom:e}=this._options,s=Math.exp(this._currentLogZ),n=this._targetLogZ-this._currentLogZ,h=Math.abs(n)>1e-6;if(h){const t=1-Math.exp(-e*i);this._currentLogZ+=n*t}const o=Math.exp(this._currentLogZ);if(o!==s){const t=this._anchorX,i=this._anchorY,e=o/s;this._tx=t-(t-this._tx)*e,this._ty=i-(i-this._ty)*e}let a=!1;if(null!==this._targetTx&&null!==this._targetTy){const t=1-Math.exp(-this._options.approachKPan*i),e=this._targetTx-this._tx,s=this._targetTy-this._ty;a=Math.abs(e)>.5||Math.abs(s)>.5,a?(this._tx+=e*t,this._ty+=s*t):(this._tx=this._targetTx,this._ty=this._targetTy,this._targetTx=null,this._targetTy=null)}if(this._isAnimatingTransform){const t=Math.abs(this._targetLogZ-this._currentLogZ)<1e-5,i=null===this._targetTx&&null===this._targetTy;t&&i&&(this._isAnimatingTransform=!1)}if(this._isResetting){const t=1-Math.exp(-this._options.approachKPan*i);this._tx+=(0-this._tx)*t,this._ty+=(0-this._ty)*t;const e=Math.abs(this._currentLogZ)<.001&&Math.abs(this._targetLogZ)<1e-6,s=Math.abs(this._tx)<.5&&Math.abs(this._ty)<.5;e&&s&&(this._currentLogZ=0,this._targetLogZ=0,this._tx=0,this._ty=0,this._isResetting=!1)}for(const t of this._updateCallbacks)t(i);if(!(this._needsRender||h||a||this._isResetting))return void(this._raf=requestAnimationFrame(()=>this._loop()));this._needsRender=!1;const r=this.contentCanvas,c=this.contentContext,_=this.topScreenCanvas,l=this.topScreenContext,d=this.canvas,u=this.context;this._ensureOffscreenSizeLike(r,d),this._ensureOffscreenSizeLike(_,d),c.setTransform(1,0,0,1,0,0),l.setTransform(1,0,0,1,0,0),u.setTransform(1,0,0,1,0,0);const g=this._options.background;"string"==typeof g&&""!==g.trim()&&"transparent"!==g.toLowerCase()?(u.fillStyle=g,u.fillRect(0,0,d.width,d.height)):u.clearRect(0,0,d.width,d.height),c.clearRect(0,0,r.width,r.height),l.clearRect(0,0,_.width,_.height),c.setTransform(this._dpr*o,0,0,this._dpr*o,this._dpr*this._tx,this._dpr*this._ty);for(const t of this._beforeRenderCallbacks)t(c);if(this._render)this._render(this);else for(const t of this._layerManagers)t.renderAllLayersIn(this);for(const t of this._afterRenderCallbacks)t(c);u.drawImage(r,0,0),u.drawImage(_,0,0),this._raf=requestAnimationFrame(()=>this._loop())}applyWorldTransform(t){const i=Math.exp(this._currentLogZ);t.setTransform(this._dpr*i,0,0,this._dpr*i,this._dpr*this._tx,this._dpr*this._ty)}applyScreenTransform(t){t.setTransform(this._dpr,0,0,this._dpr,0,0)}getPixelColorAtScreen(t,i){const e=Math.floor(t*this._dpr),s=Math.floor(i*this._dpr);if(e<0||s<0||e>=this.canvas.width||s>=this.canvas.height)return{r:0,g:0,b:0,a:0,rgba:"rgba(0,0,0,0)",hex:"#000000"};const n=this.contentContext.getImageData(e,s,1,1).data,h=n[0],o=n[1],a=n[2],r=n[3]/255,c=t=>t.toString(16).padStart(2,"0"),_=`#${c(h)}${c(o)}${c(a)}`;return{r:h,g:o,b:a,a:r,rgba:`rgba(${h},${o},${a},${r.toFixed(3)})`,hex:_}}getPixelColorAtWorld(t,i){const{x:e,y:s}=this.toScreen(t,i);return this.getPixelColorAtScreen(e,s)}registerLayerManager(t){t&&(this._layerManagers.includes(t)||(this._layerManagers.push(t),this._needsRender=!0))}unregisterLayerManager(t){const i=this._layerManagers.indexOf(t);i>=0&&(this._layerManagers.splice(i,1),this._needsRender=!0)}getLayerManagers(){return[...this._layerManagers]}resetSmooth(){this._isResetting=!0,this._targetLogZ=0,this._needsRender=!0}resetInstant(){this._currentLogZ=0,this._targetLogZ=0,this._tx=0,this._ty=0,this._needsRender=!0}toWorld(t,i){const e=Math.exp(this._currentLogZ);return{wx:(t-this._tx)/e,wy:(i-this._ty)/e}}toScreen(t,i){const e=Math.exp(this._currentLogZ);return{x:t*e+this._tx,y:i*e+this._ty}}getTransform(){return{zoom:Math.exp(this._currentLogZ),tx:this._tx,ty:this._ty}}getViewportBounds(){const t=Math.exp(this._currentLogZ),i=this.canvas.width/this._dpr,e=this.canvas.height/this._dpr,s=-this._tx/t,n=-this._ty/t,h=(i-this._tx)/t,o=(e-this._ty)/t;return{left:s,top:n,right:h,bottom:o,width:h-s,height:o-n}}setZoomRange(t,i){this._options.minZoom=t,this._options.maxZoom=i,this.LOG_MIN=Math.log(t),this.LOG_MAX=Math.log(i),this._targetLogZ=Math.min(this.LOG_MAX,Math.max(this.LOG_MIN,this._targetLogZ))}resizeToParent(){this._isResizing=!0;const t=(this.canvas.parentElement||this.canvas).getBoundingClientRect();this._dpr=Math.max(1,window.devicePixelRatio||1);const i=Math.max(1,Math.round(t.width)),e=Math.max(1,Math.round(t.height));this.canvas.width=Math.round(i*this._dpr),this.canvas.height=Math.round(e*this._dpr),this.canvas.style.width=`${i}px`,this.canvas.style.height=`${e}px`,this._ensureOffscreenSizeLike(this.contentCanvas,this.canvas),this._ensureOffscreenSizeLike(this.topScreenCanvas,this.canvas),clearTimeout(this._resizeReleaseTimer),this._resizeReleaseTimer=window.setTimeout(()=>{this._isResizing=!1},50)}destroy(){cancelAnimationFrame(this._raf);for(const t of this._plugins.values())t.destroy();this._plugins.clear(),this._resizeObserver&&this._resizeObserver.disconnect(),this._layerManagers=[],this._updateCallbacks.clear(),this._beforeRenderCallbacks.clear(),this._afterRenderCallbacks.clear()}constructor(t,i){var e;this._layerManagers=[],this._plugins=new Map,this._isResetting=!1,this._isResizing=!1,this._needsRender=!0,this._raf=0,this._lastFrameTs=performance.now(),this._tx=0,this._ty=0,this._anchorX=0,this._anchorY=0,this._currentLogZ=Math.log(1),this._targetLogZ=Math.log(1),this._targetTx=null,this._targetTy=null,this._isAnimatingTransform=!1,this._updateCallbacks=new Set,this._beforeRenderCallbacks=new Set,this._afterRenderCallbacks=new Set,this._dpr=Math.max(1,window.devicePixelRatio||1);const s=t.getContext("2d",{willReadFrequently:!0,alpha:!0});if(!s)throw new Error("2D context not available");this.canvas=t,this.context=s,this._render=null!==(e=null==i?void 0:i.render)&&void 0!==e?e:null,this.contentCanvas=document.createElement("canvas"),this.contentCanvas.width=t.width,this.contentCanvas.height=t.height,this.contentContext=this.contentCanvas.getContext("2d",{alpha:!0,willReadFrequently:!0}),this.topScreenCanvas=document.createElement("canvas"),this.topScreenCanvas.width=t.width,this.topScreenCanvas.height=t.height,this.topScreenContext=this.topScreenCanvas.getContext("2d",{alpha:!0}),this._options=Object.assign({minZoom:.5,maxZoom:10,approachKZoom:.022,approachKPan:.022,autoResize:!0,background:"#fff"},i),this.LOG_MIN=Math.log(this._options.minZoom),this.LOG_MAX=Math.log(this._options.maxZoom),this._options.autoResize&&(this._resizeObserver=new ResizeObserver(()=>this.resizeToParent()),this._resizeObserver.observe(this.canvas.parentElement||this.canvas)),this.resizeToParent(),this._lastFrameTs=performance.now(),this._raf=requestAnimationFrame(()=>this._loop())}}let o=0;class a{constructor(t,i,e="world"){this.space="world",this.visible=!0,this.opacity=1,this.blend="source-over",this.name=t,this.id=`layer_${i}_${++o}`,this.type=i,this.space=e}}class r extends a{beginStroke(t,i){const{lx:e,ly:s}=this.toLocalPoint(t,i);this._lastX=e,this._lastY=s,this._drawing=!0}stroke(t,i,e,s,n=1,h="brush"){if(!this._drawing)return;const{lx:o,ly:a}=this.toLocalPoint(t,i);this.context.beginPath(),this.context.moveTo(this._lastX,this._lastY),this.context.lineTo(o,a),"eraser"===h?(this.context.globalCompositeOperation="destination-out",this.context.strokeStyle="rgba(0, 0, 0, 1)"):(this.context.globalCompositeOperation="source-over",this.context.strokeStyle=e),this.context.lineWidth=s*n,this.context.lineCap="round",this.context.lineJoin="round",this.context.stroke(),this.context.closePath(),this._lastX=o,this._lastY=a}endStroke(){this._drawing=!1}isDrawing(){return this._drawing}captureSnapshot(t){try{if(t){const{x:i,y:e,width:s,height:n}=t,h=Math.max(0,Math.floor(i)),o=Math.max(0,Math.floor(e)),a=Math.min(this.canvas.width-h,Math.ceil(s)),r=Math.min(this.canvas.height-o,Math.ceil(n));return a<=0||r<=0?null:this.context.getImageData(h,o,a,r)}return this.context.getImageData(0,0,this.canvas.width,this.canvas.height)}catch(t){return null}}restoreSnapshot(t,i){var e,s;const n=null!==(e=null==i?void 0:i.x)&&void 0!==e?e:0,h=null!==(s=null==i?void 0:i.y)&&void 0!==s?s:0;this.context.putImageData(t,n,h)}clearRegion(t){t?this.context.clearRect(t.x,t.y,t.width,t.height):this.context.clearRect(0,0,this.canvas.width,this.canvas.height)}requestRedraw(){var t;null===(t=this._redraw)||void 0===t||t.call(this,this.context,this.canvas)}drawImage(t,i,e,s,n){this.context.drawImage(t,i,e,null!=s?s:t.width,null!=n?n:t.height)}hitTest(t,i){const{lx:e,ly:s}=this.toLocalPoint(t,i);return e>=0&&e<=this.canvas.width&&s>=0&&s<=this.canvas.height}toLocalPoint(t,i){const e=t-this.x,s=i-this.y,n=Math.cos(-this.rotation),h=Math.sin(-this.rotation),o=e*h+s*n,a=(e*n-s*h)/this.scale,r=o/this.scale;return{lx:a+("center"===this.anchor?this.canvas.width/2:0),ly:r+("center"===this.anchor?this.canvas.height/2:0)}}render(t,i){if(!this.visible)return;const e=this.canvas.width*this.scale,s=this.canvas.height*this.scale,n="center"===this.anchor?-e/2:0,h="center"===this.anchor?-s/2:0;t.save(),t.globalAlpha=this.opacity,t.globalCompositeOperation=this.blend,t.translate(this.x,this.y),t.rotate(this.rotation),t.drawImage(this.canvas,n,h,e,s),t.restore()}cropTo(t){const i=Math.max(1,Math.floor(t.width)),e=Math.max(1,Math.floor(t.height));if(i===this.canvas.width&&e===this.canvas.height)return;const s=this._cloneCanvas(),n=Math.min(s.width,i),h=Math.min(s.height,e);this._setCanvasSize(i,e),n>0&&h>0&&this.context.drawImage(s,0,0,n,h,0,0,n,h)}resizeTo(t){const i=Math.max(1,Math.floor(t.width)),e=Math.max(1,Math.floor(t.height));if(i===this.canvas.width&&e===this.canvas.height)return;const s=this._cloneCanvas();this._setCanvasSize(i,e),s.width>0&&s.height>0&&this.context.drawImage(s,0,0,s.width,s.height,0,0,i,e)}_cloneCanvas(){const t=document.createElement("canvas");if(t.width=this.canvas.width,t.height=this.canvas.height,0===t.width||0===t.height)return t;const i=t.getContext("2d");if(!i)throw new Error("Offscreen 2D context unavailable");return i.drawImage(this.canvas,0,0),t}_setCanvasSize(t,i){this.canvas.width=t,this.canvas.height=i,this.context.setTransform(1,0,0,1,0,0),this.context.clearRect(0,0,t,i)}destroy(){this.canvas.width=0,this.canvas.height=0}constructor(t){var i,e;if(super(t.name||"","canvas",null!==(i=t.space)&&void 0!==i?i:"world"),this.x=0,this.y=0,this.scale=1,this.rotation=0,this.anchor="topLeft",this._drawing=!1,this._lastX=0,this._lastY=0,"canvas"in t&&t.canvas)this.canvas=t.canvas;else{const i=t;this.canvas=document.createElement("canvas"),this.canvas.width=i.width,this.canvas.height=i.height}const s=this.canvas.getContext("2d",{willReadFrequently:!0});if(!s)throw new Error("Offscreen 2D context unavailable");this.context=s,this.x=t.x||0,this.y=t.y||0,this.scale=null!==(e=t.scale)&&void 0!==e?e:1,this.rotation=t.rotation||0,t.anchor&&(this.anchor=t.anchor),this._redraw=t.redraw,this._redraw&&this._redraw(this.context,this.canvas)}}var c;class _ extends r{static fromImage(i){return t(this,void 0,void 0,function*(){var t,n,h,o,a,r,l,d;const u=yield s(i.src,i.crossOrigin),g=null!==(t=i.width)&&void 0!==t?t:u.naturalWidth,v=null!==(n=i.height)&&void 0!==n?n:u.naturalHeight,p=new _({name:i.name,space:null!==(h=i.space)&&void 0!==h?h:"world",x:null!==(o=i.x)&&void 0!==o?o:0,y:null!==(a=i.y)&&void 0!==a?a:0,scale:null!==(r=i.scale)&&void 0!==r?r:1,rotation:null!==(l=i.rotation)&&void 0!==l?l:0,anchor:null!==(d=i.anchor)&&void 0!==d?d:"topLeft",width:g,height:v});return p.context.clearRect(0,0,p.canvas.width,p.canvas.height),p.context.drawImage(u,0,0,g,v),"string"!=typeof i.src&&e(p,c,u.src.startsWith("blob:")?u.src:null,"f"),p})}setSource(n,h){return t(this,void 0,void 0,function*(){const t=yield s(n,h);if(this.canvas.width=t.naturalWidth,this.canvas.height=t.naturalHeight,this.context.setTransform(1,0,0,1,0,0),this.context.clearRect(0,0,this.canvas.width,this.canvas.height),this.context.drawImage(t,0,0),i(this,c,"f")){try{URL.revokeObjectURL(i(this,c,"f"))}catch(t){}e(this,c,null,"f")}"string"!=typeof n&&e(this,c,t.src.startsWith("blob:")?t.src:null,"f")})}paint(t){t(this.context,this.canvas)}getImageData(t=0,i=0,e=this.canvas.width,s=this.canvas.height){return this.context.getImageData(t,i,e,s)}putImageData(t,i=0,e=0){this.context.putImageData(t,i,e)}toDataURL(t="image/png",i){return this.canvas.toDataURL(t,i)}toImageBitmap(t){return createImageBitmap(this.canvas,null!=t?t:{})}destroy(){var t;if(null===(t=super.destroy)||void 0===t||t.call(this),i(this,c,"f")){try{URL.revokeObjectURL(i(this,c,"f"))}catch(t){}e(this,c,null,"f")}}constructor(t){var i,e;super({name:t.name,space:null!==(i=t.space)&&void 0!==i?i:"world",x:t.x,y:t.y,scale:t.scale,rotation:t.rotation,anchor:null!==(e=t.anchor)&&void 0!==e?e:"topLeft",width:t.width,height:t.height}),c.set(this,null),this.type="bitmap"}}c=new WeakMap;class l{constructor(){this._worldLayers=[],this._screenLayers=[]}_renderAllLayersIn(t,i){i.save(),t.applyWorldTransform(i);for(const e of this._worldLayers)!e.visible||e.opacity<=0||(i.save(),e.render(i,t),i.restore());i.restore(),i.save(),t.applyScreenTransform(i);for(const e of this._screenLayers)!e.visible||e.opacity<=0||(i.save(),e.render(i,t),i.restore());i.restore()}renderAllLayersIn(t){const i=t.contentContext;this._renderAllLayersIn(t,i)}addLayer(t,i){const e="world"===t.space?this._worldLayers:this._screenLayers;return"number"==typeof i&&i>=0&&i<e.length?(e.splice(i,0,t),t.id):(e.push(t),t.id)}createImageLayer(i){return t(this,void 0,void 0,function*(){const t=yield _.fromImage(i);return this.addLayer(t),t})}createCanvasLayer(t){const i=new r(t);return this.addLayer(i),i}removeLayer(t){var i,e,s,n;const h=this._worldLayers.findIndex(i=>i.id===t);if(h>=0)return null===(e=(i=this._worldLayers[h]).destroy)||void 0===e||e.call(i),void this._worldLayers.splice(h,1);const o=this._screenLayers.findIndex(i=>i.id===t);o>=0&&(null===(n=(s=this._screenLayers[o]).destroy)||void 0===n||n.call(s),this._screenLayers.splice(o,1))}detachLayer(t){const i=this._worldLayers.findIndex(i=>i.id===t);if(i>=0)return void this._worldLayers.splice(i,1);const e=this._screenLayers.findIndex(i=>i.id===t);e>=0&&this._screenLayers.splice(e,1)}moveLayer(t,i){const e=this._worldLayers.findIndex(i=>i.id===t);if(e>=0){const[t]=this._worldLayers.splice(e,1),s=Math.max(0,Math.min(i,this._worldLayers.length));return void this._worldLayers.splice(s,0,t)}const s=this._screenLayers.findIndex(i=>i.id===t);if(s>=0){const[t]=this._screenLayers.splice(s,1),e=Math.max(0,Math.min(i,this._screenLayers.length));this._screenLayers.splice(e,0,t)}}reorderLayers(t){const i=[];for(const e of t){const t=this._worldLayers.find(t=>t.id===e);t&&i.push(t)}for(const e of this._worldLayers)t.includes(e.id)||i.push(e);this._worldLayers=i}getLayer(t){return this._worldLayers.find(i=>i.id===t)||this._screenLayers.find(i=>i.id===t)}getAllLayers(t){return t?("world"===t?this._worldLayers:this._screenLayers).slice():[...this._worldLayers,...this._screenLayers]}hitTest(t,i,e="world"){const s=this.getAllLayers(e);for(let e=s.length-1;e>=0;e--){const n=s[e];if(n.hitTest&&n.hitTest(t,i))return n}}destroy(){var t;for(const i of[...this._worldLayers,...this._screenLayers])null===(t=i.destroy)||void 0===t||t.call(i);this._worldLayers=[],this._screenLayers=[]}}class d extends l{constructor(){super(...arguments),this._compositeCache=null,this._compositeCacheCtx=null,this._compositeDirty=!0,this._lastCacheWidth=0,this._lastCacheHeight=0,this._cachedBoundsMinX=0,this._cachedBoundsMinY=0}markDirty(){this._compositeDirty=!0}addLayer(t,i){return this._compositeDirty=!0,super.addLayer(t,i)}removeLayer(t){this._compositeDirty=!0,super.removeLayer(t)}detachLayer(t){this._compositeDirty=!0,super.detachLayer(t)}removeAllLayers(t){var i,e;if(!t||"world"===t){for(const t of this._worldLayers)null===(i=t.destroy)||void 0===i||i.call(t);this._worldLayers=[]}if(!t||"screen"===t){for(const t of this._screenLayers)null===(e=t.destroy)||void 0===e||e.call(t);this._screenLayers=[]}}moveLayer(t,i){this._compositeDirty=!0,super.moveLayer(t,i)}renderAllLayersIn(t){const i=t.contentContext,e=this._worldLayers;0!==e.length&&(this._compositeDirty&&this._rebuildCompositeCache(e),this._compositeCache&&this._compositeCacheCtx&&i.drawImage(this._compositeCache,this._cachedBoundsMinX,this._cachedBoundsMinY))}_rebuildCompositeCache(t){let i=0,e=0,s=0,n=0,h=!1;for(const o of t){const t=o,a=t.canvas.width*t.scale,r=t.canvas.height*t.scale,c="center"===t.anchor?-a/2:0,_="center"===t.anchor?-r/2:0,l=Math.cos(t.rotation),d=Math.sin(t.rotation),u=[{x:c,y:_},{x:c+a,y:_},{x:c,y:_+r},{x:c+a,y:_+r}];let g=1/0,v=1/0,p=-1/0,m=-1/0;for(const i of u){const e=i.x*l-i.y*d+t.x,s=i.x*d+i.y*l+t.y;g=Math.min(g,e),v=Math.min(v,s),p=Math.max(p,e),m=Math.max(m,s)}h?(i=Math.min(i,g),e=Math.min(e,v),s=Math.max(s,p),n=Math.max(n,m)):(i=g,e=v,s=p,n=m,h=!0)}if(!h)return void(this._compositeDirty=!1);const o=Math.ceil(s-i),a=Math.ceil(n-e);this._compositeCache||(this._compositeCache=document.createElement("canvas"),this._compositeCacheCtx=this._compositeCache.getContext("2d",{alpha:!0})),this._lastCacheWidth===o&&this._lastCacheHeight===a||(this._compositeCache.width=o,this._compositeCache.height=a,this._lastCacheWidth=o,this._lastCacheHeight=a),this._cachedBoundsMinX=i,this._cachedBoundsMinY=e;const r=this._compositeCacheCtx;r.clearRect(0,0,o,a),r.save(),r.translate(-i,-e);for(const i of t)!i.visible||i.opacity<=0||(r.save(),i.render(r),r.restore());r.restore(),this._compositeDirty=!1}destroy(){super.destroy(),this._compositeCache=null,this._compositeCacheCtx=null}}class u extends l{renderAllLayersIn(t){const i=t.topScreenContext;this._renderAllLayersIn(t,i)}}class g{constructor(t){this.name="interaction",this._view=null,this._dragging=!1,this._vx=0,this._vy=0,this._lastMoveTs=0,this._activePointerId=null,this._lastPointerX=0,this._lastPointerY=0,this._touchPointers=new Map,this._isTouchPanning=!1,this._isPinching=!1,this._lastPinchDistance=0,this._lastPinchCenterX=0,this._lastPinchCenterY=0,this._lastTouchX=0,this._lastTouchY=0,this._onDownBound=t=>this._onPointerDown(t),this._onMoveBound=t=>this._onPointerMove(t),this._onUpBound=t=>this._onPointerUp(t),this._onCancelBound=t=>this._onPointerCancel(t),this._onWheelBound=t=>this._onWheel(t),this._onUpdate=t=>{if(!this._view)return;const{friction:i,stopSpeed:e}=this._options,s=Math.hypot(this._vx,this._vy)>=e;if(!(this._dragging||this._isTouchPanning||this._isPinching)&&s){const s=this._vx*t,n=this._vy*t;this._view.panBy(s,n),this._vx*=i,this._vy*=i,Math.hypot(this._vx,this._vy)<e&&(this._vx=0,this._vy=0)}},this._options=Object.assign({panEnabled:!0,zoomEnabled:!0,friction:.92,stopSpeed:.02,emaAlpha:.25,idleNoInertiaMs:120,wheelSensitivity:.0015},t),this._panEnabled=this._options.panEnabled,this._zoomEnabled=this._options.zoomEnabled}install(t){this._view=t;const i=t.canvas;i.style.touchAction="none",i.addEventListener("wheel",this._onWheelBound,{passive:!1}),i.addEventListener("pointerdown",this._onDownBound),window.addEventListener("pointermove",this._onMoveBound),window.addEventListener("pointerup",this._onUpBound),window.addEventListener("pointercancel",this._onCancelBound),t.onUpdate(this._onUpdate)}destroy(){if(!this._view)return;const t=this._view.canvas;t.removeEventListener("wheel",this._onWheelBound),t.removeEventListener("pointerdown",this._onDownBound),window.removeEventListener("pointermove",this._onMoveBound),window.removeEventListener("pointerup",this._onUpBound),window.removeEventListener("pointercancel",this._onCancelBound),this._touchPointers.clear(),this._isPinching=!1,this._isTouchPanning=!1,this._view.offUpdate(this._onUpdate),this._view=null}isPanEnabled(){return this._panEnabled}isZoomEnabled(){return this._zoomEnabled}setPanEnabled(t){this._panEnabled!==t&&(this._panEnabled=t,t||null===this._activePointerId||(this._dragging=!1,this._vx=0,this._vy=0))}setZoomEnabled(t){this._zoomEnabled!==t&&(this._zoomEnabled=t,!t&&this._isPinching&&this._endPinch())}setWheelSensitivity(t){this._options.wheelSensitivity=t}isDragging(){return this._dragging||this._isTouchPanning||this._isPinching}_onPointerDown(t){var i,e;if(!(null===(i=this._view)||void 0===i?void 0:i.isAnimating))if("touch"!==t.pointerType){if(("mouse"!==t.pointerType||0===t.button)&&this._panEnabled&&null===this._activePointerId){t.preventDefault(),this._dragging=!0,this._vx=0,this._vy=0,this._lastMoveTs=performance.now(),this._activePointerId=t.pointerId,this._lastPointerX=t.clientX,this._lastPointerY=t.clientY;try{null===(e=this._view)||void 0===e||e.canvas.setPointerCapture(t.pointerId)}catch(t){}}}else this._onTouchDown(t)}_onPointerMove(t){var i;if(null===(i=this._view)||void 0===i?void 0:i.isAnimating)return;if("touch"===t.pointerType)return void this._onTouchMove(t);if(t.pointerId!==this._activePointerId)return;if(!this._dragging||!this._panEnabled||!this._view)return;const e=performance.now(),s=Math.max(1,e-(this._lastMoveTs||e-16));this._lastMoveTs=e;const n=t.clientX-this._lastPointerX,h=t.clientY-this._lastPointerY;this._lastPointerX=t.clientX,this._lastPointerY=t.clientY,this._view.panBy(n,h);const o=this._options.emaAlpha,a=n/s,r=h/s;this._vx=(1-o)*this._vx+o*a,this._vy=(1-o)*this._vy+o*r}_onPointerUp(t){if("touch"===t.pointerType)return void this._onTouchUp(t);if(t.pointerId!==this._activePointerId)return;if(!this._dragging)return;this._dragging=!1;const i=performance.now(),e=this._lastMoveTs?i-this._lastMoveTs:1/0;if(null!=this._activePointerId&&this._view){try{this._view.canvas.releasePointerCapture(this._activePointerId)}catch(t){}this._activePointerId=null}if(e>=this._options.idleNoInertiaMs)this._vx=0,this._vy=0;else{const t=Math.pow(this._options.friction,e/16);this._vx*=t,this._vy*=t}Math.hypot(this._vx,this._vy)<this._options.stopSpeed&&(this._vx=0,this._vy=0)}_onPointerCancel(t){"touch"!==t.pointerType?t.pointerId===this._activePointerId&&(this._dragging=!1,this._vx=0,this._vy=0,this._activePointerId=null):this._onTouchCancel(t)}_onTouchDown(t){if(t.preventDefault(),this._touchPointers.set(t.pointerId,{x:t.clientX,y:t.clientY}),2===this._touchPointers.size&&this._zoomEnabled)return this._isTouchPanning=!1,void this._startPinch();1===this._touchPointers.size&&(this._isTouchPanning=!0,this._vx=0,this._vy=0,this._lastMoveTs=performance.now(),this._lastTouchX=t.clientX,this._lastTouchY=t.clientY)}_onTouchMove(t){if(this._touchPointers.has(t.pointerId))if(this._touchPointers.set(t.pointerId,{x:t.clientX,y:t.clientY}),this._isPinching&&2===this._touchPointers.size)this._handlePinchMove();else if(this._isTouchPanning&&1===this._touchPointers.size&&this._view){const i=performance.now(),e=Math.max(1,i-(this._lastMoveTs||i-16));this._lastMoveTs=i;const s=t.clientX-this._lastTouchX,n=t.clientY-this._lastTouchY;this._lastTouchX=t.clientX,this._lastTouchY=t.clientY,this._view.panBy(s,n);const h=this._options.emaAlpha,o=s/e,a=n/e;this._vx=(1-h)*this._vx+h*o,this._vy=(1-h)*this._vy+h*a}}_onTouchUp(t){if(this._touchPointers.delete(t.pointerId),this._isPinching){if(this._endPinch(),1===this._touchPointers.size){const[[,t]]=this._touchPointers.entries();this._isTouchPanning=!0,this._lastTouchX=t.x,this._lastTouchY=t.y,this._vx=0,this._vy=0,this._lastMoveTs=performance.now()}}else if(this._isTouchPanning&&0===this._touchPointers.size){this._isTouchPanning=!1;const t=performance.now(),i=this._lastMoveTs?t-this._lastMoveTs:1/0;if(i>=this._options.idleNoInertiaMs)this._vx=0,this._vy=0;else{const t=Math.pow(this._options.friction,i/16);this._vx*=t,this._vy*=t}Math.hypot(this._vx,this._vy)<this._options.stopSpeed&&(this._vx=0,this._vy=0)}}_onTouchCancel(t){this._touchPointers.delete(t.pointerId),this._isPinching&&this._endPinch(),0===this._touchPointers.size&&(this._isTouchPanning=!1,this._vx=0,this._vy=0)}_startPinch(){this._isPinching=!0;const[t,i]=Array.from(this._touchPointers.values());this._lastPinchDistance=Math.hypot(i.x-t.x,i.y-t.y),this._lastPinchCenterX=(t.x+i.x)/2,this._lastPinchCenterY=(t.y+i.y)/2}_handlePinchMove(){if(!this._view||!this._zoomEnabled)return;const t=Array.from(this._touchPointers.values());if(2!==t.length)return;const[i,e]=t,s=Math.hypot(e.x-i.x,e.y-i.y),n=(i.x+e.x)/2,h=(i.y+e.y)/2;if(this._lastPinchDistance>0){const t=s/this._lastPinchDistance,i=this._view.canvas.getBoundingClientRect(),e=n-i.left,o=h-i.top;this._view.zoomByFactorAtScreen(e,o,t);const a=n-this._lastPinchCenterX,r=h-this._lastPinchCenterY;this._view.panBy(a,r)}this._lastPinchDistance=s,this._lastPinchCenterX=n,this._lastPinchCenterY=h}_endPinch(){this._isPinching=!1,this._lastPinchDistance=0,this._lastPinchCenterX=0,this._lastPinchCenterY=0}_getLineHeightPx(){if(!this._view)return 16;const t=getComputedStyle(this._view.canvas).lineHeight;if(!t||"normal"===t)return 16;const i=parseFloat(t);return Number.isFinite(i)?i:16}_normalizeWheelDelta(t){if(!this._view)return 0;let i=t.deltaY;if(1===t.deltaMode)i*=this._getLineHeightPx();else if(2===t.deltaMode){i*=this._view.canvas.clientHeight||window.innerHeight||800}return i}_onWheel(t){var i;if(null===(i=this._view)||void 0===i?void 0:i.isAnimating)return;if(!this._zoomEnabled||!this._view)return;t.preventDefault(),t.stopPropagation();const e=this._normalizeWheelDelta(t),s=this._view.canvas.getBoundingClientRect(),n=t.clientX-s.left,h=t.clientY-s.top;let o=-e*this._options.wheelSensitivity;t.ctrlKey||t.metaKey?o*=1.6:t.shiftKey&&(o*=.6),this._view.zoomByLogAtScreen(n,h,o)}}function v(t){return new g(t)}class p{constructor(t){var i,e,s,n,h;this.name="bounds",this._view=null,this._enabled=!1,this._x=0,this._y=0,this._width=0,this._height=0,this._marginL=0,this._marginR=0,this._marginT=0,this._marginB=0,this._panClampMode="minVisible",this._background=null,this._shadow=null,this._onUpdate=()=>{this._enabled&&this._view&&this._clampPan()},this._onBeforeRender=t=>{var i,e,s,n,h;this._enabled&&this._view&&(this._shadow?(t.save(),t.shadowColor=null!==(i=this._shadow.color)&&void 0!==i?i:p._defaultShadow.color,t.shadowBlur=null!==(e=this._shadow.blur)&&void 0!==e?e:p._defaultShadow.blur,t.shadowOffsetX=null!==(s=this._shadow.offsetX)&&void 0!==s?s:p._defaultShadow.offsetX,t.shadowOffsetY=null!==(n=this._shadow.offsetY)&&void 0!==n?n:p._defaultShadow.offsetY,t.fillStyle=null!==(h=this._background)&&void 0!==h?h:"#ffffff",t.fillRect(this._x,this._y,this._width,this._height),t.restore()):this._background&&(t.save(),t.fillStyle=this._background,t.fillRect(this._x,this._y,this._width,this._height),t.restore()),t.save(),t.beginPath(),t.rect(this._x,this._y,this._width,this._height),t.clip())},this._onAfterRender=t=>{if(this._enabled&&this._view&&(t.restore(),this._options.drawBorder)){const i=this._view.zoom;t.save(),t.lineWidth=1/i,t.strokeStyle="#cfcfcf",t.strokeRect(this._x,this._y,this._width,this._height),t.restore()}},this._options=Object.assign({rect:{x:0,y:0,width:0,height:0},margins:{},drawBorder:!1,minVisiblePx:30,panClampMode:"minVisible",background:null,shadow:!1},t),(null==t?void 0:t.rect)&&(this._enabled=!0,this._x=t.rect.x,this._y=t.rect.y,this._width=t.rect.width,this._height=t.rect.height),(null==t?void 0:t.margins)&&(this._marginL=null!==(i=t.margins.left)&&void 0!==i?i:0,this._marginR=null!==(e=t.margins.right)&&void 0!==e?e:0,this._marginT=null!==(s=t.margins.top)&&void 0!==s?s:0,this._marginB=null!==(n=t.margins.bottom)&&void 0!==n?n:0),this._panClampMode=this._options.panClampMode,this._background=null!==(h=this._options.background)&&void 0!==h?h:null,!0===this._options.shadow?this._shadow=Object.assign({},p._defaultShadow):this._options.shadow&&"object"==typeof this._options.shadow&&(this._shadow=Object.assign(Object.assign({},p._defaultShadow),this._options.shadow))}install(t){this._view=t,t.onUpdate(this._onUpdate),t.onBeforeRender(this._onBeforeRender),t.onAfterRender(this._onAfterRender)}destroy(){this._view&&(this._view.offUpdate(this._onUpdate),this._view.offBeforeRender(this._onBeforeRender),this._view.offAfterRender(this._onAfterRender),this._view=null)}isEnabled(){return this._enabled}getRect(){return{x:this._x,y:this._y,width:this._width,height:this._height}}setRect(t,i,e,s){this._enabled=!0,this._x=t,this._y=i,this._width=e,this._height=s}clearRect(){this._enabled=!1}setMargins(t){var i,e,s,n;this._marginL=null!==(i=t.left)&&void 0!==i?i:this._marginL,this._marginR=null!==(e=t.right)&&void 0!==e?e:this._marginR,this._marginT=null!==(s=t.top)&&void 0!==s?s:this._marginT,this._marginB=null!==(n=t.bottom)&&void 0!==n?n:this._marginB}getMargins(){return{left:this._marginL,right:this._marginR,top:this._marginT,bottom:this._marginB}}setPanClampMode(t){this._panClampMode=t}getPanClampMode(){return this._panClampMode}cropTo(t){this._doResize("crop",t)}resizeTo(t){this._doResize("resize",t)}zoomToFit(t){var i,e,s;const n=null!==(i=null==t?void 0:t.mode)&&void 0!==i?i:"contain",h=null===(e=null==t?void 0:t.animate)||void 0===e||e,o=null!==(s=null==t?void 0:t.maxScale)&&void 0!==s?s:1/0;if(!this._enabled||!this._view)return;const a=this._view.dpr,r=this._view.canvas.width/a,c=this._view.canvas.height/a,_=Math.max(1,r-(this._marginL+this._marginR)),l=Math.max(1,c-(this._marginT+this._marginB));let d;const u=_/this._width,g=l/this._height;d="contain"===n?Math.min(u,g):"cover"===n?Math.max(u,g):"fitWidth"===n?u:g,d=Math.min(d,o),d=Math.min(this._view.maxZoom,Math.max(this._view.minZoom,d));const v=this._marginL+(_-d*this._width)/2,p=this._marginT+(l-d*this._height)/2,m=v-d*this._x,y=p-d*this._y;h?this._view.setTransformSmooth(d,m,y):this._view.setTransform(d,m,y)}isPointInBounds(t,i){return!this._enabled||t>=this._x&&t<=this._x+this._width&&i>=this._y&&i<=this._y+this._height}get background(){return this._background}setBackground(t){var i;this._background=t,null===(i=this._view)||void 0===i||i.requestRender()}get shadow(){return this._shadow?Object.assign({},this._shadow):null}setShadow(t){var i;this._shadow=!0===t?Object.assign({},p._defaultShadow):t&&"object"==typeof t?Object.assign(Object.assign({},p._defaultShadow),t):null,null===(i=this._view)||void 0===i||i.requestRender()}_clampPan(){if(!this._view)return;const{zoom:t,tx:i,ty:e}=this._view.getTransform(),s=t,n=this._view.dpr,h=this._view.canvas.width/n,o=this._view.canvas.height/n,a=this._x,r=this._y,c=this._x+this._width,_=this._y+this._height;let l=i,d=e;if("margin"===this._panClampMode){const t=this._marginL-s*a,n=h-this._marginR-s*c,u=this._marginT-s*r,g=o-this._marginB-s*_,v=Math.max(1,h-(this._marginL+this._marginR)),p=Math.max(1,o-(this._marginT+this._marginB));l=s*this._width<=v?this._marginL+(v-s*this._width)/2-s*this._x:Math.min(t,Math.max(n,i)),d=s*this._height<=p?this._marginT+(p-s*this._height)/2-s*this._y:Math.min(u,Math.max(g,e))}else if("minVisible"===this._panClampMode){const t=s*this._width,n=s*this._height,u=Math.min(this._options.minVisiblePx,t),g=Math.min(this._options.minVisiblePx,n),v=h-u-s*a,p=u-s*c,m=o-g-s*r,y=g-s*_;l=p<=v?Math.min(v,Math.max(p,i)):(p+v)/2,d=y<=m?Math.min(m,Math.max(y,e)):(y+m)/2}l===i&&d===e||this._view.setPan(l,d)}_doResize(t,i){if(!this._view)return;const e=Math.max(1,Math.floor(i.width)),s=Math.max(1,Math.floor(i.height)),n={width:e,height:s},h=this._view.getLayerManagers();for(const i of h){const e=i.getAllLayers("world");for(const i of e){const e=i;"function"==typeof e.cropTo&&"function"==typeof e.resizeTo&&("crop"===t?e.cropTo(n):e.resizeTo(n))}}this._width=e,this._height=s,this._enabled&&this._clampPan()}}function m(t){return new p(t)}p._defaultShadow={color:"rgba(0, 0, 0, 0.3)",blur:20,offsetX:0,offsetY:4};class y{constructor(t,i,e,s){this.type="snapshot",this._isExecuted=!0,this._target=t,this._beforeData=i,this._afterData=e,this._region=null==s?void 0:s.region}execute(){if(this._isExecuted)return;const t=this._region?{x:this._region.x,y:this._region.y}:void 0;this._target.restoreSnapshot(this._afterData,t),this._isExecuted=!0}undo(){if(!this._isExecuted)return;const t=this._region?{x:this._region.x,y:this._region.y}:void 0;this._target.restoreSnapshot(this._beforeData,t),this._isExecuted=!1}canMerge(){return!1}merge(){return this}}function f(t,i,e,s){return i&&e?new y(t,i,e,s):null}class w{constructor(t){this.type="create-layer",this._layer=t.layer,this._layerManager=t.layerManager,this._insertIndex=t.insertIndex,this._previousSelectedId=t.previousSelectedId,this._getLayerList=t.getLayerList,this._setSelectedId=t.setSelectedId}execute(){this._layerManager.addLayer(this._layer,this._insertIndex);this._getLayerList().splice(this._insertIndex,0,this._layer),this._setSelectedId(this._layer.id)}undo(){this._layerManager.detachLayer(this._layer.id);const t=this._getLayerList(),i=t.findIndex(t=>t.id===this._layer.id);i>-1&&t.splice(i,1),this._setSelectedId(this._previousSelectedId)}}class x{constructor(t){this.type="delete-layer",this._layer=t.layer,this._layerManager=t.layerManager,this._originalIndex=t.originalIndex,this._previousSelectedId=t.previousSelectedId,this._newSelectedId=t.newSelectedId,this._getLayerList=t.getLayerList,this._setSelectedId=t.setSelectedId}execute(){this._layerManager.detachLayer(this._layer.id);const t=this._getLayerList(),i=t.findIndex(t=>t.id===this._layer.id);i>-1&&t.splice(i,1),this._setSelectedId(this._newSelectedId)}undo(){this._layerManager.addLayer(this._layer,this._originalIndex);this._getLayerList().splice(this._originalIndex,0,this._layer),this._setSelectedId(this._previousSelectedId)}}class M{executeCommand(t){t.execute(),this.addCommand(t)}addCommand(t){var i,e;this._redoStack.splice(0,this._redoStack.length);const s=this._undoStack[this._undoStack.length-1];if(s&&(null===(i=s.canMerge)||void 0===i?void 0:i.call(s,t))&&s.merge){const i=null!==(e=s.merge(t))&&void 0!==e?e:s;return void(i!==s&&(this._undoStack[this._undoStack.length-1]=i))}this._undoStack.push(t),this._undoStack.length>this._maxHistorySize&&this._undoStack.shift()}undo(){if(0===this._undoStack.length)return null;const t=this._undoStack.pop();return t.undo(),this._redoStack.push(t),t}redo(){if(0===this._redoStack.length)return null;const t=this._redoStack.pop();return t.execute(),this._undoStack.push(t),t}canUndo(){return this._undoStack.length>0}canRedo(){return this._redoStack.length>0}clear(){this._undoStack.splice(0,this._undoStack.length),this._redoStack.splice(0,this._redoStack.length)}setMaxHistorySize(t){if(this._maxHistorySize=Math.max(1,t),this._undoStack.length>this._maxHistorySize){const t=this._undoStack.length-this._maxHistorySize;this._undoStack.splice(0,t)}}constructor(t){var i,e,s;this._undoStack=[],this._redoStack=[],this._maxHistorySize=null!==(i=null==t?void 0:t.maxHistorySize)&&void 0!==i?i:50,this._undoStack=null!==(e=null==t?void 0:t.undoStack)&&void 0!==e?e:[],this._redoStack=null!==(s=null==t?void 0:t.redoStack)&&void 0!==s?s:[]}}export{_ as BitmapLayer,p as BoundsPlugin,r as CanvasLayer,d as ContentLayerManager,w as CreateLayerCommand,x as DeleteLayerCommand,M as HistoryManager,g as InteractionPlugin,a as LayerBase,l as LayerManagerBase,y as SnapshotCommand,u as TopScreenLayerManager,h as ViewManager,m as createBoundsPlugin,v as createInteractionPlugin,f as createSnapshotCommand};
@@ -10,6 +10,11 @@ declare class LayerManagerBase {
10
10
  * Render all layers in target view.
11
11
  */
12
12
  protected _renderAllLayersIn(view: ViewManager, context: CanvasRenderingContext2D): void;
13
+ /**
14
+ * Render all layers in target view.
15
+ * Subclasses may override this for custom rendering behavior (e.g., caching).
16
+ */
17
+ renderAllLayersIn(view: ViewManager): void;
13
18
  addLayer(layer: LayerBase, insertAt?: number): string;
14
19
  createImageLayer(option: ICreateBitmapLayerOptions): Promise<BitmapLayer>;
15
20
  /**
@@ -2,7 +2,7 @@ import type { ViewManager } from '../../core/view-manager';
2
2
  import type { ILayerResizeConfig } from '../../layer/layer.canvas';
3
3
  import type { Plugin } from '../types';
4
4
  type PanClampMode = 'margin' | 'minVisible';
5
- interface DocumentShadowOptions {
5
+ interface BoundsShadowOptions {
6
6
  /** Shadow color. Default 'rgba(0, 0, 0, 0.3)' */
7
7
  color?: string;
8
8
  /** Shadow blur radius. Default 20 */
@@ -12,7 +12,7 @@ interface DocumentShadowOptions {
12
12
  /** Shadow vertical offset. Default 4 */
13
13
  offsetY?: number;
14
14
  }
15
- interface DocumentPluginOptions {
15
+ interface BoundsPluginOptions {
16
16
  /**
17
17
  * Initial document rectangle (world coordinates).
18
18
  */
@@ -50,15 +50,15 @@ interface DocumentPluginOptions {
50
50
  /**
51
51
  * Shadow configuration. Set to true for default shadow, or provide custom options. Default false.
52
52
  */
53
- shadow?: DocumentShadowOptions | boolean;
53
+ shadow?: BoundsShadowOptions | boolean;
54
54
  }
55
55
  /**
56
- * Document Plugin
56
+ * Bounds Plugin
57
57
  *
58
58
  * Manages document bounds, margins, clipping, and pan clamping.
59
59
  */
60
- declare class DocumentPlugin implements Plugin {
61
- readonly name = "document";
60
+ declare class BoundsPlugin implements Plugin {
61
+ readonly name = "bounds";
62
62
  private _view;
63
63
  private _options;
64
64
  private _enabled;
@@ -74,7 +74,7 @@ declare class DocumentPlugin implements Plugin {
74
74
  private _background;
75
75
  private _shadow;
76
76
  private static readonly _defaultShadow;
77
- constructor(options?: DocumentPluginOptions);
77
+ constructor(options?: BoundsPluginOptions);
78
78
  install(view: ViewManager): void;
79
79
  destroy(): void;
80
80
  isEnabled(): boolean;
@@ -112,12 +112,17 @@ declare class DocumentPlugin implements Plugin {
112
112
  * Zoom to fit the document in the viewport.
113
113
  * @param mode Fit mode: 'contain', 'cover', 'fitWidth', 'fitHeight'
114
114
  * @param animate Whether to animate the transition. Default true.
115
+ * @param maxScale Maximum scale limit. Use 1 to prevent upscaling small documents. Default Infinity.
115
116
  */
116
- zoomToFit(mode?: 'contain' | 'cover' | 'fitWidth' | 'fitHeight', animate?: boolean): void;
117
+ zoomToFit(options?: {
118
+ mode?: 'contain' | 'cover' | 'fitWidth' | 'fitHeight';
119
+ animate?: boolean;
120
+ maxScale?: number;
121
+ }): void;
117
122
  /**
118
123
  * Check if a world point is inside the document.
119
124
  */
120
- isPointInDocument(wx: number, wy: number): boolean;
125
+ isPointInBounds(wx: number, wy: number): boolean;
121
126
  /**
122
127
  * Get the current background color.
123
128
  */
@@ -130,12 +135,12 @@ declare class DocumentPlugin implements Plugin {
130
135
  /**
131
136
  * Get the current shadow configuration.
132
137
  */
133
- get shadow(): DocumentShadowOptions | null;
138
+ get shadow(): BoundsShadowOptions | null;
134
139
  /**
135
140
  * Set the shadow configuration.
136
141
  * @param options Shadow options, true for default shadow, or false/null to disable.
137
142
  */
138
- setShadow(options: DocumentShadowOptions | boolean | null): void;
143
+ setShadow(options: BoundsShadowOptions | boolean | null): void;
139
144
  private _onUpdate;
140
145
  private _onBeforeRender;
141
146
  private _onAfterRender;
@@ -143,8 +148,8 @@ declare class DocumentPlugin implements Plugin {
143
148
  private _doResize;
144
149
  }
145
150
  /**
146
- * Create a document plugin instance.
151
+ * Create a Bounds Plugin instance.
147
152
  */
148
- declare function createDocumentPlugin(options?: DocumentPluginOptions): DocumentPlugin;
149
- export { DocumentPlugin, createDocumentPlugin };
150
- export type { DocumentPluginOptions, DocumentShadowOptions, PanClampMode };
153
+ declare function createBoundsPlugin(options?: BoundsPluginOptions): BoundsPlugin;
154
+ export { BoundsPlugin, createBoundsPlugin };
155
+ export type { BoundsPluginOptions, BoundsShadowOptions, PanClampMode };
@@ -1,4 +1,4 @@
1
1
  export * from './types';
2
2
  export * from './interaction';
3
- export * from './document';
3
+ export * from './bounds';
4
4
  export * from './history';
package/package.json CHANGED
@@ -1,33 +1,33 @@
1
- {
2
- "name": "@lancercomet/zoom-pan",
3
- "version": "0.2.1",
4
- "description": "Yet another web 2D rendering lib.",
5
- "main": "./dist/index.js",
6
- "module": "./dist/index.module.js",
7
- "files": [
8
- "dist/**/*",
9
- "README.md"
10
- ],
11
- "scripts": {
12
- "dev": "vite",
13
- "build:example": "vite build --mode example",
14
- "build:lib": "rollup -c"
15
- },
16
- "keywords": [],
17
- "author": "",
18
- "devDependencies": {
19
- "@lancercomet/eslint-config-eslint-rules": "^0.2.0",
20
- "@rollup/plugin-terser": "^0.4.4",
21
- "@vitejs/plugin-vue-jsx": "^5.1.2",
22
- "rollup": "^4.53.3",
23
- "rollup-plugin-commonjs": "^10.1.0",
24
- "rollup-plugin-delete": "^2.0.0",
25
- "rollup-plugin-typescript2": "^0.31.2",
26
- "stylus": "^0.64.0",
27
- "terser": "^5.44.1",
28
- "typescript": "^5.9.2",
29
- "vite": "^7.1.7",
30
- "vite-plugin-dts": "^3.9.1",
31
- "vue": "^3.5.22"
32
- }
33
- }
1
+ {
2
+ "name": "@lancercomet/zoom-pan",
3
+ "version": "0.3.0",
4
+ "description": "Yet another web 2D rendering lib.",
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.module.js",
7
+ "files": [
8
+ "dist/**/*",
9
+ "README.md"
10
+ ],
11
+ "scripts": {
12
+ "dev": "vite",
13
+ "build:example": "vite build --mode example",
14
+ "build:lib": "rollup -c"
15
+ },
16
+ "keywords": [],
17
+ "author": "",
18
+ "devDependencies": {
19
+ "@lancercomet/eslint-config-eslint-rules": "^0.2.0",
20
+ "@rollup/plugin-terser": "^0.4.4",
21
+ "@vitejs/plugin-vue-jsx": "^5.1.2",
22
+ "rollup": "^4.53.3",
23
+ "rollup-plugin-commonjs": "^10.1.0",
24
+ "rollup-plugin-delete": "^2.0.0",
25
+ "rollup-plugin-typescript2": "^0.31.2",
26
+ "stylus": "^0.64.0",
27
+ "terser": "^5.44.1",
28
+ "typescript": "^5.9.2",
29
+ "vite": "^7.1.7",
30
+ "vite-plugin-dts": "^3.9.1",
31
+ "vue": "^3.5.22"
32
+ }
33
+ }