@canvas-tile-engine/core 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,514 @@
1
+ /**
2
+ * Simple image loader with in-memory caching to avoid duplicate network requests.
3
+ */
4
+ declare class ImageLoader {
5
+ private cache;
6
+ private inflight;
7
+ private listeners;
8
+ /**
9
+ * Register a callback fired when a new image finishes loading.
10
+ */
11
+ onLoad(cb: () => void): () => boolean;
12
+ private notifyLoaded;
13
+ /**
14
+ * Load an image, reusing cache when possible.
15
+ * @param src Image URL.
16
+ * @param retry How many times to retry on error (default: 1).
17
+ * @returns Promise resolving to the loaded image element.
18
+ */
19
+ load(src: string, retry?: number): Promise<HTMLImageElement>;
20
+ /**
21
+ * Get a cached image without loading.
22
+ * @param src Image URL key.
23
+ */
24
+ get(src: string): HTMLImageElement | undefined;
25
+ /**
26
+ * Check if an image is already cached.
27
+ * @param src Image URL key.
28
+ */
29
+ has(src: string): boolean;
30
+ /**
31
+ * Clear all cached and inflight images/listeners to free memory.
32
+ */
33
+ clear(): void;
34
+ }
35
+
36
+ interface LayerHandle {
37
+ layer: number;
38
+ id: symbol;
39
+ }
40
+
41
+ type CanvasTileEngineConfig = {
42
+ renderer?: "canvas";
43
+ scale: number;
44
+ maxScale?: number;
45
+ minScale?: number;
46
+ backgroundColor?: string;
47
+ size: {
48
+ width: number;
49
+ height: number;
50
+ minWidth?: number;
51
+ minHeight?: number;
52
+ maxWidth?: number;
53
+ maxHeight?: number;
54
+ };
55
+ eventHandlers?: EventHandlers;
56
+ bounds?: {
57
+ minX: number;
58
+ maxX: number;
59
+ minY: number;
60
+ maxY: number;
61
+ };
62
+ coordinates?: {
63
+ enabled?: boolean;
64
+ shownScaleRange?: {
65
+ min: number;
66
+ max: number;
67
+ };
68
+ };
69
+ cursor?: {
70
+ default?: string;
71
+ move?: string;
72
+ };
73
+ debug?: {
74
+ enabled?: boolean;
75
+ hud?: {
76
+ enabled?: boolean;
77
+ topLeftCoordinates?: boolean;
78
+ coordinates?: boolean;
79
+ scale?: boolean;
80
+ tilesInView?: boolean;
81
+ fps?: boolean;
82
+ };
83
+ eventHandlers?: {
84
+ click?: boolean;
85
+ hover?: boolean;
86
+ drag?: boolean;
87
+ zoom?: boolean;
88
+ resize?: boolean;
89
+ };
90
+ };
91
+ };
92
+ type EventHandlers = {
93
+ click?: boolean;
94
+ hover?: boolean;
95
+ drag?: boolean;
96
+ zoom?: boolean;
97
+ resize?: boolean;
98
+ };
99
+ type Coords = {
100
+ x: number;
101
+ y: number;
102
+ };
103
+ type onDrawCallback = (ctx: CanvasRenderingContext2D, info: {
104
+ scale: number;
105
+ width: number;
106
+ height: number;
107
+ coords: Coords;
108
+ }) => void;
109
+ type onClickCallback = (coords: {
110
+ raw: Coords;
111
+ snapped: Coords;
112
+ }, mouse: {
113
+ raw: Coords;
114
+ snapped: Coords;
115
+ }, client: {
116
+ raw: Coords;
117
+ snapped: Coords;
118
+ }) => void;
119
+ type onHoverCallback = onClickCallback;
120
+ type DrawObject = {
121
+ x: number;
122
+ y: number;
123
+ size?: number;
124
+ origin?: {
125
+ mode?: "cell" | "self";
126
+ x?: number;
127
+ y?: number;
128
+ };
129
+ style?: {
130
+ fillStyle?: string;
131
+ strokeStyle?: string;
132
+ lineWidth?: number;
133
+ };
134
+ /** Rotation angle in degrees (0 = no rotation, positive = clockwise) */
135
+ rotate?: number;
136
+ /** Border radius in pixels. Single value for all corners, or array for [topLeft, topRight, bottomRight, bottomLeft] */
137
+ radius?: number | number[];
138
+ };
139
+ type Rect = DrawObject;
140
+ type Line = {
141
+ from: Coords;
142
+ to: Coords;
143
+ style: {
144
+ strokeStyle?: string;
145
+ lineWidth?: number;
146
+ };
147
+ };
148
+ type Circle = Omit<DrawObject, "rotate" | "radius">;
149
+ type Text = {
150
+ coords: Coords;
151
+ text: string;
152
+ };
153
+ type Path = Coords[];
154
+ type ImageItem = Omit<DrawObject, "style"> & {
155
+ img: HTMLImageElement;
156
+ };
157
+
158
+ /**
159
+ * Core engine wiring camera, config, renderer, events, and draw helpers.
160
+ */
161
+ declare class CanvasTileEngine {
162
+ private config;
163
+ private camera;
164
+ private viewport;
165
+ private coordinateTransformer;
166
+ private layers?;
167
+ private renderer;
168
+ private events;
169
+ private draw?;
170
+ images: ImageLoader;
171
+ private sizeController;
172
+ private animationController;
173
+ canvasWrapper: HTMLDivElement;
174
+ canvas: HTMLCanvasElement;
175
+ /** Callback: center coordinates change */
176
+ onCoordsChange?: (coords: Coords) => void;
177
+ private _onClick?;
178
+ get onClick(): onClickCallback | undefined;
179
+ set onClick(cb: onClickCallback | undefined);
180
+ private _onHover?;
181
+ get onHover(): onHoverCallback | undefined;
182
+ set onHover(cb: onHoverCallback | undefined);
183
+ private _onMouseDown?;
184
+ get onMouseDown(): (() => void) | undefined;
185
+ set onMouseDown(cb: (() => void) | undefined);
186
+ private _onMouseUp?;
187
+ get onMouseUp(): (() => void) | undefined;
188
+ set onMouseUp(cb: (() => void) | undefined);
189
+ private _onMouseLeave?;
190
+ get onMouseLeave(): (() => void) | undefined;
191
+ set onMouseLeave(cb: (() => void) | undefined);
192
+ private _onDraw?;
193
+ get onDraw(): onDrawCallback | undefined;
194
+ set onDraw(cb: onDrawCallback | undefined);
195
+ private _onResize?;
196
+ get onResize(): (() => void) | undefined;
197
+ set onResize(cb: (() => void) | undefined);
198
+ /**
199
+ * @param canvas Target canvas element.
200
+ * @param config Initial engine configuration.
201
+ * @param center Initial center in world space.
202
+ */
203
+ constructor(canvasWrapper: HTMLDivElement, config: CanvasTileEngineConfig, center?: Coords);
204
+ /** Tear down listeners and observers. */
205
+ destroy(): void;
206
+ /** Render a frame using the active renderer. */
207
+ render(): void;
208
+ /**
209
+ * Manually update canvas size (e.g., user-driven select). Keeps view centered.
210
+ * @param width New canvas width in pixels.
211
+ * @param height New canvas height in pixels.
212
+ * @param durationMs Animation duration in ms (default 500). Use 0 for instant resize.
213
+ * @param onComplete Optional callback fired when resize animation completes.
214
+ */
215
+ resize(width: number, height: number, durationMs?: number, onComplete?: () => void): void;
216
+ /**
217
+ * Current canvas size.
218
+ * @returns Current `{ width, height }` in pixels.
219
+ */
220
+ getSize(): {
221
+ width: number;
222
+ height: number;
223
+ };
224
+ /**
225
+ * Current canvas scale.
226
+ * @returns Current canvas scale.
227
+ */
228
+ getScale(): number;
229
+ /**
230
+ * Zoom in by a given factor, centered on the viewport.
231
+ * @param factor Zoom multiplier (default: 1.5). Higher values zoom in more.
232
+ */
233
+ zoomIn(factor?: number): void;
234
+ /**
235
+ * Zoom out by a given factor, centered on the viewport.
236
+ * @param factor Zoom multiplier (default: 1.5). Higher values zoom out more.
237
+ */
238
+ zoomOut(factor?: number): void;
239
+ /** Snapshot of current normalized config. */
240
+ getConfig(): Required<CanvasTileEngineConfig>;
241
+ /** Center coordinates of the map. */
242
+ getCenterCoords(): Coords;
243
+ /** Set center coordinates from outside (adjusts the camera accordingly). */
244
+ updateCoords(newCenter: Coords): void;
245
+ /**
246
+ * Smoothly move the camera center to target coordinates over the given duration.
247
+ * @param x Target world x.
248
+ * @param y Target world y.
249
+ * @param durationMs Animation duration in milliseconds (default: 500ms). Set to 0 for instant move.
250
+ * @param onComplete Optional callback fired when animation completes.
251
+ */
252
+ goCoords(x: number, y: number, durationMs?: number, onComplete?: () => void): void;
253
+ /**
254
+ * Update event handlers at runtime.
255
+ * This allows you to enable or disable specific interactions dynamically.
256
+ * @param handlers Partial event handlers to update.
257
+ * @example
258
+ * ```ts
259
+ * // Disable drag temporarily
260
+ * engine.setEventHandlers({ drag: false });
261
+ *
262
+ * // Enable painting mode
263
+ * engine.setEventHandlers({ drag: false, hover: true });
264
+ *
265
+ * // Re-enable drag
266
+ * engine.setEventHandlers({ drag: true });
267
+ * ```
268
+ */
269
+ setEventHandlers(handlers: Partial<EventHandlers>): void;
270
+ /**
271
+ * Set or update map boundaries to restrict camera movement.
272
+ * @param bounds Boundary limits. Use Infinity/-Infinity to remove limits.
273
+ * @example
274
+ * ```ts
275
+ * // Restrict map to -100 to 100 on both axes
276
+ * engine.setBounds({ minX: -100, maxX: 100, minY: -100, maxY: 100 });
277
+ *
278
+ * // Remove boundaries
279
+ * engine.setBounds({ minX: -Infinity, maxX: Infinity, minY: -Infinity, maxY: Infinity });
280
+ *
281
+ * // Only limit X axis
282
+ * engine.setBounds({ minX: 0, maxX: 500, minY: -Infinity, maxY: Infinity });
283
+ * ```
284
+ */
285
+ setBounds(bounds: {
286
+ minX: number;
287
+ maxX: number;
288
+ minY: number;
289
+ maxY: number;
290
+ }): void;
291
+ /**
292
+ * Register a generic draw callback (canvas renderer only).
293
+ * @param fn Callback invoked with context, top-left coords, and config.
294
+ * @param layer Layer order (lower draws first).
295
+ */
296
+ addDrawFunction(fn: (ctx: CanvasRenderingContext2D, coords: Coords, config: Required<CanvasTileEngineConfig>) => void, layer?: number): LayerHandle;
297
+ /**
298
+ * Draw one or many rectangles in world space (canvas renderer only).
299
+ * Supports rotation via the `rotate` property (degrees, positive = clockwise).
300
+ * @param items Rectangle definitions.
301
+ * @param layer Layer order (lower draws first).
302
+ */
303
+ drawRect(items: DrawObject | Array<DrawObject>, layer?: number): LayerHandle;
304
+ /**
305
+ * Draw rectangles with pre-rendering cache (canvas renderer only).
306
+ * Renders all items once to an offscreen canvas, then blits the visible portion each frame.
307
+ * Ideal for large static datasets like mini-maps where items don't change.
308
+ * Supports rotation via the `rotate` property (degrees, positive = clockwise).
309
+ * @param items Array of rectangle definitions.
310
+ * @param cacheKey Unique key for this cache (e.g., "minimap-items").
311
+ * @param layer Layer order (lower draws first).
312
+ */
313
+ drawStaticRect(items: Array<DrawObject>, cacheKey: string, layer?: number): LayerHandle;
314
+ /**
315
+ * Draw circles with pre-rendering cache (canvas renderer only).
316
+ * Renders all items once to an offscreen canvas, then blits the visible portion each frame.
317
+ * Ideal for large static datasets like mini-maps where items don't change.
318
+ * @param items Array of circle definitions.
319
+ * @param cacheKey Unique key for this cache (e.g., "minimap-circles").
320
+ * @param layer Layer order (lower draws first).
321
+ */
322
+ drawStaticCircle(items: Array<DrawObject>, cacheKey: string, layer?: number): LayerHandle;
323
+ /**
324
+ * Draw images with pre-rendering cache (canvas renderer only).
325
+ * Renders all items once to an offscreen canvas, then blits the visible portion each frame.
326
+ * Ideal for large static datasets like terrain tiles or static decorations.
327
+ * Supports rotation via the `rotate` property (degrees, positive = clockwise).
328
+ * @param items Array of image definitions with HTMLImageElement.
329
+ * @param cacheKey Unique key for this cache (e.g., "terrain-cache").
330
+ * @param layer Layer order (lower draws first).
331
+ */
332
+ drawStaticImage(items: Array<Omit<DrawObject, "style"> & {
333
+ img: HTMLImageElement;
334
+ }>, cacheKey: string, layer?: number): LayerHandle;
335
+ /**
336
+ * Clear a static rendering cache.
337
+ * @param cacheKey The cache key to clear, or undefined to clear all caches.
338
+ */
339
+ clearStaticCache(cacheKey?: string): void;
340
+ /**
341
+ * Draw one or many lines between world points (canvas renderer only).
342
+ * @param items Line segments.
343
+ * @param style Line style overrides.
344
+ * @param layer Layer order.
345
+ */
346
+ drawLine(items: Array<{
347
+ from: Coords;
348
+ to: Coords;
349
+ }> | {
350
+ from: Coords;
351
+ to: Coords;
352
+ }, style?: {
353
+ strokeStyle?: string;
354
+ lineWidth?: number;
355
+ }, layer?: number): LayerHandle;
356
+ /**
357
+ * Draw one or many circles sized in world units (canvas renderer only).
358
+ * @param items Circle definitions.
359
+ * @param layer Layer order.
360
+ */
361
+ drawCircle(items: DrawObject | Array<DrawObject>, layer?: number): LayerHandle;
362
+ /**
363
+ * Draw one or many texts at world positions (canvas renderer only).
364
+ * @param items Text definitions.
365
+ * @param style Text style overrides.
366
+ * @param layer Layer order.
367
+ */
368
+ drawText(items: Array<{
369
+ coords: Coords;
370
+ text: string;
371
+ }> | {
372
+ coords: Coords;
373
+ text: string;
374
+ }, style?: {
375
+ fillStyle?: string;
376
+ font?: string;
377
+ textAlign?: CanvasTextAlign;
378
+ textBaseline?: CanvasTextBaseline;
379
+ }, layer?: number): LayerHandle;
380
+ /**
381
+ * Draw one or many polylines through world points (canvas renderer only).
382
+ * @param items Polyline point collections.
383
+ * @param style Stroke style overrides.
384
+ * @param layer Layer order.
385
+ */
386
+ drawPath(items: Array<Coords[]> | Coords[], style?: {
387
+ strokeStyle?: string;
388
+ lineWidth?: number;
389
+ }, layer?: number): LayerHandle;
390
+ /**
391
+ * Draw one or many images scaled in world units (canvas renderer only).
392
+ * Supports rotation via the `rotate` property (degrees, positive = clockwise).
393
+ * @param items Image definitions.
394
+ * @param layer Layer order.
395
+ */
396
+ drawImage(items: Array<Omit<DrawObject, "style"> & {
397
+ img: HTMLImageElement;
398
+ }> | (Omit<DrawObject, "style"> & {
399
+ img: HTMLImageElement;
400
+ }), layer?: number): LayerHandle;
401
+ /**
402
+ * Draw grid lines at specified cell size (canvas renderer only).
403
+ * @param cellSize Size of each grid cell in world units.
404
+ * @example
405
+ * ```ts
406
+ * engine.drawGridLines(50);
407
+ * ```
408
+ */
409
+ drawGridLines(cellSize: number, lineWidth?: number, strokeStyle?: string, layer?: number): LayerHandle;
410
+ /**
411
+ * Remove a specific draw callback by handle (canvas renderer only).
412
+ * Does not clear other callbacks on the same layer.
413
+ */
414
+ removeLayerHandle(handle: LayerHandle): void;
415
+ /**
416
+ * Clear all draw callbacks from a specific layer (canvas renderer only).
417
+ * Use this before redrawing dynamic content to prevent accumulation.
418
+ * @param layer Layer index to clear.
419
+ * @example
420
+ * ```ts
421
+ * engine.clearLayer(1);
422
+ * engine.drawRect(newRects, 1);
423
+ * engine.render();
424
+ * ```
425
+ */
426
+ clearLayer(layer: number): void;
427
+ /**
428
+ * Clear all draw callbacks from all layers (canvas renderer only).
429
+ * Useful for complete scene reset.
430
+ * @example
431
+ * ```ts
432
+ * engine.clearAll();
433
+ * // Redraw everything from scratch
434
+ * ```
435
+ */
436
+ clearAll(): void;
437
+ /**
438
+ * Build the active renderer based on config.
439
+ * @param type Renderer type requested.
440
+ */
441
+ private createRenderer;
442
+ private ensureCanvasDraw;
443
+ private getCanvasRenderer;
444
+ private handleCameraChange;
445
+ }
446
+
447
+ /**
448
+ * Global constants for the canvas grid engine.
449
+ * Centralizes magic numbers and configuration values.
450
+ */
451
+ declare const DEFAULT_VALUES: {
452
+ /** Default animation duration in milliseconds */
453
+ readonly ANIMATION_DURATION_MS: 500;
454
+ /** Pixel offset for centering cells (0.5 = center of pixel) */
455
+ readonly CELL_CENTER_OFFSET: 0.5;
456
+ /** Default retry count for image loading */
457
+ readonly IMAGE_LOAD_RETRY_COUNT: 1;
458
+ /** Maximum wheel delta value for zoom (prevents extreme zooming) */
459
+ readonly MAX_WHEEL_DELTA: 100;
460
+ /** Minimum wheel delta value for zoom */
461
+ readonly MIN_WHEEL_DELTA: -100;
462
+ /** Zoom sensitivity factor */
463
+ readonly ZOOM_SENSITIVITY: 0.001;
464
+ };
465
+ declare const SCALE_LIMITS: {
466
+ /** Default minimum scale multiplier */
467
+ readonly MIN_SCALE_MULTIPLIER: 0.5;
468
+ /** Default maximum scale multiplier */
469
+ readonly MAX_SCALE_MULTIPLIER: 2;
470
+ };
471
+ declare const SIZE_LIMITS: {
472
+ /** Default minimum canvas width in pixels */
473
+ readonly MIN_WIDTH: 100;
474
+ /** Default minimum canvas height in pixels */
475
+ readonly MIN_HEIGHT: 100;
476
+ /** Default maximum width (infinity means no limit) */
477
+ readonly MAX_WIDTH: number;
478
+ /** Default maximum height (infinity means no limit) */
479
+ readonly MAX_HEIGHT: number;
480
+ };
481
+ declare const RENDER_DEFAULTS: {
482
+ /** Default background color */
483
+ readonly BACKGROUND_COLOR: "#ffffff";
484
+ /** Default renderer type */
485
+ readonly RENDERER_TYPE: "canvas";
486
+ };
487
+ declare const COORDINATE_OVERLAY: {
488
+ /** Coordinate overlay border width in pixels */
489
+ readonly BORDER_WIDTH: 20;
490
+ /** Coordinate text opacity */
491
+ readonly TEXT_OPACITY: 0.8;
492
+ /** Border overlay opacity */
493
+ readonly BORDER_OPACITY: 0.1;
494
+ /** Minimum font size for coordinate labels */
495
+ readonly MIN_FONT_SIZE: 8;
496
+ /** Maximum font size for coordinate labels */
497
+ readonly MAX_FONT_SIZE: 12;
498
+ /** Font size scale factor relative to camera scale */
499
+ readonly FONT_SIZE_SCALE_FACTOR: 0.25;
500
+ };
501
+ declare const DEBUG_HUD: {
502
+ /** Debug HUD panel width in pixels */
503
+ readonly PANEL_WIDTH: 160;
504
+ /** Debug HUD padding in pixels */
505
+ readonly PADDING: 8;
506
+ /** Debug HUD line height in pixels */
507
+ readonly LINE_HEIGHT: 16;
508
+ };
509
+ declare const VISIBILITY_BUFFER: {
510
+ /** Buffer zone for visibility culling (tiles) */
511
+ readonly TILE_BUFFER: 1;
512
+ };
513
+
514
+ export { COORDINATE_OVERLAY, CanvasTileEngine, type CanvasTileEngineConfig, type Circle, type Coords, DEBUG_HUD, DEFAULT_VALUES, type DrawObject, type EventHandlers, type ImageItem, type LayerHandle, type Line, type Path, RENDER_DEFAULTS, type Rect, SCALE_LIMITS, SIZE_LIMITS, type Text, VISIBILITY_BUFFER, type onClickCallback, type onDrawCallback, type onHoverCallback };
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";var he=Object.create;var A=Object.defineProperty;var le=Object.getOwnPropertyDescriptor;var ce=Object.getOwnPropertyNames;var de=Object.getPrototypeOf,me=Object.prototype.hasOwnProperty;var ue=(p,e)=>{for(var t in e)A(p,t,{get:e[t],enumerable:!0})},te=(p,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of ce(e))!me.call(p,i)&&i!==t&&A(p,i,{get:()=>e[i],enumerable:!(r=le(e,i))||r.enumerable});return p};var fe=(p,e,t)=>(t=p!=null?he(de(p)):{},te(e||!p||!p.__esModule?A(t,"default",{value:p,enumerable:!0}):t,p)),ve=p=>te(A({},"__esModule",{value:!0}),p);var ge={};ue(ge,{COORDINATE_OVERLAY:()=>x,CanvasTileEngine:()=>J,DEBUG_HUD:()=>T,DEFAULT_VALUES:()=>w,RENDER_DEFAULTS:()=>k,SCALE_LIMITS:()=>O,SIZE_LIMITS:()=>R,VISIBILITY_BUFFER:()=>S});module.exports=ve(ge);var w={ANIMATION_DURATION_MS:500,CELL_CENTER_OFFSET:.5,IMAGE_LOAD_RETRY_COUNT:1,MAX_WHEEL_DELTA:100,MIN_WHEEL_DELTA:-100,ZOOM_SENSITIVITY:.001},O={MIN_SCALE_MULTIPLIER:.5,MAX_SCALE_MULTIPLIER:2},R={MIN_WIDTH:100,MIN_HEIGHT:100,MAX_WIDTH:1/0,MAX_HEIGHT:1/0},k={BACKGROUND_COLOR:"#ffffff",RENDERER_TYPE:"canvas"},x={BORDER_WIDTH:20,TEXT_OPACITY:.8,BORDER_OPACITY:.1,MIN_FONT_SIZE:8,MAX_FONT_SIZE:12,FONT_SIZE_SCALE_FACTOR:.25},T={PANEL_WIDTH:160,PADDING:8,LINE_HEIGHT:16},S={TILE_BUFFER:1};function re(p,e,t,r){return{x:p.x-t/e,y:p.y-r/e}}function ie(p,e,t,r,i,n){let s=Math.min(Math.max(t,w.MIN_WHEEL_DELTA),w.MAX_WHEEL_DELTA),a=Math.exp(-s*w.ZOOM_SENSITIVITY),o=Math.min(i,Math.max(r,e*a));return o===e?{topLeft:p,scale:e}:{topLeft:{x:p.x+n.x*(1/e-1/o),y:p.y+n.y*(1/e-1/o)},scale:o}}function se(p,e){return{x:(p.x+w.CELL_CENTER_OFFSET-e.x)*e.scale,y:(p.y+w.CELL_CENTER_OFFSET-e.y)*e.scale}}function ne(p,e){return{x:e.x+p.x/e.scale,y:e.y+p.y/e.scale}}var D=class{_x;_y;_scale;minScale;maxScale;bounds;viewport;constructor(e,t=1,r=.1,i=10,n){this._x=e.x+w.CELL_CENTER_OFFSET,this._y=e.y+w.CELL_CENTER_OFFSET,this._scale=t,this.minScale=r,this.maxScale=i,this.viewport=n}setBounds(e){this.bounds=e,this.bounds&&this.clampToBounds()}clampToBounds(){if(!this.bounds||!this.viewport)return;let{width:e,height:t}=this.viewport.getSize(),r=e/this._scale,i=t/this._scale;this._x=this.clampAxis(this._x,r,this.bounds.minX,this.bounds.maxX),this._y=this.clampAxis(this._y,i,this.bounds.minY,this.bounds.maxY)}clampAxis(e,t,r,i){let n=i-r;return t>=n?r-(t-n)/2:e<r?r:e+t>i?i-t:e}get x(){return this._x}get y(){return this._y}get scale(){return this._scale}pan(e,t){let r=re({x:this._x,y:this._y},this._scale,e,t);this._x=r.x,this._y=r.y,this.clampToBounds()}zoom(e,t,r,i){let n=e-i.left,s=t-i.top,a=ie({x:this._x,y:this._y},this._scale,r,this.minScale,this.maxScale,{x:n,y:s});this._x=a.topLeft.x,this._y=a.topLeft.y,this._scale=a.scale,this.clampToBounds()}zoomByFactor(e,t,r){let i=Math.min(this.maxScale,Math.max(this.minScale,this._scale*e));i!==this._scale&&(this._x=this._x+t*(1/this._scale-1/i),this._y=this._y+r*(1/this._scale-1/i),this._scale=i,this.clampToBounds())}getCenter(e,t){return{x:this._x+e/(2*this._scale)-.5,y:this._y+t/(2*this._scale)-.5}}setCenter(e,t,r){this._x=e.x-t/(2*this._scale)+.5,this._y=e.y-r/(2*this._scale)+.5,this.clampToBounds()}adjustForResize(e,t){this._x-=e/(2*this._scale),this._y-=t/(2*this._scale),this.clampToBounds()}};var F=class{config;constructor(e){let t={renderer:k.RENDERER_TYPE,scale:e.scale,minScale:e.minScale??e.scale*O.MIN_SCALE_MULTIPLIER,maxScale:e.maxScale??e.scale*O.MAX_SCALE_MULTIPLIER,size:{width:e.size.width,height:e.size.height,maxHeight:e.size.maxHeight??R.MAX_HEIGHT,maxWidth:e.size.maxWidth??R.MAX_WIDTH,minHeight:e.size.minHeight??R.MIN_HEIGHT,minWidth:e.size.minWidth??R.MIN_WIDTH},backgroundColor:e.backgroundColor??k.BACKGROUND_COLOR,eventHandlers:{click:e.eventHandlers?.click??!1,hover:e.eventHandlers?.hover??!1,drag:e.eventHandlers?.drag??!1,zoom:e.eventHandlers?.zoom??!1,resize:e.eventHandlers?.resize??!1},bounds:e.bounds??{minX:-1/0,maxX:1/0,minY:-1/0,maxY:1/0},coordinates:{enabled:e.coordinates?.enabled??!1,shownScaleRange:e.coordinates?.shownScaleRange??{min:0,max:1/0}},cursor:{default:e.cursor?.default??"default",move:e.cursor?.move??"move"},debug:{enabled:e.debug?.enabled??!1,hud:{enabled:e.debug?.hud?.enabled??!1,topLeftCoordinates:e.debug?.hud?.topLeftCoordinates??!1,coordinates:e.debug?.hud?.coordinates??!1,scale:e.debug?.hud?.scale??!1,tilesInView:e.debug?.hud?.tilesInView??!1,fps:e.debug?.hud?.fps??!1},eventHandlers:{click:e.debug?.eventHandlers?.click??!0,hover:e.debug?.eventHandlers?.hover??!0,drag:e.debug?.eventHandlers?.drag??!0,zoom:e.debug?.eventHandlers?.zoom??!0,resize:e.debug?.eventHandlers?.resize??!0}}};this.config={...t,size:Object.freeze(t.size),eventHandlers:Object.freeze(t.eventHandlers),bounds:Object.freeze(t.bounds),coordinates:Object.freeze({...t.coordinates,shownScaleRange:Object.freeze(t.coordinates.shownScaleRange)}),cursor:Object.freeze(t.cursor),debug:Object.freeze({enabled:t.debug.enabled,hud:Object.freeze(t.debug.hud),eventHandlers:Object.freeze(t.debug.eventHandlers)})}}get(){let e=this.config;return{...e,size:{...e.size},eventHandlers:{...e.eventHandlers},bounds:{...e.bounds},coordinates:{...e.coordinates,shownScaleRange:{min:e.coordinates.shownScaleRange?.min??0,max:e.coordinates.shownScaleRange?.max??1/0}},cursor:{...e.cursor},debug:{...e.debug,hud:{...e.debug.hud},eventHandlers:{...e.debug.eventHandlers}}}}updateEventHandlers(e){this.config={...this.config,eventHandlers:Object.freeze({...this.config.eventHandlers,...e})}}updateBounds(e){this.config={...this.config,bounds:Object.freeze(e)}}};var W=class{constructor(e){this.camera=e}worldToScreen(e,t){return se({x:e,y:t},{x:this.camera.x,y:this.camera.y,scale:this.camera.scale})}screenToWorld(e,t){return ne({x:e,y:t},{x:this.camera.x,y:this.camera.y,scale:this.camera.scale})}};var ae=fe(require("rbush")),_=class p{tree;constructor(){this.tree=new ae.default}load(e){let t=e.map(r=>{let n=(typeof r.size=="number"?r.size:0)/2;return{minX:r.x-n,minY:r.y-n,maxX:r.x+n,maxY:r.y+n,item:r}});this.tree.load(t)}query(e,t,r,i){return this.tree.search({minX:e,minY:t,maxX:r,maxY:i}).map(s=>s.item)}clear(){this.tree.clear()}static fromArray(e){let t=new p;return t.load(e),t}};var ee=500,oe=16384,P=class{constructor(e,t,r){this.layers=e;this.transformer=t;this.camera=r;this.staticCacheSupported=typeof OffscreenCanvas<"u"||typeof document<"u"}staticCaches=new Map;staticCacheSupported;warnedStaticCacheDisabled=!1;isVisible(e,t,r,i,n){let s=n.size.width/n.scale,a=n.size.height/n.scale,o=i.x-S.TILE_BUFFER,l=i.y-S.TILE_BUFFER,c=i.x+s+S.TILE_BUFFER,h=i.y+a+S.TILE_BUFFER;return e+r>=o&&e-r<=c&&t+r>=l&&t-r<=h}getViewportBounds(e,t){let r=t.size.width/t.scale,i=t.size.height/t.scale;return{minX:e.x-S.TILE_BUFFER,minY:e.y-S.TILE_BUFFER,maxX:e.x+r+S.TILE_BUFFER,maxY:e.y+i+S.TILE_BUFFER}}addDrawFunction(e,t=1){return this.layers.add(t,({ctx:r,config:i,topLeft:n})=>{e(r,n,i)})}drawRect(e,t=1){let r=Array.isArray(e)?e:[e],n=r.length>ee?_.fromArray(r):null;return this.layers.add(t,({ctx:s,config:a,topLeft:o})=>{let l=this.getViewportBounds(o,a),c=n?n.query(l.minX,l.minY,l.maxX,l.maxY):r;s.save();let h,v,u;for(let d of c){let m=d.size??1,C={mode:d.origin?.mode==="self"?"self":"cell",x:d.origin?.x??.5,y:d.origin?.y??.5},f=d.style;if(!n&&!this.isVisible(d.x,d.y,m/2,o,a))continue;let y=this.transformer.worldToScreen(d.x,d.y),g=m*this.camera.scale,{x:b,y:E}=this.computeOriginOffset(y,g,C,this.camera);f?.fillStyle&&f.fillStyle!==h&&(s.fillStyle=f.fillStyle,h=f.fillStyle),f?.strokeStyle&&f.strokeStyle!==v&&(s.strokeStyle=f.strokeStyle,v=f.strokeStyle),f?.lineWidth&&f.lineWidth!==u&&(s.lineWidth=f.lineWidth,u=f.lineWidth);let I=d.rotate??0,z=I*(Math.PI/180),L=d.radius;if(I!==0){let K=b+g/2,Q=E+g/2;s.save(),s.translate(K,Q),s.rotate(z),s.beginPath(),L&&s.roundRect?s.roundRect(-g/2,-g/2,g,g,L):s.rect(-g/2,-g/2,g,g),f?.fillStyle&&s.fill(),f?.strokeStyle&&s.stroke(),s.restore()}else s.beginPath(),L&&s.roundRect?s.roundRect(b,E,g,g,L):s.rect(b,E,g,g),f?.fillStyle&&s.fill(),f?.strokeStyle&&s.stroke()}s.restore()})}drawLine(e,t,r=1){let i=Array.isArray(e)?e:[e];return this.layers.add(r,({ctx:n,config:s,topLeft:a})=>{n.save(),t?.strokeStyle&&(n.strokeStyle=t.strokeStyle),t?.lineWidth&&(n.lineWidth=t.lineWidth),n.beginPath();for(let o of i){let l=(o.from.x+o.to.x)/2,c=(o.from.y+o.to.y)/2,h=Math.max(Math.abs(o.from.x-o.to.x),Math.abs(o.from.y-o.to.y))/2;if(!this.isVisible(l,c,h,a,s))continue;let v=this.transformer.worldToScreen(o.from.x,o.from.y),u=this.transformer.worldToScreen(o.to.x,o.to.y);n.moveTo(v.x,v.y),n.lineTo(u.x,u.y)}n.stroke(),n.restore()})}drawCircle(e,t=1){let r=Array.isArray(e)?e:[e],n=r.length>ee?_.fromArray(r):null;return this.layers.add(t,({ctx:s,config:a,topLeft:o})=>{let l=this.getViewportBounds(o,a),c=n?n.query(l.minX,l.minY,l.maxX,l.maxY):r;s.save();let h,v,u;for(let d of c){let m=d.size??1,C={mode:d.origin?.mode==="self"?"self":"cell",x:d.origin?.x??.5,y:d.origin?.y??.5},f=d.style;if(!n&&!this.isVisible(d.x,d.y,m/2,o,a))continue;let y=this.transformer.worldToScreen(d.x,d.y),g=m*this.camera.scale,b=g/2,{x:E,y:I}=this.computeOriginOffset(y,g,C,this.camera);f?.fillStyle&&f.fillStyle!==h&&(s.fillStyle=f.fillStyle,h=f.fillStyle),f?.strokeStyle&&f.strokeStyle!==v&&(s.strokeStyle=f.strokeStyle,v=f.strokeStyle),f?.lineWidth&&f.lineWidth!==u&&(s.lineWidth=f.lineWidth,u=f.lineWidth),s.beginPath(),s.arc(E+b,I+b,b,0,Math.PI*2),f?.fillStyle&&s.fill(),f?.strokeStyle&&s.stroke()}s.restore()})}drawText(e,t,r=2){let i=Array.isArray(e)?e:[e];return this.layers.add(r,({ctx:n,config:s,topLeft:a})=>{n.save(),t?.font&&(n.font=t.font),t?.fillStyle&&(n.fillStyle=t.fillStyle),n.textAlign=t?.textAlign??"center",n.textBaseline=t?.textBaseline??"middle";for(let o of i){if(!this.isVisible(o.coords.x,o.coords.y,0,a,s))continue;let l=this.transformer.worldToScreen(o.coords.x,o.coords.y);n.fillText(o.text,l.x,l.y)}n.restore()})}drawPath(e,t,r=1){let i=Array.isArray(e[0])?e:[e];return this.layers.add(r,({ctx:n,config:s,topLeft:a})=>{n.save(),t?.strokeStyle&&(n.strokeStyle=t.strokeStyle),t?.lineWidth&&(n.lineWidth=t.lineWidth),n.beginPath();for(let o of i){if(!o.length)continue;let l=o.map(g=>g.x),c=o.map(g=>g.y),h=Math.min(...l),v=Math.max(...l),u=Math.min(...c),d=Math.max(...c),m=(h+v)/2,C=(u+d)/2,f=Math.max(v-h,d-u)/2;if(!this.isVisible(m,C,f,a,s))continue;let y=this.transformer.worldToScreen(o[0].x,o[0].y);n.moveTo(y.x,y.y);for(let g=1;g<o.length;g++){let b=this.transformer.worldToScreen(o[g].x,o[g].y);n.lineTo(b.x,b.y)}}n.stroke(),n.restore()})}drawImage(e,t=1){let r=Array.isArray(e)?e:[e],n=r.length>ee?_.fromArray(r):null;return this.layers.add(t,({ctx:s,config:a,topLeft:o})=>{let l=this.getViewportBounds(o,a),c=n?n.query(l.minX,l.minY,l.maxX,l.maxY):r;for(let h of c){let v=h.size??1,u={mode:h.origin?.mode==="self"?"self":"cell",x:h.origin?.x??.5,y:h.origin?.y??.5};if(!n&&!this.isVisible(h.x,h.y,v/2,o,a))continue;let d=this.transformer.worldToScreen(h.x,h.y),m=v*this.camera.scale,C=h.img.width/h.img.height,f=m,y=m;C>1?y=m/C:f=m*C;let{x:g,y:b}=this.computeOriginOffset(d,m,u,this.camera),E=g+(m-f)/2,I=b+(m-y)/2,z=h.rotate??0,L=z*(Math.PI/180);if(z!==0){let K=E+f/2,Q=I+y/2;s.save(),s.translate(K,Q),s.rotate(L),s.drawImage(h.img,-f/2,-y/2,f,y),s.restore()}else s.drawImage(h.img,E,I,f,y)}})}drawGridLines(e,t,r=0){return this.layers.add(r,({ctx:i,config:n,topLeft:s})=>{let a=n.size.width/n.scale,o=n.size.height/n.scale,l=Math.floor(s.x/e)*e-w.CELL_CENTER_OFFSET,c=Math.ceil((s.x+a)/e)*e-w.CELL_CENTER_OFFSET,h=Math.floor(s.y/e)*e-w.CELL_CENTER_OFFSET,v=Math.ceil((s.y+o)/e)*e-w.CELL_CENTER_OFFSET;i.save(),i.strokeStyle=t.strokeStyle,i.lineWidth=t.lineWidth,i.beginPath();for(let u=l;u<=c;u+=e){let d=this.transformer.worldToScreen(u,h),m=this.transformer.worldToScreen(u,v);i.moveTo(d.x,d.y),i.lineTo(m.x,m.y)}for(let u=h;u<=v;u+=e){let d=this.transformer.worldToScreen(l,u),m=this.transformer.worldToScreen(c,u);i.moveTo(d.x,d.y),i.lineTo(m.x,m.y)}i.stroke(),i.restore()})}computeOriginOffset(e,t,r,i){if(r.mode==="cell"){let n=i.scale;return{x:e.x-n/2+r.x*n-t/2,y:e.y-n/2+r.y*n-t/2}}return{x:e.x-r.x*t,y:e.y-r.y*t}}getOrCreateStaticCache(e,t,r){if(!this.staticCacheSupported)return this.warnedStaticCacheDisabled||(console.warn("[CanvasDraw] Static cache disabled: OffscreenCanvas not available."),this.warnedStaticCacheDisabled=!0),null;let i=1/0,n=-1/0,s=1/0,a=-1/0;for(let m of e){let C=m.size??1;m.x-C/2<i&&(i=m.x-C/2),m.x+C/2>n&&(n=m.x+C/2),m.y-C/2<s&&(s=m.y-C/2),m.y+C/2>a&&(a=m.y+C/2)}i-=1,s-=1,n+=1,a+=1;let o=n-i,l=a-s,c=this.camera.scale,h=Math.ceil(o*c),v=Math.ceil(l*c);if(h>oe||v>oe)return this.warnedStaticCacheDisabled||(console.warn(`Static cache disabled: offscreen canvas too large (${h}x${v}).`),this.warnedStaticCacheDisabled=!0),null;let u=this.staticCaches.get(t);if(!u||u.scale!==c||u.worldBounds.minX!==i||u.worldBounds.maxX!==n||u.worldBounds.minY!==s||u.worldBounds.maxY!==a){let m=typeof OffscreenCanvas<"u"?new OffscreenCanvas(h,v):document.createElement("canvas");typeof OffscreenCanvas<"u"&&m instanceof OffscreenCanvas||(m.width=h,m.height=v);let f=m.getContext("2d");if(!f)return this.warnedStaticCacheDisabled||(console.warn("[CanvasDraw] Static cache disabled: 2D context unavailable."),this.warnedStaticCacheDisabled=!0),null;for(let y of e){let b=(y.size??1)*c,E=(y.x+w.CELL_CENTER_OFFSET-i)*c-b/2,I=(y.y+w.CELL_CENTER_OFFSET-s)*c-b/2;r(f,y,E,I,b)}u={canvas:m,ctx:f,worldBounds:{minX:i,minY:s,maxX:n,maxY:a},scale:c},this.staticCaches.set(t,u)}return u||null}addStaticCacheLayer(e,t){if(!e)return null;let r=e.canvas,i=e.worldBounds,n=e.scale;return this.layers.add(t,({ctx:s,config:a,topLeft:o})=>{let l=a.size.width/a.scale,c=a.size.height/a.scale,h=(o.x-i.minX)*n,v=(o.y-i.minY)*n,u=l*n,d=c*n;s.drawImage(r,h,v,u,d,0,0,a.size.width,a.size.height)})}drawStaticRect(e,t,r=1){let i,n=this.getOrCreateStaticCache(e,t,(s,a,o,l,c)=>{let h=a.style,v=a.rotate??0,u=v*(Math.PI/180),d=a.radius;if(h?.fillStyle&&h.fillStyle!==i&&(s.fillStyle=h.fillStyle,i=h.fillStyle),v!==0){let m=o+c/2,C=l+c/2;s.save(),s.translate(m,C),s.rotate(u),d&&s.roundRect?(s.beginPath(),s.roundRect(-c/2,-c/2,c,c,d),s.fill()):s.fillRect(-c/2,-c/2,c,c),s.restore()}else d&&s.roundRect?(s.beginPath(),s.roundRect(o,l,c,c,d),s.fill()):s.fillRect(o,l,c,c)});return n?this.addStaticCacheLayer(n,r):this.drawRect(e,r)}drawStaticImage(e,t,r=1){let i=this.getOrCreateStaticCache(e,t,(n,s,a,o,l)=>{let c=s.img,h=s.rotate??0,v=h*(Math.PI/180),u=c.width/c.height,d=l,m=l;u>1?m=l/u:d=l*u;let C=a+(l-d)/2,f=o+(l-m)/2;if(h!==0){let y=C+d/2,g=f+m/2;n.save(),n.translate(y,g),n.rotate(v),n.drawImage(c,-d/2,-m/2,d,m),n.restore()}else n.drawImage(c,C,f,d,m)});return i?this.addStaticCacheLayer(i,r):this.drawImage(e,r)}drawStaticCircle(e,t,r=1){let i,n=this.getOrCreateStaticCache(e,t,(s,a,o,l,c)=>{let h=a.style,v=c/2;h?.fillStyle&&h.fillStyle!==i&&(s.fillStyle=h.fillStyle,i=h.fillStyle),s.beginPath(),s.arc(o+v,l+v,v,0,Math.PI*2),s.fill()});return n?this.addStaticCacheLayer(n,r):this.drawCircle(e,r)}clearStaticCache(e){e?this.staticCaches.delete(e):this.staticCaches.clear()}destroy(){this.staticCaches.clear(),this.layers.clear()}};var Y=class{constructor(e,t){this.canvas=e;this.handlers=t}attach(){this.handlers.click&&this.canvas.addEventListener("click",this.handlers.click),this.handlers.mousedown&&this.canvas.addEventListener("mousedown",this.handlers.mousedown),this.handlers.mousemove&&this.canvas.addEventListener("mousemove",this.handlers.mousemove),this.handlers.mouseup&&this.canvas.addEventListener("mouseup",this.handlers.mouseup),this.handlers.mouseleave&&this.canvas.addEventListener("mouseleave",this.handlers.mouseleave),this.handlers.wheel&&this.canvas.addEventListener("wheel",this.handlers.wheel,{passive:!1}),this.handlers.touchstart&&this.canvas.addEventListener("touchstart",this.handlers.touchstart,{passive:!1}),this.handlers.touchmove&&this.canvas.addEventListener("touchmove",this.handlers.touchmove,{passive:!1}),this.handlers.touchend&&this.canvas.addEventListener("touchend",this.handlers.touchend,{passive:!1})}detach(){this.handlers.click&&this.canvas.removeEventListener("click",this.handlers.click),this.handlers.mousedown&&this.canvas.removeEventListener("mousedown",this.handlers.mousedown),this.handlers.mousemove&&this.canvas.removeEventListener("mousemove",this.handlers.mousemove),this.handlers.mouseup&&this.canvas.removeEventListener("mouseup",this.handlers.mouseup),this.handlers.mouseleave&&this.canvas.removeEventListener("mouseleave",this.handlers.mouseleave),this.handlers.wheel&&this.canvas.removeEventListener("wheel",this.handlers.wheel),this.handlers.touchstart&&this.canvas.removeEventListener("touchstart",this.handlers.touchstart),this.handlers.touchmove&&this.canvas.removeEventListener("touchmove",this.handlers.touchmove),this.handlers.touchend&&this.canvas.removeEventListener("touchend",this.handlers.touchend)}};var X=class{constructor(e,t,r,i,n,s){this.canvas=e;this.camera=t;this.viewport=r;this.config=i;this.transformer=n;this.onCameraChange=s}isDragging=!1;shouldPreventClick=!1;lastPos={x:0,y:0};isPinching=!1;lastPinchDistance=0;lastPinchCenter={x:0,y:0};onClick;onHover;onMouseDown;onMouseUp;onMouseLeave;handleClick=e=>{if(this.shouldPreventClick){this.shouldPreventClick=!1;return}if(!this.config.get().eventHandlers.click||!this.onClick)return;let t=this.canvas.getBoundingClientRect(),r=e.clientX-t.left,i=e.clientY-t.top,n=this.transformer.screenToWorld(r,i),s=this.transformer.worldToScreen(Math.floor(n.x),Math.floor(n.y));this.onClick({raw:n,snapped:{x:Math.floor(n.x),y:Math.floor(n.y)}},{raw:{x:e.clientX-t.left,y:e.clientY-t.top},snapped:{x:s.x,y:s.y}},{raw:{x:e.clientX,y:e.clientY},snapped:{x:s.x+t.left,y:s.y+t.top}})};handleMouseDown=e=>{this.onMouseDown&&this.onMouseDown(),this.config.get().eventHandlers.drag&&(this.isDragging=!0,this.shouldPreventClick=!1,this.lastPos={x:e.clientX,y:e.clientY})};handleMouseMove=e=>{if(!this.isDragging){if(this.onHover&&this.config.get().eventHandlers.hover){let i=this.canvas.getBoundingClientRect(),n=e.clientX-i.left,s=e.clientY-i.top,a=this.transformer.screenToWorld(n,s),o=this.transformer.worldToScreen(Math.floor(a.x),Math.floor(a.y));this.onHover({raw:a,snapped:{x:Math.floor(a.x),y:Math.floor(a.y)}},{raw:{x:e.clientX-i.left,y:e.clientY-i.top},snapped:{x:o.x,y:o.y}},{raw:{x:e.clientX,y:e.clientY},snapped:{x:o.x+i.left,y:o.y+i.top}})}return}let t=e.clientX-this.lastPos.x,r=e.clientY-this.lastPos.y;(t!==0||r!==0)&&(this.canvas.style.cursor=this.config.get().cursor.move||"move",this.shouldPreventClick=!0),this.camera.pan(t,r),this.lastPos={x:e.clientX,y:e.clientY},this.onCameraChange()};handleMouseUp=()=>{this.onMouseUp&&this.onMouseUp(),this.isDragging=!1,this.canvas.style.cursor=this.config.get().cursor.default||"default"};handleMouseLeave=()=>{this.onMouseLeave&&this.onMouseLeave(),this.isDragging=!1,this.canvas.style.cursor=this.config.get().cursor.default||"default"};handleTouchStart=e=>{let t=this.config.get().eventHandlers;if(e.touches.length===2&&t.zoom){e.preventDefault(),this.isPinching=!0,this.isDragging=!1,this.lastPinchDistance=this.getTouchDistance(e.touches),this.lastPinchCenter=this.getTouchCenter(e.touches);return}if(!t.drag||e.touches.length!==1)return;let r=e.touches[0];this.isDragging=!0,this.isPinching=!1,this.shouldPreventClick=!1,this.lastPos={x:r.clientX,y:r.clientY}};handleTouchMove=e=>{if(this.isPinching&&e.touches.length===2){e.preventDefault();let n=this.getTouchDistance(e.touches),s=this.getTouchCenter(e.touches),a=this.canvas.getBoundingClientRect(),o=n/this.lastPinchDistance,l=s.x-a.left,c=s.y-a.top;this.camera.zoomByFactor(o,l,c);let h=s.x-this.lastPinchCenter.x,v=s.y-this.lastPinchCenter.y;(h!==0||v!==0)&&this.camera.pan(h,v),this.lastPinchDistance=n,this.lastPinchCenter=s,this.onCameraChange();return}if(!this.isDragging||e.touches.length!==1)return;e.preventDefault();let t=e.touches[0],r=t.clientX-this.lastPos.x,i=t.clientY-this.lastPos.y;(r!==0||i!==0)&&(this.canvas.style.cursor=this.config.get().cursor.move||"move",this.shouldPreventClick=!0),this.camera.pan(r,i),this.lastPos={x:t.clientX,y:t.clientY},this.onCameraChange()};handleTouchEnd=e=>{if(e.touches.length>=2&&this.isPinching){this.lastPinchDistance=this.getTouchDistance(e.touches),this.lastPinchCenter=this.getTouchCenter(e.touches);return}if(e.touches.length===1&&this.isPinching){if(this.isPinching=!1,this.config.get().eventHandlers.drag){this.isDragging=!0;let t=e.touches[0];this.lastPos={x:t.clientX,y:t.clientY}}return}this.isDragging=!1,this.isPinching=!1,this.canvas.style.cursor=this.config.get().cursor.default||"default"};getTouchDistance(e){let t=e[1].clientX-e[0].clientX,r=e[1].clientY-e[0].clientY;return Math.sqrt(t*t+r*r)}getTouchCenter(e){return{x:(e[0].clientX+e[1].clientX)/2,y:(e[0].clientY+e[1].clientY)/2}}handleWheel=e=>{if(!this.config.get().eventHandlers.zoom)return;e.preventDefault();let t=this.canvas.getBoundingClientRect();this.camera.zoom(e.clientX,e.clientY,e.deltaY,t),this.onCameraChange()}};var B=class{constructor(e,t,r,i,n,s){this.wrapper=e;this.canvas=t;this.viewport=r;this.camera=i;this.config=n;this.onCameraChange=s;this.currentDpr=this.viewport.dpr}resizeObserver;handleWindowResize;currentDpr;onResize;start(){this.viewport.updateDpr(),this.currentDpr=this.viewport.dpr;let e=this.viewport.getSize(),t=this.config.get().size,r=t?.maxWidth,i=t?.maxHeight,n=t?.minWidth,s=t?.minHeight;e.width=this.clamp(e.width,n,r),e.height=this.clamp(e.height,s,i),Object.assign(this.wrapper.style,{resize:"both",overflow:"hidden",width:`${e.width}px`,height:`${e.height}px`,touchAction:"none",position:"relative",maxWidth:r?`${r}px`:"",maxHeight:i?`${i}px`:"",minWidth:n?`${n}px`:"",minHeight:s?`${s}px`:""}),this.resizeObserver=new ResizeObserver(a=>{for(let o of a){let{width:l,height:c}=o.contentRect,h=this.clamp(l,n,r),v=this.clamp(c,s,i),u=this.viewport.getSize();if(h===u.width&&v===u.height)continue;let d=h-u.width,m=v-u.height,C=this.viewport.dpr;this.camera.adjustForResize(d,m),this.viewport.setSize(h,v),this.canvas.width=h*C,this.canvas.height=v*C,this.canvas.style.width=`${h}px`,this.canvas.style.height=`${v}px`,this.wrapper.style.width=`${h}px`,this.wrapper.style.height=`${v}px`,this.onResize&&this.onResize(),this.onCameraChange()}}),this.resizeObserver.observe(this.wrapper),this.attachDprWatcher()}stop(){this.resizeObserver&&(this.resizeObserver.unobserve(this.wrapper),this.resizeObserver.disconnect()),this.resizeObserver=void 0,this.handleWindowResize&&(window.removeEventListener("resize",this.handleWindowResize),this.handleWindowResize=void 0)}clamp(e,t,r){let i=e;return t!==void 0&&(i=Math.max(t,i)),r!==void 0&&(i=Math.min(r,i)),i}attachDprWatcher(){typeof window>"u"||(this.handleWindowResize=()=>{let e=this.currentDpr;this.viewport.updateDpr();let t=this.viewport.dpr;if(t===e)return;this.currentDpr=t;let{width:r,height:i}=this.viewport.getSize();this.canvas.width=r*t,this.canvas.height=i*t,this.canvas.style.width=`${r}px`,this.canvas.style.height=`${i}px`,this.onResize&&this.onResize(),this.onCameraChange()},window.addEventListener("resize",this.handleWindowResize,{passive:!0}))}};var N=class{constructor(e,t,r,i,n,s,a){this.canvasWrapper=e;this.canvas=t;this.camera=r;this.viewport=i;this.config=n;this.coordinateTransformer=s;this.onCameraChange=a;this.gestures=new X(this.canvas,this.camera,this.viewport,this.config,this.coordinateTransformer,this.onCameraChange),this.binder=new Y(this.canvas,{click:this.gestures.handleClick,mousedown:this.gestures.handleMouseDown,mousemove:this.gestures.handleMouseMove,mouseup:this.gestures.handleMouseUp,mouseleave:this.gestures.handleMouseLeave,wheel:this.gestures.handleWheel,touchstart:this.gestures.handleTouchStart,touchmove:this.gestures.handleTouchMove,touchend:this.gestures.handleTouchEnd})}binder;gestures;resizeWatcher;attached=!1;onResize;get onClick(){return this.gestures.onClick}set onClick(e){this.gestures.onClick=e}get onHover(){return this.gestures.onHover}set onHover(e){this.gestures.onHover=e}get onMouseDown(){return this.gestures.onMouseDown}set onMouseDown(e){this.gestures.onMouseDown=e}get onMouseUp(){return this.gestures.onMouseUp}set onMouseUp(e){this.gestures.onMouseUp=e}get onMouseLeave(){return this.gestures.onMouseLeave}set onMouseLeave(e){this.gestures.onMouseLeave=e}setupEvents(){this.attached||(this.binder.attach(),this.attached=!0,this.config.get().eventHandlers.resize&&this.camera instanceof D&&(this.resizeWatcher=new B(this.canvasWrapper,this.canvas,this.viewport,this.camera,this.config,this.onCameraChange),this.resizeWatcher.onResize=()=>{this.onResize&&this.onResize()},this.resizeWatcher.start()))}destroy(){this.attached&&(this.binder.detach(),this.resizeWatcher?.stop(),this.resizeWatcher=void 0,this.attached=!1)}};var U=class{cache=new Map;inflight=new Map;listeners=new Set;onLoad(e){return this.listeners.add(e),()=>this.listeners.delete(e)}notifyLoaded(){for(let e of this.listeners)e()}async load(e,t=w.IMAGE_LOAD_RETRY_COUNT){if(this.cache.has(e))return this.cache.get(e);if(this.inflight.has(e))return this.inflight.get(e);let r=new Promise((i,n)=>{let s=new Image;s.crossOrigin="anonymous",s.decoding="async",s.loading="eager",s.onload=async()=>{try{"decode"in s&&await s.decode?.()}catch{}this.cache.set(e,s),this.inflight.delete(e),this.notifyLoaded(),i(s)},s.onerror=a=>{if(this.inflight.delete(e),t>0)console.warn(`Retrying image: ${e}`),i(this.load(e,t-1));else{console.error(`Image failed to load: ${e}`,a);let o=a instanceof Error?a.message:typeof a=="string"?a:JSON.stringify(a);n(new Error(`Image failed to load: ${e}. Reason: ${o}`))}},s.src=e});return this.inflight.set(e,r),r}get(e){return this.cache.get(e)}has(e){return this.cache.has(e)}clear(){this.cache.clear(),this.inflight.clear(),this.listeners.clear()}};var V=class{layers=new Map;add(e,t){let r=Symbol("layer-callback"),i={id:r,fn:t};return this.layers.has(e)||this.layers.set(e,[]),this.layers.get(e).push(i),{layer:e,id:r}}remove(e){let t=this.layers.get(e.layer);t&&this.layers.set(e.layer,t.filter(r=>r.id!==e.id))}clear(e){if(e===void 0){this.layers.clear();return}this.layers.set(e,[])}drawAll(e){let t=[...this.layers.keys()].sort((r,i)=>r-i);for(let r of t){let i=this.layers.get(r);if(i)for(let{fn:n}of i)e.ctx.save(),n(e),e.ctx.restore()}}};var $=class{width;height;_dpr;constructor(e,t){this.width=e,this.height=t,this._dpr=typeof window<"u"&&window.devicePixelRatio||1}getSize(){return{width:this.width,height:this.height}}setSize(e,t){this.width=e,this.height=t}get dpr(){return this._dpr}updateDpr(){this._dpr=typeof window<"u"&&window.devicePixelRatio||1}};var j=class{ctx;camera;config;viewport;constructor(e,t,r,i){this.ctx=e,this.camera=t,this.config=r,this.viewport=i}draw(){this.ctx.save(),this.ctx.fillStyle=`rgba(0, 0, 0, ${x.BORDER_OPACITY})`;let{width:e,height:t}=this.viewport.getSize();this.ctx.fillRect(0,0,x.BORDER_WIDTH,t),this.ctx.fillRect(x.BORDER_WIDTH,t-x.BORDER_WIDTH,e,x.BORDER_WIDTH),this.ctx.fillStyle=`rgba(255, 255, 255, ${x.TEXT_OPACITY})`;let r=Math.min(x.MAX_FONT_SIZE,Math.max(x.MIN_FONT_SIZE,this.camera.scale*x.FONT_SIZE_SCALE_FACTOR));this.ctx.font=`${r}px Arial`,this.ctx.textAlign="center",this.ctx.textBaseline="middle";let i=this.camera.scale,n=e/i,s=t/i;for(let a=0-this.camera.y%1;a<=s+1;a++)this.ctx.fillText(Math.round(this.camera.y+a).toString(),10,i*a+i/2);for(let a=0-this.camera.x%1;a<=n+1;a++)this.ctx.fillText(Math.round(this.camera.x+a).toString(),i*a+i/2,t-10);this.ctx.restore()}shouldDraw(e){let t=this.config.get().coordinates;if(!t.enabled||!t.shownScaleRange)return!1;let{min:r,max:i}=t.shownScaleRange;return e>=r&&e<=i}};var pe=10,H=class{ctx;camera;transformer;config;viewport;frameTimes=[];lastFrameTime=0;currentFps=0;fpsLoopRunning=!1;onFpsUpdate=null;constructor(e,t,r,i,n){this.ctx=e,this.camera=t,this.transformer=r,this.config=i,this.viewport=n}setFpsUpdateCallback(e){this.onFpsUpdate=e}startFpsLoop(){this.fpsLoopRunning||(this.fpsLoopRunning=!0,this.lastFrameTime=performance.now(),this.fpsLoop())}stopFpsLoop(){this.fpsLoopRunning=!1}fpsLoop(){if(!this.fpsLoopRunning)return;let e=performance.now(),t=e-this.lastFrameTime;this.lastFrameTime=e,this.frameTimes.push(t),this.frameTimes.length>pe&&this.frameTimes.shift();let r=this.frameTimes.reduce((n,s)=>n+s,0)/this.frameTimes.length,i=Math.round(1e3/r);i!==this.currentFps&&(this.currentFps=i,this.onFpsUpdate?.()),requestAnimationFrame(()=>this.fpsLoop())}draw(){this.drawHud()}destroy(){this.stopFpsLoop(),this.onFpsUpdate=null}drawHud(){let e=this.config.get();if(!e.debug.hud||!e.debug.hud.enabled)return;let t=[],r={x:this.camera.x,y:this.camera.y};if(e.debug.hud.topLeftCoordinates&&t.push(`TopLeft: ${r.x.toFixed(2)}, ${r.y.toFixed(2)}`),e.debug.hud.coordinates){let{width:n,height:s}=this.viewport.getSize(),a=this.camera.getCenter(n,s);t.push(`Coords: ${a.x.toFixed(2)}, ${a.y.toFixed(2)}`)}if(e.debug.hud.scale&&t.push(`Scale: ${this.camera.scale.toFixed(2)}`),e.debug.hud.tilesInView){let{width:n,height:s}=this.viewport.getSize();t.push(`Tiles in view: ${Math.ceil(n/this.camera.scale)} x ${Math.ceil(s/this.camera.scale)}`)}e.debug.hud.fps&&t.push(`FPS: ${this.currentFps}`);let{width:i}=this.viewport.getSize();this.ctx.save(),this.ctx.fillStyle="rgba(0,0,0,0.5)",this.ctx.fillRect(i-T.PANEL_WIDTH-T.PADDING,T.PADDING/2,T.PANEL_WIDTH,t.length*T.LINE_HEIGHT+T.PADDING),this.ctx.fillStyle="#00ff99",this.ctx.font="12px monospace";for(let n=0;n<t.length;n++)this.ctx.fillText(t[n],i-T.PANEL_WIDTH-T.PADDING+5,18+n*T.LINE_HEIGHT);this.ctx.restore()}};var M=class{constructor(e,t,r,i,n,s){this.canvas=e;this.camera=t;this.coordinateTransformer=r;this.config=i;this.viewport=n;this.layers=s;let a=e.getContext("2d");if(!a)throw new Error("Failed to get 2D canvas context");this.ctx=a,this.applyCanvasSize(),this.coordinateOverlayRenderer=new j(this.ctx,this.camera,this.config,this.viewport),this.config.get().debug?.enabled&&(this.debugOverlay=new H(this.ctx,this.camera,this.coordinateTransformer,this.config,this.viewport),this.config.get().debug?.hud?.fps&&(this.debugOverlay.setFpsUpdateCallback(()=>this.render()),this.debugOverlay.startFpsLoop()))}ctx;coordinateOverlayRenderer;debugOverlay;onDraw;init(){this.applyCanvasSize()}applyCanvasSize(){let e=this.viewport.getSize(),t=this.viewport.dpr;this.canvas.width=e.width*t,this.canvas.height=e.height*t,this.canvas.style.width=`${e.width}px`,this.canvas.style.height=`${e.height}px`,this.ctx.setTransform(t,0,0,t,0,0)}render(){let e=this.viewport.getSize(),t=this.viewport.dpr,r={...this.config.get(),size:{...e},scale:this.camera.scale},i={x:this.camera.x,y:this.camera.y};this.ctx.setTransform(t,0,0,t,0,0),this.ctx.clearRect(0,0,r.size.width,r.size.height),this.ctx.fillStyle=r.backgroundColor,this.ctx.fillRect(0,0,r.size.width,r.size.height),this.layers.drawAll({ctx:this.ctx,camera:this.camera,transformer:this.coordinateTransformer,config:r,topLeft:i}),this.onDraw?.(this.ctx,{scale:this.camera.scale,width:r.size.width,height:r.size.height,coords:i}),this.coordinateOverlayRenderer.shouldDraw(this.camera.scale)&&this.coordinateOverlayRenderer.draw(),r.debug?.enabled&&(this.debugOverlay||(this.debugOverlay=new H(this.ctx,this.camera,this.coordinateTransformer,this.config,this.viewport),r.debug?.hud?.fps&&(this.debugOverlay.setFpsUpdateCallback(()=>this.render()),this.debugOverlay.startFpsLoop())),this.debugOverlay.draw())}resize(e,t){let r=this.viewport.dpr;this.viewport.setSize(e,t),this.canvas.width=e*r,this.canvas.height=t*r,this.canvas.style.width=`${e}px`,this.canvas.style.height=`${t}px`,this.ctx.setTransform(r,0,0,r,0,0)}destroy(){this.debugOverlay&&(this.debugOverlay.destroy(),this.debugOverlay=void 0),this.layers.clear()}getContext(){return this.ctx}};var G=class{canvasWrapper;canvas;camera;viewport;renderer;config;onSizeApplied;constructor(e,t,r,i,n,s,a){this.canvasWrapper=e,this.canvas=t,this.camera=r,this.renderer=i,this.viewport=n,this.config=s,this.onSizeApplied=a}resizeWithAnimation(e,t,r,i,n){if(e<=0||t<=0)return;let s=this.config.get().size,a=(o,l,c)=>{let h=o;return l!==void 0&&(h=Math.max(l,h)),c!==void 0&&(h=Math.min(c,h)),h};e=a(e,s?.minWidth,s?.maxWidth),t=a(t,s?.minHeight,s?.maxHeight),i.animateResize(e,t,r,(o,l,c)=>this.applySize(o,l,c),n)}applySize(e,t,r){let i=Math.round(e),n=Math.round(t),s=this.viewport.dpr;this.viewport.setSize(i,n),this.canvasWrapper.style.width=`${i}px`,this.canvasWrapper.style.height=`${n}px`,this.canvas.width=i*s,this.canvas.height=n*s,this.canvas.style.width=`${i}px`,this.canvas.style.height=`${n}px`,this.camera.setCenter(r,i,n),this.renderer.resize(i,n),this.onSizeApplied()}};var q=class{constructor(e,t,r){this.camera=e;this.viewport=t;this.onAnimationFrame=r}moveAnimationId;resizeAnimationId;animateMoveTo(e,t,r=w.ANIMATION_DURATION_MS,i){if(this.cancelMove(),r<=0){let l=this.viewport.getSize();this.camera.setCenter({x:e,y:t},l.width,l.height),this.onAnimationFrame(),i?.();return}let n=this.viewport.getSize(),s=this.camera.getCenter(n.width,n.height),a=performance.now(),o=l=>{let c=l-a,h=Math.min(1,c/r),v=h<.5?2*h*h:1-Math.pow(-2*h+2,2)/2,u=s.x+(e-s.x)*v,d=s.y+(t-s.y)*v,m=this.viewport.getSize();this.camera.setCenter({x:u,y:d},m.width,m.height),this.onAnimationFrame(),h<1?this.moveAnimationId=requestAnimationFrame(o):(this.moveAnimationId=void 0,i?.())};this.moveAnimationId=requestAnimationFrame(o)}animateResize(e,t,r=w.ANIMATION_DURATION_MS,i,n){if(e<=0||t<=0)return;this.cancelResize();let s=this.viewport.getSize(),a=this.camera.getCenter(s.width,s.height);if(r<=0){i(e,t,a),n?.();return}let o=s.width,l=s.height,c=e-s.width,h=t-s.height,v=performance.now(),u=d=>{let m=d-v,C=Math.min(1,m/r),f=o+c*C,y=l+h*C;i(f,y,a),C<1?this.resizeAnimationId=requestAnimationFrame(u):(this.resizeAnimationId=void 0,n?.())};this.resizeAnimationId=requestAnimationFrame(u)}cancelMove(){this.moveAnimationId!==void 0&&(cancelAnimationFrame(this.moveAnimationId),this.moveAnimationId=void 0)}cancelResize(){this.resizeAnimationId!==void 0&&(cancelAnimationFrame(this.resizeAnimationId),this.resizeAnimationId=void 0)}cancelAll(){this.cancelMove(),this.cancelResize()}isAnimating(){return this.moveAnimationId!==void 0||this.resizeAnimationId!==void 0}};var Z=class{static createRenderer(e,t,r,i,n,s,a){switch(e){case"canvas":return new M(t,r,i,n,s,a);default:throw new Error(`Unsupported renderer type: ${e}`)}}static isSupported(e){return e==="canvas"}static getSupportedTypes(){return["canvas"]}};var J=class{config;camera;viewport;coordinateTransformer;layers;renderer;events;draw;images;sizeController;animationController;canvasWrapper;canvas;onCoordsChange;_onClick;get onClick(){return this._onClick}set onClick(e){this._onClick=e,this.events.onClick=e}_onHover;get onHover(){return this._onHover}set onHover(e){this._onHover=e,this.events.onHover=e}_onMouseDown;get onMouseDown(){return this._onMouseDown}set onMouseDown(e){this._onMouseDown=e,this.events.onMouseDown=e}_onMouseUp;get onMouseUp(){return this._onMouseUp}set onMouseUp(e){this._onMouseUp=e,this.events.onMouseUp=e}_onMouseLeave;get onMouseLeave(){return this._onMouseLeave}set onMouseLeave(e){this._onMouseLeave=e,this.events.onMouseLeave=e}_onDraw;get onDraw(){return this._onDraw}set onDraw(e){this._onDraw=e,this.getCanvasRenderer().onDraw=e}_onResize;get onResize(){return this._onResize}set onResize(e){this._onResize=e,this.events.onResize=e}constructor(e,t,r={x:0,y:0}){this.canvasWrapper=e,this.canvas=e.querySelector("canvas"),this.canvasWrapper.style.position="relative",this.canvasWrapper.style.width=t.size.width+"px",this.canvasWrapper.style.height=t.size.height+"px",this.canvas.style.position="absolute",this.config=new F(t);let i=t.renderer??"canvas",n={x:r.x-t.size.width/(2*t.scale),y:r.y-t.size.height/(2*t.scale)};this.viewport=new $(t.size.width,t.size.height),this.camera=new D(n,this.config.get().scale,this.config.get().minScale,this.config.get().maxScale,this.viewport),this.coordinateTransformer=new W(this.camera),this.animationController=new q(this.camera,this.viewport,()=>this.handleCameraChange()),this.renderer=this.createRenderer(i),this.images=new U,this.events=new N(this.canvasWrapper,this.canvas,this.camera,this.viewport,this.config,this.coordinateTransformer,()=>this.handleCameraChange()),this.sizeController=new G(this.canvasWrapper,this.canvas,this.camera,this.renderer,this.viewport,this.config,()=>this.handleCameraChange()),this.events.setupEvents(),t.bounds&&this.camera.setBounds(t.bounds)}destroy(){this.events.destroy(),this.animationController.cancelAll(),this.draw?.destroy(),this.layers?.clear(),this.images.clear(),this.renderer.destroy()}render(){this.renderer.render()}resize(e,t,r=500,i){this.sizeController.resizeWithAnimation(e,t,r,this.animationController,()=>{this._onResize?.(),i?.()})}getSize(){return this.viewport.getSize()}getScale(){return this.camera.scale}zoomIn(e=1.5){let t=this.viewport.getSize();this.camera.zoomByFactor(e,t.width/2,t.height/2),this.handleCameraChange()}zoomOut(e=1.5){let t=this.viewport.getSize();this.camera.zoomByFactor(1/e,t.width/2,t.height/2),this.handleCameraChange()}getConfig(){let e=this.config.get(),t=this.viewport.getSize();return{...e,scale:this.camera.scale,size:{...t}}}getCenterCoords(){let e=this.viewport.getSize();return this.camera.getCenter(e.width,e.height)}updateCoords(e){let t=this.viewport.getSize();this.camera.setCenter(e,t.width,t.height),this.handleCameraChange()}goCoords(e,t,r=500,i){this.animationController.animateMoveTo(e,t,r,i)}setEventHandlers(e){this.config.updateEventHandlers(e)}setBounds(e){this.config.updateBounds(e),this.camera.setBounds(e),this.render()}addDrawFunction(e,t=1){return this.ensureCanvasDraw().addDrawFunction(e,t)}drawRect(e,t=1){return this.ensureCanvasDraw().drawRect(e,t)}drawStaticRect(e,t,r=1){return this.ensureCanvasDraw().drawStaticRect(e,t,r)}drawStaticCircle(e,t,r=1){return this.ensureCanvasDraw().drawStaticCircle(e,t,r)}drawStaticImage(e,t,r=1){return this.ensureCanvasDraw().drawStaticImage(e,t,r)}clearStaticCache(e){this.ensureCanvasDraw().clearStaticCache(e)}drawLine(e,t,r=1){return this.ensureCanvasDraw().drawLine(e,t,r)}drawCircle(e,t=1){return this.ensureCanvasDraw().drawCircle(e,t)}drawText(e,t,r=2){return this.ensureCanvasDraw().drawText(e,t,r)}drawPath(e,t,r=1){return this.ensureCanvasDraw().drawPath(e,t,r)}drawImage(e,t=1){return this.ensureCanvasDraw().drawImage(e,t)}drawGridLines(e,t=1,r="black",i=0){return this.ensureCanvasDraw().drawGridLines(e,{lineWidth:t,strokeStyle:r},i)}removeLayerHandle(e){if(!this.layers)throw new Error("removeLayerHandle is only available when renderer is set to 'canvas'.");this.layers.remove(e)}clearLayer(e){if(!this.layers)throw new Error("clearLayer is only available when renderer is set to 'canvas'.");this.layers.clear(e)}clearAll(){if(!this.layers)throw new Error("clearAll is only available when renderer is set to 'canvas'.");this.layers.clear()}createRenderer(e){return e==="canvas"&&(this.layers=new V,this.draw=new P(this.layers,this.coordinateTransformer,this.camera)),Z.createRenderer(e??"canvas",this.canvas,this.camera,this.coordinateTransformer,this.config,this.viewport,this.layers)}ensureCanvasDraw(){if(!this.draw)throw new Error("Draw helpers are only available when renderer is set to 'canvas'.");return this.draw}getCanvasRenderer(){if(!(this.renderer instanceof M))throw new Error("Canvas renderer required for this operation.");return this.renderer}handleCameraChange(){this.onCoordsChange&&this.onCoordsChange(this.getCenterCoords()),this.render()}};0&&(module.exports={COORDINATE_OVERLAY,CanvasTileEngine,DEBUG_HUD,DEFAULT_VALUES,RENDER_DEFAULTS,SCALE_LIMITS,SIZE_LIMITS,VISIBILITY_BUFFER});
2
+ //# sourceMappingURL=index.js.map