@markup-canvas/core 1.1.7 → 1.2.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.
Files changed (161) hide show
  1. package/dist/index.d.ts +1 -1
  2. package/dist/lib/MarkupCanvas.d.ts +9 -12
  3. package/dist/lib/actions/config/getConfig.d.ts +2 -0
  4. package/dist/lib/actions/index.d.ts +3 -0
  5. package/dist/lib/actions/pan/centerContent.d.ts +2 -0
  6. package/dist/lib/actions/pan/index.d.ts +6 -0
  7. package/dist/lib/actions/pan/panDown.d.ts +2 -0
  8. package/dist/lib/actions/pan/panLeft.d.ts +2 -0
  9. package/dist/lib/actions/pan/panRight.d.ts +2 -0
  10. package/dist/lib/actions/pan/panUp.d.ts +2 -0
  11. package/dist/lib/actions/pan/scrollToPoint.d.ts +2 -0
  12. package/dist/lib/actions/transform/index.d.ts +2 -0
  13. package/dist/lib/actions/transform/resetTransform.d.ts +2 -0
  14. package/dist/lib/actions/transform/updateTransform.d.ts +2 -0
  15. package/dist/lib/actions/ui/grid/hideGrid.d.ts +2 -0
  16. package/dist/lib/actions/ui/grid/index.d.ts +4 -0
  17. package/dist/lib/actions/ui/grid/isGridVisible.d.ts +2 -0
  18. package/dist/lib/actions/ui/grid/showGrid.d.ts +2 -0
  19. package/dist/lib/actions/ui/grid/toggleGrid.d.ts +2 -0
  20. package/dist/lib/actions/ui/index.d.ts +4 -0
  21. package/dist/lib/actions/ui/rulers/areRulersVisible.d.ts +2 -0
  22. package/dist/lib/actions/ui/rulers/hideRulers.d.ts +2 -0
  23. package/dist/lib/actions/ui/rulers/index.d.ts +4 -0
  24. package/dist/lib/actions/ui/rulers/showRulers.d.ts +2 -0
  25. package/dist/lib/actions/ui/rulers/toggleRulers.d.ts +2 -0
  26. package/dist/lib/actions/ui/toggleTransition.d.ts +1 -0
  27. package/dist/lib/actions/ui/updateThemeMode.d.ts +2 -0
  28. package/dist/lib/actions/zoom/index.d.ts +6 -0
  29. package/dist/lib/actions/zoom/resetView.d.ts +2 -0
  30. package/dist/lib/actions/zoom/resetViewToCenter.d.ts +3 -0
  31. package/dist/lib/actions/zoom/setZoom.d.ts +3 -0
  32. package/dist/lib/actions/zoom/zoomIn.d.ts +3 -0
  33. package/dist/lib/actions/zoom/zoomOut.d.ts +3 -0
  34. package/dist/lib/actions/zoom/zoomToPoint.d.ts +2 -0
  35. package/dist/lib/canvas/createCanvas.d.ts +2 -2
  36. package/dist/lib/canvas/fitToScreen.d.ts +2 -0
  37. package/dist/lib/canvas/getCanvasBounds.d.ts +2 -2
  38. package/dist/lib/canvas/index.d.ts +1 -1
  39. package/dist/lib/events/emitTransformEvents.d.ts +3 -0
  40. package/dist/lib/events/keyboard/handleKeyDown.d.ts +3 -2
  41. package/dist/lib/events/keyboard/handleKeyUp.d.ts +3 -2
  42. package/dist/lib/events/keyboard/setupKeyboardEvents.d.ts +3 -2
  43. package/dist/lib/events/mouse/createMouseDragControls.d.ts +7 -0
  44. package/dist/lib/events/mouse/handleClickToZoom.d.ts +3 -2
  45. package/dist/lib/events/mouse/handleMouseDown.d.ts +3 -2
  46. package/dist/lib/events/mouse/handleMouseLeave.d.ts +3 -2
  47. package/dist/lib/events/mouse/handleMouseMove.d.ts +3 -2
  48. package/dist/lib/events/mouse/handleMouseUp.d.ts +3 -2
  49. package/dist/lib/events/mouse/setupMouseDrag.d.ts +4 -3
  50. package/dist/lib/events/mouse/setupMouseEvents.d.ts +4 -3
  51. package/dist/lib/events/touch/handleTouchMove.d.ts +3 -2
  52. package/dist/lib/events/touch/setupTouchEvents.d.ts +2 -2
  53. package/dist/lib/events/trackpad/createTrackpadPanHandler.d.ts +2 -2
  54. package/dist/lib/events/utils/getAdaptiveZoomSpeed.d.ts +2 -2
  55. package/dist/lib/events/utils/getViewportCenter.d.ts +2 -2
  56. package/dist/lib/events/utils/resetDragState.d.ts +3 -2
  57. package/dist/lib/events/utils/updateCursor.d.ts +3 -2
  58. package/dist/lib/events/wheel/handleWheel.d.ts +3 -2
  59. package/dist/lib/events/wheel/setupWheelEvents.d.ts +3 -2
  60. package/dist/lib/events/wheel/setupWheelHandler.d.ts +3 -2
  61. package/dist/lib/helpers/getVisibleArea.d.ts +7 -0
  62. package/dist/lib/helpers/index.d.ts +2 -0
  63. package/dist/lib/helpers/isPointVisible.d.ts +2 -0
  64. package/dist/lib/transform/applyZoomToCanvas.d.ts +2 -2
  65. package/dist/lib/window/bindCanvasToWindow.d.ts +3 -0
  66. package/dist/lib/window/broadcastEvent.d.ts +2 -0
  67. package/dist/lib/window/cleanupWindowBinding.d.ts +2 -0
  68. package/dist/lib/window/index.d.ts +3 -0
  69. package/dist/markup-canvas.cjs.js +686 -530
  70. package/dist/markup-canvas.esm.js +686 -530
  71. package/dist/markup-canvas.umd.js +684 -525
  72. package/dist/markup-canvas.umd.min.js +1 -1
  73. package/dist/types/canvas.d.ts +1 -48
  74. package/dist/types/config.d.ts +0 -3
  75. package/dist/types/events.d.ts +4 -1
  76. package/dist/types/index.d.ts +3 -2
  77. package/dist/types/window.d.ts +84 -0
  78. package/package.json +1 -1
  79. package/src/index.ts +1 -1
  80. package/src/lib/MarkupCanvas.ts +136 -316
  81. package/src/lib/actions/config/getConfig.ts +5 -0
  82. package/src/lib/actions/index.ts +6 -0
  83. package/src/lib/actions/pan/centerContent.ts +21 -0
  84. package/src/lib/actions/pan/index.ts +6 -0
  85. package/src/lib/actions/pan/panDown.ts +13 -0
  86. package/src/lib/actions/pan/panLeft.ts +13 -0
  87. package/src/lib/actions/pan/panRight.ts +13 -0
  88. package/src/lib/actions/pan/panUp.ts +13 -0
  89. package/src/lib/actions/pan/scrollToPoint.ts +27 -0
  90. package/src/lib/actions/transform/index.ts +2 -0
  91. package/src/lib/actions/transform/resetTransform.ts +11 -0
  92. package/src/lib/actions/transform/updateTransform.ts +9 -0
  93. package/src/lib/actions/ui/grid/hideGrid.ts +9 -0
  94. package/src/lib/actions/ui/grid/index.ts +4 -0
  95. package/src/lib/actions/ui/grid/isGridVisible.ts +8 -0
  96. package/src/lib/actions/ui/grid/showGrid.ts +9 -0
  97. package/src/lib/actions/ui/grid/toggleGrid.ts +9 -0
  98. package/src/lib/actions/ui/index.ts +4 -0
  99. package/src/lib/actions/ui/rulers/areRulersVisible.ts +8 -0
  100. package/src/lib/actions/ui/rulers/hideRulers.ts +9 -0
  101. package/src/lib/actions/ui/rulers/index.ts +4 -0
  102. package/src/lib/actions/ui/rulers/showRulers.ts +9 -0
  103. package/src/lib/actions/ui/rulers/toggleRulers.ts +14 -0
  104. package/src/lib/actions/ui/toggleTransition.ts +3 -0
  105. package/src/lib/actions/ui/updateThemeMode.ts +25 -0
  106. package/src/lib/actions/zoom/index.ts +6 -0
  107. package/src/lib/actions/zoom/resetView.ts +17 -0
  108. package/src/lib/actions/zoom/resetViewToCenter.ts +21 -0
  109. package/src/lib/actions/zoom/setZoom.ts +22 -0
  110. package/src/lib/actions/zoom/zoomIn.ts +21 -0
  111. package/src/lib/actions/zoom/zoomOut.ts +21 -0
  112. package/src/lib/actions/zoom/zoomToPoint.ts +18 -0
  113. package/src/lib/canvas/createCanvas.ts +6 -14
  114. package/src/lib/canvas/fitToScreen.ts +27 -0
  115. package/src/lib/canvas/getCanvasBounds.ts +3 -4
  116. package/src/lib/canvas/index.ts +1 -1
  117. package/src/lib/config/constants.ts +2 -6
  118. package/src/lib/config/presets/editor-preset.ts +2 -6
  119. package/src/lib/events/emitTransformEvents.ts +9 -0
  120. package/src/lib/events/keyboard/handleKeyDown.ts +3 -2
  121. package/src/lib/events/keyboard/handleKeyUp.ts +3 -2
  122. package/src/lib/events/keyboard/setupKeyboardEvents.ts +3 -2
  123. package/src/lib/events/mouse/createMouseDragControls.ts +21 -0
  124. package/src/lib/events/mouse/handleClickToZoom.ts +3 -2
  125. package/src/lib/events/mouse/handleMouseDown.ts +3 -2
  126. package/src/lib/events/mouse/handleMouseLeave.ts +3 -2
  127. package/src/lib/events/mouse/handleMouseMove.ts +3 -2
  128. package/src/lib/events/mouse/handleMouseUp.ts +3 -2
  129. package/src/lib/events/mouse/setupMouseDrag.ts +5 -4
  130. package/src/lib/events/mouse/setupMouseEvents.ts +5 -4
  131. package/src/lib/events/postMessage/setupPostMessageEvents.ts +10 -0
  132. package/src/lib/events/touch/handleTouchMove.ts +3 -2
  133. package/src/lib/events/touch/setupTouchEvents.ts +3 -2
  134. package/src/lib/events/trackpad/createTrackpadPanHandler.ts +3 -2
  135. package/src/lib/events/utils/getAdaptiveZoomSpeed.ts +2 -2
  136. package/src/lib/events/utils/getViewportCenter.ts +2 -2
  137. package/src/lib/events/utils/resetDragState.ts +3 -2
  138. package/src/lib/events/utils/updateCursor.ts +3 -2
  139. package/src/lib/events/wheel/handleWheel.ts +3 -2
  140. package/src/lib/events/wheel/setupWheelEvents.ts +3 -2
  141. package/src/lib/events/wheel/setupWheelHandler.ts +3 -2
  142. package/src/lib/helpers/getVisibleArea.ts +6 -0
  143. package/src/lib/helpers/index.ts +2 -0
  144. package/src/lib/helpers/isPointVisible.ts +7 -0
  145. package/src/lib/rulers/createRulers.ts +0 -1
  146. package/src/lib/transform/applyZoomToCanvas.ts +2 -2
  147. package/src/lib/window/bindCanvasToWindow.ts +128 -0
  148. package/src/lib/window/broadcastEvent.ts +38 -0
  149. package/src/lib/window/cleanupWindowBinding.ts +15 -0
  150. package/src/lib/window/index.ts +3 -0
  151. package/src/types/canvas.ts +1 -48
  152. package/src/types/config.ts +1 -7
  153. package/src/types/events.ts +7 -1
  154. package/src/types/index.ts +4 -2
  155. package/src/types/window.ts +77 -0
  156. package/dist/lib/canvas/config.d.ts +0 -2
  157. package/dist/lib/canvas/getCanvasMethods.d.ts +0 -12
  158. package/src/lib/canvas/config.ts +0 -29
  159. package/src/lib/canvas/getCanvasMethods.ts +0 -102
  160. /package/dist/lib/canvas/{calcVisibleArea.d.ts → calculateVisibleArea.d.ts} +0 -0
  161. /package/src/lib/canvas/{calcVisibleArea.ts → calculateVisibleArea.ts} +0 -0
@@ -1,15 +1,14 @@
1
1
  /**
2
2
  * Markup Canvas
3
3
  * High-performance markup canvas with zoom and pan capabilities
4
- * @version 1.1.7
4
+ * @version 1.2.0
5
5
  */
6
6
  const EDITOR_PRESET = {
7
7
  // Canvas dimensions
8
8
  width: 4000,
9
9
  height: 4000,
10
10
  enableAcceleration: true,
11
- // Global Binding & Instance Access
12
- bindToWindow: true,
11
+ // Global Instance Access
13
12
  name: "canvas",
14
13
  enablePostMessageAPI: true,
15
14
  // Interaction controls
@@ -39,7 +38,7 @@ const EDITOR_PRESET = {
39
38
  requireOptionForClickZoom: true,
40
39
  // Visual elements
41
40
  enableRulers: true,
42
- enableGrid: false,
41
+ enableGrid: true,
43
42
  showRulers: true,
44
43
  showGrid: false,
45
44
  rulerFontSize: 9,
@@ -63,72 +62,8 @@ const EDITOR_PRESET = {
63
62
  gridColorDark: "rgba(232, 86, 193, 0.5)",
64
63
  // Theme
65
64
  themeMode: "light",
66
- // Callbacks
67
- onTransformUpdate: () => { },
68
65
  };
69
66
 
70
- // Default transform values
71
- const DEFAULT_ZOOM = 1.0;
72
- // Validation thresholds
73
- const ZOOM_CHANGE_THRESHOLD = 0.001;
74
- // CSS transition values
75
- const FALLBACK_TRANSITION_DURATION = 0.2;
76
- // Zoom to fit padding factor
77
- const ZOOM_FIT_PADDING = 0.9;
78
- // CSS class names
79
- const CANVAS_CONTAINER_CLASS = "canvas-container";
80
- const TRANSFORM_LAYER_CLASS = "transform-layer";
81
- const CONTENT_LAYER_CLASS = "content-layer";
82
-
83
- function moveExistingContent(existingContent, contentLayer, transformLayer) {
84
- existingContent.forEach((child) => {
85
- if (child !== transformLayer && !child.classList.contains(TRANSFORM_LAYER_CLASS)) {
86
- contentLayer.appendChild(child);
87
- }
88
- });
89
- }
90
-
91
- function setupContentLayer(contentLayer) {
92
- contentLayer.style.position = "relative";
93
- contentLayer.style.width = "100%";
94
- contentLayer.style.height = "100%";
95
- contentLayer.style.pointerEvents = "auto";
96
- }
97
-
98
- // Sets up the transform layer with proper styles and dimensions
99
- function setupTransformLayer(transformLayer, config) {
100
- transformLayer.style.position = "absolute";
101
- const rulerOffset = config.rulerSize;
102
- transformLayer.style.top = `${rulerOffset}px`;
103
- transformLayer.style.left = `${rulerOffset}px`;
104
- transformLayer.style.width = `${config.width}px`;
105
- transformLayer.style.height = `${config.height}px`;
106
- transformLayer.style.transformOrigin = "0 0";
107
- }
108
-
109
- function createCanvasLayers(container, config) {
110
- const existingContent = Array.from(container.children);
111
- // Create or find transform layer
112
- let transformLayer = container.querySelector(`.${TRANSFORM_LAYER_CLASS}`);
113
- if (!transformLayer) {
114
- transformLayer = document.createElement("div");
115
- transformLayer.className = TRANSFORM_LAYER_CLASS;
116
- container.appendChild(transformLayer);
117
- }
118
- setupTransformLayer(transformLayer, config);
119
- // Create or find content layer
120
- let contentLayer = transformLayer.querySelector(`.${CONTENT_LAYER_CLASS}`);
121
- if (!contentLayer) {
122
- contentLayer = document.createElement("div");
123
- contentLayer.className = CONTENT_LAYER_CLASS;
124
- transformLayer.appendChild(contentLayer);
125
- moveExistingContent(existingContent, contentLayer, transformLayer);
126
- }
127
- // Set content layer properties
128
- setupContentLayer(contentLayer);
129
- return { transformLayer, contentLayer };
130
- }
131
-
132
67
  function canvasToContent(canvasX, canvasY, matrix) {
133
68
  if (!matrix?.inverse) {
134
69
  return { x: canvasX, y: canvasY };
@@ -156,6 +91,19 @@ function createMatrix(scale, translateX, translateY) {
156
91
  return new DOMMatrix([scale, 0, 0, scale, translateX, translateY]);
157
92
  }
158
93
 
94
+ // Default transform values
95
+ const DEFAULT_ZOOM = 1.0;
96
+ // Validation thresholds
97
+ const ZOOM_CHANGE_THRESHOLD = 0.001;
98
+ // CSS transition values
99
+ const FALLBACK_TRANSITION_DURATION = 0.2;
100
+ // Zoom to fit padding factor
101
+ const ZOOM_FIT_PADDING = 0.9;
102
+ // CSS class names
103
+ const CANVAS_CONTAINER_CLASS = "canvas-container";
104
+ const TRANSFORM_LAYER_CLASS = "transform-layer";
105
+ const CONTENT_LAYER_CLASS = "content-layer";
106
+
159
107
  function getZoomToMouseTransform(mouseX, mouseY, currentTransform, zoomFactor, config) {
160
108
  const rulerOffset = config.enableRulers ? -config.rulerSize : 0;
161
109
  const transform = currentTransform || {
@@ -217,6 +165,16 @@ function getEmptyBounds() {
217
165
  };
218
166
  }
219
167
 
168
+ function getVisibleArea(canvas) {
169
+ const bounds = canvas.getBounds();
170
+ return bounds.visibleArea;
171
+ }
172
+
173
+ function isPointVisible(canvas, x, y) {
174
+ const visibleArea = getVisibleArea(canvas);
175
+ return x >= visibleArea.x && x <= visibleArea.x + visibleArea.width && y >= visibleArea.y && y <= visibleArea.y + visibleArea.height;
176
+ }
177
+
220
178
  function withClampedZoom(config, operation) {
221
179
  const clampFunction = (scale) => clampZoom(scale, config);
222
180
  return operation(clampFunction);
@@ -303,8 +261,7 @@ const DEFAULT_CONFIG = {
303
261
  width: 8000,
304
262
  height: 8000,
305
263
  enableAcceleration: true,
306
- // Global Binding & Instance Access
307
- bindToWindow: false,
264
+ // Global Instance Access
308
265
  name: "markupCanvas",
309
266
  enablePostMessageAPI: false,
310
267
  // Interaction controls
@@ -312,7 +269,7 @@ const DEFAULT_CONFIG = {
312
269
  enablePan: true,
313
270
  enableTouch: true,
314
271
  enableKeyboard: true,
315
- bindKeyboardEventsTo: "canvas",
272
+ bindKeyboardEventsTo: "document",
316
273
  // Zoom behavior
317
274
  zoomSpeed: 1.5,
318
275
  minZoom: 0.05,
@@ -358,14 +315,11 @@ const DEFAULT_CONFIG = {
358
315
  gridColorDark: "rgba(232, 86, 193, 0.5)",
359
316
  // Theme
360
317
  themeMode: "light",
361
- // Callbacks
362
- onTransformUpdate: () => { },
363
318
  };
364
319
 
365
- function getCanvasBounds(canvas) {
320
+ function getCanvasBounds(canvas, config) {
366
321
  try {
367
322
  const container = canvas.container;
368
- const config = canvas.config;
369
323
  const transform = canvas.transform || {
370
324
  scale: 1.0,
371
325
  translateX: 0,
@@ -415,37 +369,6 @@ function getCanvasBounds(canvas) {
415
369
  }
416
370
  }
417
371
 
418
- function createMatrixString(matrix) {
419
- return `matrix3d(${matrix.m11}, ${matrix.m12}, ${matrix.m13}, ${matrix.m14}, ${matrix.m21}, ${matrix.m22}, ${matrix.m23}, ${matrix.m24}, ${matrix.m31}, ${matrix.m32}, ${matrix.m33}, ${matrix.m34}, ${matrix.m41}, ${matrix.m42}, ${matrix.m43}, ${matrix.m44})`;
420
- }
421
-
422
- function applyTransform(element, matrix) {
423
- if (!element?.style || !matrix) {
424
- return false;
425
- }
426
- try {
427
- element.style.transform = createMatrixString(matrix);
428
- return true;
429
- }
430
- catch (error) {
431
- console.warn("Transform application failed:", error);
432
- return false;
433
- }
434
- }
435
-
436
- function enableHardwareAcceleration(element) {
437
- try {
438
- // Set CSS properties for hardware acceleration
439
- element.style.transform = element.style.transform || "translateZ(0)";
440
- element.style.backfaceVisibility = "hidden";
441
- return true;
442
- }
443
- catch (error) {
444
- console.error("Failed to enable hardware acceleration:", error);
445
- return false;
446
- }
447
- }
448
-
449
372
  function disableTransition(element, config) {
450
373
  try {
451
374
  if (config.enableTransition) {
@@ -497,85 +420,386 @@ function withTransition(element, config, operation) {
497
420
  }
498
421
  }
499
422
 
500
- function getCanvasMethods() {
501
- return {
502
- // Utility methods
503
- getBounds: function () {
504
- return getCanvasBounds(this);
505
- },
506
- // Transform methods
507
- updateTransform: function (newTransform) {
508
- this.transform = { ...this.transform, ...newTransform };
509
- const matrix = createMatrix(this.transform.scale, this.transform.translateX, this.transform.translateY);
510
- const result = applyTransform(this.transformLayer, matrix);
511
- withFeatureEnabled(this.config, "onTransformUpdate", () => {
512
- this.config.onTransformUpdate(this.transform);
513
- });
514
- return result;
515
- },
516
- // Reset method
517
- reset: function () {
518
- const resetTransform = {
519
- scale: 1.0,
520
- translateX: 0,
521
- translateY: 0,
522
- };
523
- return this.updateTransform(resetTransform);
524
- },
525
- // Handle canvas resize
526
- handleResize: function () {
527
- return true;
528
- },
529
- // Set zoom level
530
- setZoom: function (zoomLevel) {
531
- const newScale = withClampedZoom(this.config, (clamp) => clamp(zoomLevel));
532
- return this.updateTransform({ scale: newScale });
533
- },
534
- // Convert canvas coordinates to content coordinates
535
- canvasToContent: function (x, y) {
536
- const matrix = createMatrix(this.transform.scale, this.transform.translateX, this.transform.translateY);
537
- return canvasToContent(x, y, matrix);
538
- },
539
- // Zoom to a specific point with animation
540
- zoomToPoint: function (x, y, targetScale) {
541
- return withTransition(this.transformLayer, this.config, () => {
542
- const newTransform = getZoomToMouseTransform(x, y, this.transform, targetScale / this.transform.scale, this.config);
543
- return this.updateTransform(newTransform);
544
- });
545
- },
546
- // Reset view with animation
547
- resetView: function () {
548
- return withTransition(this.transformLayer, this.config, () => {
549
- return withRulerSize(this, this.config.rulerSize, (rulerSize) => {
550
- const resetTransform = {
551
- scale: 1.0,
552
- translateX: rulerSize * -1,
553
- translateY: rulerSize * -1,
554
- };
555
- return this.updateTransform(resetTransform);
556
- });
557
- });
558
- },
559
- // Zoom to fit content in canvas
560
- zoomToFitContent: function () {
561
- return withTransition(this.transformLayer, this.config, () => {
562
- const bounds = this.getBounds();
563
- const scaleX = bounds.width / this.config.width;
564
- const scaleY = bounds.height / this.config.height;
565
- const fitScale = withClampedZoom(this.config, (clamp) => clamp(Math.min(scaleX, scaleY) * ZOOM_FIT_PADDING));
566
- // Center the content
567
- const scaledWidth = this.config.width * fitScale;
568
- const scaledHeight = this.config.height * fitScale;
569
- const centerX = (bounds.width - scaledWidth) / 2;
570
- const centerY = (bounds.height - scaledHeight) / 2;
571
- return this.updateTransform({
572
- scale: fitScale,
573
- translateX: centerX,
574
- translateY: centerY,
575
- });
576
- });
577
- },
578
- };
423
+ function centerContent(canvas, config, updateTransformFn, transformLayer) {
424
+ return withTransition(transformLayer, config, () => {
425
+ const bounds = getCanvasBounds(canvas, config);
426
+ const centerX = (bounds.width - bounds.contentWidth * canvas.transform.scale) / 2;
427
+ const centerY = (bounds.height - bounds.contentHeight * canvas.transform.scale) / 2;
428
+ return updateTransformFn({
429
+ translateX: centerX,
430
+ translateY: centerY,
431
+ });
432
+ });
433
+ }
434
+
435
+ function panDown(canvas, config, updateTransform) {
436
+ const panDistance = config.keyboardPanStep;
437
+ const newTransform = {
438
+ translateY: canvas.transform.translateY - panDistance,
439
+ };
440
+ return updateTransform(newTransform);
441
+ }
442
+
443
+ function panLeft(canvas, config, updateTransform) {
444
+ const panDistance = config.keyboardPanStep;
445
+ const newTransform = {
446
+ translateX: canvas.transform.translateX + panDistance,
447
+ };
448
+ return updateTransform(newTransform);
449
+ }
450
+
451
+ function panRight(canvas, config, updateTransform) {
452
+ const panDistance = config.keyboardPanStep;
453
+ const newTransform = {
454
+ translateX: canvas.transform.translateX - panDistance,
455
+ };
456
+ return updateTransform(newTransform);
457
+ }
458
+
459
+ function panUp(canvas, config, updateTransform) {
460
+ const panDistance = config.keyboardPanStep;
461
+ const newTransform = {
462
+ translateY: canvas.transform.translateY + panDistance,
463
+ };
464
+ return updateTransform(newTransform);
465
+ }
466
+
467
+ function scrollToPoint(canvas, config, x, y, updateTransform, transformLayer) {
468
+ return withTransition(transformLayer, config, () => {
469
+ const bounds = getCanvasBounds(canvas, config);
470
+ const centerX = bounds.width / 2;
471
+ const centerY = bounds.height / 2;
472
+ // Calculate new translation to center the point
473
+ const newTranslateX = centerX - x * canvas.transform.scale;
474
+ const newTranslateY = centerY - y * canvas.transform.scale;
475
+ return updateTransform({
476
+ translateX: newTranslateX,
477
+ translateY: newTranslateY,
478
+ });
479
+ });
480
+ }
481
+
482
+ function createMatrixString(matrix) {
483
+ return `matrix3d(${matrix.m11}, ${matrix.m12}, ${matrix.m13}, ${matrix.m14}, ${matrix.m21}, ${matrix.m22}, ${matrix.m23}, ${matrix.m24}, ${matrix.m31}, ${matrix.m32}, ${matrix.m33}, ${matrix.m34}, ${matrix.m41}, ${matrix.m42}, ${matrix.m43}, ${matrix.m44})`;
484
+ }
485
+
486
+ function applyTransform(element, matrix) {
487
+ if (!element?.style || !matrix) {
488
+ return false;
489
+ }
490
+ try {
491
+ element.style.transform = createMatrixString(matrix);
492
+ return true;
493
+ }
494
+ catch (error) {
495
+ console.warn("Transform application failed:", error);
496
+ return false;
497
+ }
498
+ }
499
+
500
+ function enableHardwareAcceleration(element) {
501
+ try {
502
+ // Set CSS properties for hardware acceleration
503
+ element.style.transform = element.style.transform || "translateZ(0)";
504
+ element.style.backfaceVisibility = "hidden";
505
+ return true;
506
+ }
507
+ catch (error) {
508
+ console.error("Failed to enable hardware acceleration:", error);
509
+ return false;
510
+ }
511
+ }
512
+
513
+ function updateTransform(canvas, newTransform) {
514
+ canvas.transform = { ...canvas.transform, ...newTransform };
515
+ const matrix = createMatrix(canvas.transform.scale, canvas.transform.translateX, canvas.transform.translateY);
516
+ return applyTransform(canvas.transformLayer, matrix);
517
+ }
518
+
519
+ function resetTransform(canvas) {
520
+ const resetTransformData = {
521
+ scale: 1.0,
522
+ translateX: 0,
523
+ translateY: 0,
524
+ };
525
+ return updateTransform(canvas, resetTransformData);
526
+ }
527
+
528
+ function hideGrid(rulers) {
529
+ if (rulers?.gridOverlay) {
530
+ rulers.gridOverlay.style.display = "none";
531
+ return true;
532
+ }
533
+ return false;
534
+ }
535
+
536
+ function isGridVisible(rulers) {
537
+ if (rulers?.gridOverlay) {
538
+ return rulers.gridOverlay.style.display !== "none";
539
+ }
540
+ return false;
541
+ }
542
+
543
+ function showGrid(rulers) {
544
+ if (rulers?.gridOverlay) {
545
+ rulers.gridOverlay.style.display = "block";
546
+ return true;
547
+ }
548
+ return false;
549
+ }
550
+
551
+ function toggleGrid(rulers) {
552
+ if (rulers?.toggleGrid) {
553
+ rulers.toggleGrid();
554
+ return true;
555
+ }
556
+ return false;
557
+ }
558
+
559
+ function areRulersVisible(rulers) {
560
+ if (rulers?.horizontalRuler) {
561
+ return rulers.horizontalRuler.style.display !== "none";
562
+ }
563
+ return false;
564
+ }
565
+
566
+ function hideRulers(rulers) {
567
+ if (rulers) {
568
+ rulers.hide();
569
+ return true;
570
+ }
571
+ return false;
572
+ }
573
+
574
+ function showRulers(rulers) {
575
+ if (rulers) {
576
+ rulers.show();
577
+ return true;
578
+ }
579
+ return false;
580
+ }
581
+
582
+ function toggleRulers(rulers, areRulersVisible) {
583
+ if (rulers) {
584
+ const isVisible = areRulersVisible();
585
+ if (isVisible) {
586
+ rulers.hide();
587
+ }
588
+ else {
589
+ rulers.show();
590
+ }
591
+ return true;
592
+ }
593
+ return false;
594
+ }
595
+
596
+ function toggleTransition(enableTransition) {
597
+ return !enableTransition;
598
+ }
599
+
600
+ function createMarkupCanvasConfig(options = {}) {
601
+ const config = {
602
+ ...DEFAULT_CONFIG,
603
+ ...options,
604
+ };
605
+ if (typeof config.width !== "number" || config.width <= 0) {
606
+ console.warn("Invalid width, using default");
607
+ config.width = DEFAULT_CONFIG.width;
608
+ }
609
+ if (typeof config.height !== "number" || config.height <= 0) {
610
+ console.warn("Invalid height, using default");
611
+ config.height = DEFAULT_CONFIG.height;
612
+ }
613
+ if (typeof config.zoomSpeed !== "number" || config.zoomSpeed <= 0) {
614
+ console.warn("Invalid zoomSpeed, using default");
615
+ config.zoomSpeed = DEFAULT_CONFIG.zoomSpeed;
616
+ }
617
+ if (typeof config.minZoom !== "number" || config.minZoom <= 0) {
618
+ console.warn("Invalid minZoom, using default");
619
+ config.minZoom = DEFAULT_CONFIG.minZoom;
620
+ }
621
+ if (typeof config.maxZoom !== "number" || config.maxZoom <= config.minZoom) {
622
+ console.warn("Invalid maxZoom, using default");
623
+ config.maxZoom = DEFAULT_CONFIG.maxZoom;
624
+ }
625
+ if (typeof config.keyboardPanStep !== "number" || config.keyboardPanStep <= 0) {
626
+ console.warn("Invalid keyboardPanStep, using default");
627
+ config.keyboardPanStep = DEFAULT_CONFIG.keyboardPanStep;
628
+ }
629
+ if (typeof config.keyboardFastMultiplier !== "number" || config.keyboardFastMultiplier <= 0) {
630
+ console.warn("Invalid keyboardFastMultiplier, using default");
631
+ config.keyboardFastMultiplier = DEFAULT_CONFIG.keyboardFastMultiplier;
632
+ }
633
+ if (typeof config.clickZoomLevel !== "number" || config.clickZoomLevel <= 0) {
634
+ console.warn("Invalid clickZoomLevel, using default");
635
+ config.clickZoomLevel = DEFAULT_CONFIG.clickZoomLevel;
636
+ }
637
+ if (typeof config.rulerFontSize !== "number" || config.rulerFontSize <= 0) {
638
+ console.warn("Invalid rulerFontSize, using default");
639
+ config.rulerFontSize = DEFAULT_CONFIG.rulerFontSize;
640
+ }
641
+ if (typeof config.rulerSize !== "number" || config.rulerSize <= 0) {
642
+ console.warn("Invalid rulerSize, using default");
643
+ config.rulerSize = DEFAULT_CONFIG.rulerSize;
644
+ }
645
+ return config;
646
+ }
647
+
648
+ function updateThemeMode(canvasContainer, config, rulers, mode) {
649
+ const newConfig = {
650
+ ...config,
651
+ themeMode: mode,
652
+ };
653
+ const updatedConfig = createMarkupCanvasConfig(newConfig);
654
+ // Update canvas background color
655
+ const backgroundColor = getThemeValue(updatedConfig, "canvasBackgroundColor");
656
+ canvasContainer.style.backgroundColor = backgroundColor;
657
+ // Update rulers if they exist
658
+ if (rulers) {
659
+ rulers.updateTheme(updatedConfig);
660
+ }
661
+ }
662
+
663
+ function resetView(canvas, transformLayer, config) {
664
+ return withTransition(transformLayer, config, () => {
665
+ return withRulerSize(canvas, config.rulerSize, (rulerSize) => {
666
+ const resetTransformData = {
667
+ scale: 1.0,
668
+ translateX: rulerSize * -1,
669
+ translateY: rulerSize * -1,
670
+ };
671
+ return updateTransform(canvas, resetTransformData);
672
+ });
673
+ });
674
+ }
675
+
676
+ function getViewportCenter(canvas) {
677
+ try {
678
+ const bounds = canvas.getBounds();
679
+ return {
680
+ x: bounds.width / 2,
681
+ y: bounds.height / 2,
682
+ };
683
+ }
684
+ catch (error) {
685
+ console.warn("Failed to calculate viewport center:", error);
686
+ return { x: 0, y: 0 };
687
+ }
688
+ }
689
+
690
+ function resetViewToCenter(canvas, transformLayer, config, zoomToPoint) {
691
+ return withTransition(transformLayer, config, () => {
692
+ return withClampedZoom(config, (clamp) => {
693
+ const newScale = clamp(1.0);
694
+ const center = getViewportCenter(canvas);
695
+ return zoomToPoint(center.x, center.y, newScale);
696
+ });
697
+ });
698
+ }
699
+
700
+ function setZoom(canvas, transformLayer, config, zoomToPoint, zoomLevel) {
701
+ return withTransition(transformLayer, config, () => {
702
+ return withClampedZoom(config, (clamp) => {
703
+ const newScale = clamp(zoomLevel);
704
+ const center = getViewportCenter(canvas);
705
+ return zoomToPoint(center.x, center.y, newScale);
706
+ });
707
+ });
708
+ }
709
+
710
+ function zoomIn(canvas, transformLayer, config, zoomToPoint, factor = 0.5) {
711
+ return withTransition(transformLayer, config, () => {
712
+ return withClampedZoom(config, (clamp) => {
713
+ const newScale = clamp(canvas.transform.scale * (1 + factor));
714
+ const center = getViewportCenter(canvas);
715
+ return zoomToPoint(center.x, center.y, newScale);
716
+ });
717
+ });
718
+ }
719
+
720
+ function zoomOut(canvas, transformLayer, config, zoomToPoint, factor = 0.5) {
721
+ return withTransition(transformLayer, config, () => {
722
+ return withClampedZoom(config, (clamp) => {
723
+ const newScale = clamp(canvas.transform.scale * (1 - factor));
724
+ const center = getViewportCenter(canvas);
725
+ return zoomToPoint(center.x, center.y, newScale);
726
+ });
727
+ });
728
+ }
729
+
730
+ function zoomToPoint(canvas, transformLayer, config, x, y, targetScale) {
731
+ return withTransition(transformLayer, config, () => {
732
+ const newTransform = getZoomToMouseTransform(x, y, canvas.transform, targetScale / canvas.transform.scale, config);
733
+ return updateTransform(canvas, newTransform);
734
+ });
735
+ }
736
+
737
+ function fitToScreen(canvas, transformLayer, config) {
738
+ return withTransition(transformLayer, config, () => {
739
+ const bounds = getCanvasBounds(canvas, config);
740
+ const scaleX = bounds.width / config.width;
741
+ const scaleY = bounds.height / config.height;
742
+ const fitScale = withClampedZoom(config, (clamp) => clamp(Math.min(scaleX, scaleY) * ZOOM_FIT_PADDING));
743
+ // Center the content
744
+ const scaledWidth = config.width * fitScale;
745
+ const scaledHeight = config.height * fitScale;
746
+ const centerX = (bounds.width - scaledWidth) / 2;
747
+ const centerY = (bounds.height - scaledHeight) / 2;
748
+ return updateTransform(canvas, {
749
+ scale: fitScale,
750
+ translateX: centerX,
751
+ translateY: centerY,
752
+ });
753
+ });
754
+ }
755
+
756
+ function moveExistingContent(existingContent, contentLayer, transformLayer) {
757
+ existingContent.forEach((child) => {
758
+ if (child !== transformLayer && !child.classList.contains(TRANSFORM_LAYER_CLASS)) {
759
+ contentLayer.appendChild(child);
760
+ }
761
+ });
762
+ }
763
+
764
+ function setupContentLayer(contentLayer) {
765
+ contentLayer.style.position = "relative";
766
+ contentLayer.style.width = "100%";
767
+ contentLayer.style.height = "100%";
768
+ contentLayer.style.pointerEvents = "auto";
769
+ }
770
+
771
+ // Sets up the transform layer with proper styles and dimensions
772
+ function setupTransformLayer(transformLayer, config) {
773
+ transformLayer.style.position = "absolute";
774
+ const rulerOffset = config.rulerSize;
775
+ transformLayer.style.top = `${rulerOffset}px`;
776
+ transformLayer.style.left = `${rulerOffset}px`;
777
+ transformLayer.style.width = `${config.width}px`;
778
+ transformLayer.style.height = `${config.height}px`;
779
+ transformLayer.style.transformOrigin = "0 0";
780
+ }
781
+
782
+ function createCanvasLayers(container, config) {
783
+ const existingContent = Array.from(container.children);
784
+ // Create or find transform layer
785
+ let transformLayer = container.querySelector(`.${TRANSFORM_LAYER_CLASS}`);
786
+ if (!transformLayer) {
787
+ transformLayer = document.createElement("div");
788
+ transformLayer.className = TRANSFORM_LAYER_CLASS;
789
+ container.appendChild(transformLayer);
790
+ }
791
+ setupTransformLayer(transformLayer, config);
792
+ // Create or find content layer
793
+ let contentLayer = transformLayer.querySelector(`.${CONTENT_LAYER_CLASS}`);
794
+ if (!contentLayer) {
795
+ contentLayer = document.createElement("div");
796
+ contentLayer.className = CONTENT_LAYER_CLASS;
797
+ transformLayer.appendChild(contentLayer);
798
+ moveExistingContent(existingContent, contentLayer, transformLayer);
799
+ }
800
+ // Set content layer properties
801
+ setupContentLayer(contentLayer);
802
+ return { transformLayer, contentLayer };
579
803
  }
580
804
 
581
805
  function checkContainerDimensions(container) {
@@ -611,7 +835,6 @@ function setupCanvasContainer(container, config) {
611
835
  }
612
836
  }
613
837
 
614
- // Creates and initializes a canvas with the required DOM structure
615
838
  function createCanvas(container, config) {
616
839
  if (!container?.appendChild) {
617
840
  console.error("Invalid container element provided to createCanvas");
@@ -620,10 +843,9 @@ function createCanvas(container, config) {
620
843
  try {
621
844
  setupCanvasContainer(container, config);
622
845
  const { transformLayer, contentLayer } = createCanvasLayers(container, config);
623
- // Enable hardware acceleration if requested
624
- if (config.enableAcceleration) {
846
+ withFeatureEnabled(config, "enableAcceleration", () => {
625
847
  enableHardwareAcceleration(transformLayer);
626
- }
848
+ });
627
849
  const rulerOffset = config.enableRulers ? -config.rulerSize : 0;
628
850
  const initialTransform = {
629
851
  scale: DEFAULT_ZOOM,
@@ -638,12 +860,8 @@ function createCanvas(container, config) {
638
860
  container,
639
861
  transformLayer,
640
862
  contentLayer,
641
- // Configuration
642
- config: config,
643
863
  // Current state
644
864
  transform: initialTransform,
645
- // Add all canvas methods
646
- ...getCanvasMethods(),
647
865
  };
648
866
  return canvas;
649
867
  }
@@ -653,54 +871,6 @@ function createCanvas(container, config) {
653
871
  }
654
872
  }
655
873
 
656
- function createMarkupCanvasConfig(options = {}) {
657
- const config = {
658
- ...DEFAULT_CONFIG,
659
- ...options,
660
- };
661
- if (typeof config.width !== "number" || config.width <= 0) {
662
- console.warn("Invalid width, using default");
663
- config.width = DEFAULT_CONFIG.width;
664
- }
665
- if (typeof config.height !== "number" || config.height <= 0) {
666
- console.warn("Invalid height, using default");
667
- config.height = DEFAULT_CONFIG.height;
668
- }
669
- if (typeof config.zoomSpeed !== "number" || config.zoomSpeed <= 0) {
670
- console.warn("Invalid zoomSpeed, using default");
671
- config.zoomSpeed = DEFAULT_CONFIG.zoomSpeed;
672
- }
673
- if (typeof config.minZoom !== "number" || config.minZoom <= 0) {
674
- console.warn("Invalid minZoom, using default");
675
- config.minZoom = DEFAULT_CONFIG.minZoom;
676
- }
677
- if (typeof config.maxZoom !== "number" || config.maxZoom <= config.minZoom) {
678
- console.warn("Invalid maxZoom, using default");
679
- config.maxZoom = DEFAULT_CONFIG.maxZoom;
680
- }
681
- if (typeof config.keyboardPanStep !== "number" || config.keyboardPanStep <= 0) {
682
- console.warn("Invalid keyboardPanStep, using default");
683
- config.keyboardPanStep = DEFAULT_CONFIG.keyboardPanStep;
684
- }
685
- if (typeof config.keyboardFastMultiplier !== "number" || config.keyboardFastMultiplier <= 0) {
686
- console.warn("Invalid keyboardFastMultiplier, using default");
687
- config.keyboardFastMultiplier = DEFAULT_CONFIG.keyboardFastMultiplier;
688
- }
689
- if (typeof config.clickZoomLevel !== "number" || config.clickZoomLevel <= 0) {
690
- console.warn("Invalid clickZoomLevel, using default");
691
- config.clickZoomLevel = DEFAULT_CONFIG.clickZoomLevel;
692
- }
693
- if (typeof config.rulerFontSize !== "number" || config.rulerFontSize <= 0) {
694
- console.warn("Invalid rulerFontSize, using default");
695
- config.rulerFontSize = DEFAULT_CONFIG.rulerFontSize;
696
- }
697
- if (typeof config.rulerSize !== "number" || config.rulerSize <= 0) {
698
- console.warn("Invalid rulerSize, using default");
699
- config.rulerSize = DEFAULT_CONFIG.rulerSize;
700
- }
701
- return config;
702
- }
703
-
704
874
  class EventEmitter {
705
875
  constructor() {
706
876
  this.listeners = new Map();
@@ -739,6 +909,13 @@ class EventEmitter {
739
909
  }
740
910
  }
741
911
 
912
+ function emitTransformEvents(listen, canvas) {
913
+ const transform = canvas.transform;
914
+ listen.emit("transform", transform);
915
+ listen.emit("zoom", transform.scale);
916
+ listen.emit("pan", { x: transform.translateX, y: transform.translateY });
917
+ }
918
+
742
919
  const REFERENCE_DISPLAY_AREA = 1920 * 1080;
743
920
  const TRACKPAD_PINCH_SPEED_FACTOR = 0.05;
744
921
  const ADAPTIVE_ZOOM_FACTOR = 1;
@@ -1233,6 +1410,17 @@ function setupPostMessageEvents(canvas) {
1233
1410
  const newMode = currentConfig.themeMode === "light" ? "dark" : "light";
1234
1411
  canvas.updateThemeMode(newMode);
1235
1412
  }
1413
+ // Transition methods
1414
+ else if (action === "updateTransition") {
1415
+ const enabled = args[0];
1416
+ if (typeof enabled !== "boolean") {
1417
+ throw new Error(`Invalid transition enabled value: ${enabled}. Must be a boolean.`);
1418
+ }
1419
+ canvas.updateTransition(enabled);
1420
+ }
1421
+ else if (action === "toggleTransitionMode") {
1422
+ canvas.toggleTransitionMode();
1423
+ }
1236
1424
  else {
1237
1425
  throw new Error(`Unknown action: ${action}`);
1238
1426
  }
@@ -1468,20 +1656,6 @@ function setupWheelEvents(canvas, config) {
1468
1656
  };
1469
1657
  }
1470
1658
 
1471
- function getViewportCenter(canvas) {
1472
- try {
1473
- const bounds = canvas.getBounds();
1474
- return {
1475
- x: bounds.width / 2,
1476
- y: bounds.height / 2,
1477
- };
1478
- }
1479
- catch (error) {
1480
- console.warn("Failed to calculate viewport center:", error);
1481
- return { x: 0, y: 0 };
1482
- }
1483
- }
1484
-
1485
1659
  // Rulers
1486
1660
  const RULER_Z_INDEX = {
1487
1661
  GRID: 100,
@@ -1844,8 +2018,6 @@ function createRulers(canvas, config) {
1844
2018
  elements.verticalRuler.style.display = "block";
1845
2019
  if (elements.cornerBox)
1846
2020
  elements.cornerBox.style.display = "flex";
1847
- if (elements.gridOverlay)
1848
- elements.gridOverlay.style.display = "block";
1849
2021
  },
1850
2022
  hide: () => {
1851
2023
  if (elements.horizontalRuler)
@@ -1889,14 +2061,163 @@ function createRulers(canvas, config) {
1889
2061
  }
1890
2062
  }
1891
2063
 
2064
+ function broadcastEvent(event, data, config) {
2065
+ if (typeof window === "undefined") {
2066
+ return;
2067
+ }
2068
+ // Receivers can get the instance from the window binding
2069
+ let broadcastData = data;
2070
+ if (event === "ready") {
2071
+ broadcastData = { ready: true };
2072
+ }
2073
+ window.postMessage({
2074
+ source: "markup-canvas",
2075
+ event,
2076
+ data: broadcastData,
2077
+ timestamp: Date.now(),
2078
+ canvasName: config.name,
2079
+ }, "*");
2080
+ if (window.parent) {
2081
+ window.parent.postMessage({
2082
+ source: "markup-canvas",
2083
+ event,
2084
+ data: broadcastData,
2085
+ timestamp: Date.now(),
2086
+ canvasName: config.name,
2087
+ }, "*");
2088
+ }
2089
+ }
2090
+
2091
+ function cleanupWindowBinding(config) {
2092
+ if (typeof window === "undefined") {
2093
+ return;
2094
+ }
2095
+ const canvasName = config.name || "markupCanvas";
2096
+ const windowObj = window;
2097
+ delete windowObj[canvasName];
2098
+ if (windowObj.__markupCanvasInstances) {
2099
+ windowObj.__markupCanvasInstances.delete(canvasName);
2100
+ }
2101
+ }
2102
+
2103
+ function bindCanvasToWindow(canvas, config) {
2104
+ if (typeof window === "undefined") {
2105
+ return;
2106
+ }
2107
+ const canvasName = config.name || "markupCanvas";
2108
+ const windowObj = window;
2109
+ const api = {
2110
+ config: {
2111
+ get current() {
2112
+ return canvas.config;
2113
+ },
2114
+ get: canvas.getConfig.bind(canvas),
2115
+ update: canvas.updateConfig.bind(canvas),
2116
+ },
2117
+ // Transform group
2118
+ transform: {
2119
+ update: canvas.updateTransform.bind(canvas),
2120
+ reset: canvas.reset.bind(canvas),
2121
+ },
2122
+ // Zoom group
2123
+ zoom: {
2124
+ set: canvas.setZoom.bind(canvas),
2125
+ toPoint: canvas.zoomToPoint.bind(canvas),
2126
+ in: canvas.zoomIn.bind(canvas),
2127
+ out: canvas.zoomOut.bind(canvas),
2128
+ reset: canvas.resetZoom.bind(canvas),
2129
+ resetToCenter: canvas.resetViewToCenter.bind(canvas),
2130
+ fitToScreen: canvas.fitToScreen.bind(canvas),
2131
+ },
2132
+ // Pan group
2133
+ pan: {
2134
+ left: canvas.panLeft.bind(canvas),
2135
+ right: canvas.panRight.bind(canvas),
2136
+ up: canvas.panUp.bind(canvas),
2137
+ down: canvas.panDown.bind(canvas),
2138
+ toPoint: canvas.scrollToPoint.bind(canvas),
2139
+ toCenter: canvas.centerContent.bind(canvas),
2140
+ },
2141
+ // Mouse drag group
2142
+ mouseDrag: {
2143
+ enable: canvas.enableMouseDrag.bind(canvas),
2144
+ disable: canvas.disableMouseDrag.bind(canvas),
2145
+ isEnabled: canvas.isMouseDragEnabled.bind(canvas),
2146
+ },
2147
+ // Grid group
2148
+ grid: {
2149
+ toggle: canvas.toggleGrid.bind(canvas),
2150
+ show: canvas.showGrid.bind(canvas),
2151
+ hide: canvas.hideGrid.bind(canvas),
2152
+ isVisible: canvas.isGridVisible.bind(canvas),
2153
+ },
2154
+ // Ruler group
2155
+ rulers: {
2156
+ toggle: canvas.toggleRulers.bind(canvas),
2157
+ show: canvas.showRulers.bind(canvas),
2158
+ hide: canvas.hideRulers.bind(canvas),
2159
+ isVisible: canvas.areRulersVisible.bind(canvas),
2160
+ },
2161
+ // Utility group
2162
+ canvas: {
2163
+ canvasToContent: canvas.canvasToContent.bind(canvas),
2164
+ getVisibleArea: canvas.getVisibleArea.bind(canvas),
2165
+ isPointVisible: canvas.isPointVisible.bind(canvas),
2166
+ getBounds: canvas.getBounds.bind(canvas),
2167
+ },
2168
+ theme: {
2169
+ get current() {
2170
+ return canvas.config.themeMode;
2171
+ },
2172
+ update: canvas.updateThemeMode.bind(canvas),
2173
+ toggle: canvas.toggleThemeMode.bind(canvas),
2174
+ },
2175
+ transition: {
2176
+ get current() {
2177
+ return canvas.config.enableTransition;
2178
+ },
2179
+ set: canvas.updateTransition.bind(canvas),
2180
+ toggle: canvas.toggleTransitionMode.bind(canvas),
2181
+ },
2182
+ // Event group
2183
+ event: canvas.event,
2184
+ // Lifecycle group
2185
+ lifecycle: {
2186
+ cleanup: canvas.cleanup.bind(canvas),
2187
+ destroy: canvas.destroy.bind(canvas),
2188
+ },
2189
+ // Properties/State group
2190
+ state: {
2191
+ get isReady() {
2192
+ return canvas.isReady;
2193
+ },
2194
+ get isTransforming() {
2195
+ return canvas.isTransforming;
2196
+ },
2197
+ get visibleBounds() {
2198
+ return canvas.visibleBounds;
2199
+ },
2200
+ get transform() {
2201
+ return canvas.transform;
2202
+ },
2203
+ },
2204
+ };
2205
+ // Bind public API to window
2206
+ windowObj[canvasName] = api;
2207
+ // Track all instances
2208
+ if (!windowObj.__markupCanvasInstances) {
2209
+ windowObj.__markupCanvasInstances = new Map();
2210
+ }
2211
+ windowObj.__markupCanvasInstances.set(canvasName, api);
2212
+ }
2213
+
1892
2214
  class MarkupCanvas {
1893
2215
  constructor(container, options = {}) {
1894
- this.cleanupFunctions = [];
2216
+ this.cleanupCallbacks = [];
1895
2217
  this.rulers = null;
1896
2218
  this.dragSetup = null;
2219
+ this.event = new EventEmitter();
1897
2220
  this._isReady = false;
1898
- this.listen = new EventEmitter();
1899
- this.postMessageCleanup = null;
1900
2221
  if (!container) {
1901
2222
  throw new Error("Container element is required");
1902
2223
  }
@@ -1905,100 +2226,48 @@ class MarkupCanvas {
1905
2226
  if (!canvas) {
1906
2227
  throw new Error("Failed to create canvas");
1907
2228
  }
1908
- this.baseCanvas = canvas;
1909
- if (this.config.bindToWindow) {
1910
- this.listen.setEmitInterceptor((event, data) => {
1911
- this.broadcastEvent(event, data);
1912
- });
1913
- this.setupGlobalBinding();
1914
- // Set up postMessage listener
1915
- if (this.config.enablePostMessageAPI) {
1916
- this.postMessageCleanup = setupPostMessageEvents(this);
1917
- }
2229
+ this.canvas = canvas;
2230
+ // Always bind canvas to window
2231
+ this.event.setEmitInterceptor((event, data) => {
2232
+ broadcastEvent(event, data, this.config);
2233
+ });
2234
+ bindCanvasToWindow(this, this.config);
2235
+ // Set up postMessage listener
2236
+ if (this.config.enablePostMessageAPI) {
2237
+ const postMessageCleanup = setupPostMessageEvents(this);
2238
+ this.cleanupCallbacks.push(postMessageCleanup);
1918
2239
  }
1919
2240
  this.setupEventHandlers();
1920
2241
  this._isReady = true;
1921
2242
  // Emit ready event
1922
- this.listen.emit("ready", this);
1923
- }
1924
- setupGlobalBinding() {
1925
- if (typeof window === "undefined") {
1926
- return;
1927
- }
1928
- const canvasName = this.config.name || "markupCanvas";
1929
- const windowObj = window;
1930
- // Bind instance to window
1931
- windowObj[canvasName] = this;
1932
- // Track all instances
1933
- if (!windowObj.__markupCanvasInstances) {
1934
- windowObj.__markupCanvasInstances = new Map();
1935
- }
1936
- windowObj.__markupCanvasInstances.set(canvasName, this);
1937
- }
1938
- cleanupGlobalBinding() {
1939
- if (typeof window === "undefined") {
1940
- return;
1941
- }
1942
- const canvasName = this.config.name || "markupCanvas";
1943
- const windowObj = window;
1944
- delete windowObj[canvasName];
1945
- if (windowObj.__markupCanvasInstances) {
1946
- windowObj.__markupCanvasInstances.delete(canvasName);
1947
- }
1948
- }
1949
- broadcastEvent(event, data) {
1950
- if (typeof window === "undefined") {
1951
- return;
1952
- }
1953
- // Receivers can get the instance from the window binding
1954
- let broadcastData = data;
1955
- if (event === "ready") {
1956
- broadcastData = { ready: true };
1957
- }
1958
- window.postMessage({
1959
- source: "markup-canvas",
1960
- event,
1961
- data: broadcastData,
1962
- timestamp: Date.now(),
1963
- canvasName: this.config.name,
1964
- }, "*");
1965
- if (window.parent) {
1966
- window.parent.postMessage({
1967
- source: "markup-canvas",
1968
- event,
1969
- data: broadcastData,
1970
- timestamp: Date.now(),
1971
- canvasName: this.config.name,
1972
- }, "*");
1973
- }
2243
+ this.event.emit("ready", this);
1974
2244
  }
1975
2245
  setupEventHandlers() {
1976
2246
  try {
1977
- // Wheel zoom
2247
+ // Wheel events
1978
2248
  withFeatureEnabled(this.config, "enableZoom", () => {
1979
2249
  const wheelCleanup = setupWheelEvents(this, this.config);
1980
- this.cleanupFunctions.push(wheelCleanup);
2250
+ this.cleanupCallbacks.push(wheelCleanup);
1981
2251
  });
1982
- // Mouse events (drag and click-to-zoom)
1983
- // Set up mouse events if either pan or click-to-zoom is enabled
2252
+ // Mouse events
1984
2253
  if (this.config.enablePan || this.config.enableClickToZoom) {
1985
2254
  this.dragSetup = setupMouseEvents(this, this.config, true);
1986
- this.cleanupFunctions.push(this.dragSetup.cleanup);
2255
+ this.cleanupCallbacks.push(this.dragSetup.cleanup);
1987
2256
  }
1988
- // Keyboard navigation
2257
+ // Keyboard events
1989
2258
  withFeatureEnabled(this.config, "enableKeyboard", () => {
1990
2259
  const keyboardCleanup = setupKeyboardEvents(this, this.config);
1991
- this.cleanupFunctions.push(keyboardCleanup);
2260
+ this.cleanupCallbacks.push(keyboardCleanup);
1992
2261
  });
1993
- // Touch events (if enabled)
2262
+ // Touch events
1994
2263
  withFeatureEnabled(this.config, "enableTouch", () => {
1995
2264
  const touchCleanup = setupTouchEvents(this);
1996
- this.cleanupFunctions.push(touchCleanup);
2265
+ this.cleanupCallbacks.push(touchCleanup);
1997
2266
  });
1998
2267
  // Set up rulers and grid
1999
2268
  withFeatureEnabled(this.config, "enableRulers", () => {
2000
- this.rulers = createRulers(this.baseCanvas, this.config);
2001
- this.cleanupFunctions.push(() => {
2269
+ this.rulers = createRulers(this, this.config);
2270
+ this.cleanupCallbacks.push(() => {
2002
2271
  if (this.rulers) {
2003
2272
  this.rulers.destroy();
2004
2273
  }
@@ -2011,20 +2280,18 @@ class MarkupCanvas {
2011
2280
  throw error;
2012
2281
  }
2013
2282
  }
2014
- // Base canvas properties and methods
2015
2283
  get container() {
2016
- return this.baseCanvas.container;
2284
+ return this.canvas.container;
2017
2285
  }
2018
2286
  get transformLayer() {
2019
- return this.baseCanvas.transformLayer;
2287
+ return this.canvas.transformLayer;
2020
2288
  }
2021
2289
  get contentLayer() {
2022
- return this.baseCanvas.contentLayer;
2290
+ return this.canvas.contentLayer;
2023
2291
  }
2024
2292
  get transform() {
2025
- return this.baseCanvas.transform;
2293
+ return this.canvas.transform;
2026
2294
  }
2027
- // State management getters for React integration
2028
2295
  get isReady() {
2029
2296
  return this._isReady;
2030
2297
  }
@@ -2032,131 +2299,62 @@ class MarkupCanvas {
2032
2299
  return this.dragSetup?.isEnabled() || false;
2033
2300
  }
2034
2301
  get visibleBounds() {
2035
- return this.getVisibleArea();
2302
+ return getVisibleArea(this);
2036
2303
  }
2037
2304
  getBounds() {
2038
- return this.baseCanvas.getBounds();
2305
+ return getCanvasBounds(this.canvas, this.config);
2039
2306
  }
2040
2307
  updateTransform(newTransform) {
2041
- const result = this.baseCanvas.updateTransform(newTransform);
2308
+ const result = updateTransform(this.canvas, newTransform);
2042
2309
  if (result) {
2043
- this.emitTransformEvents();
2310
+ emitTransformEvents(this.event, this.canvas);
2044
2311
  }
2045
2312
  return result;
2046
2313
  }
2047
- emitTransformEvents() {
2048
- const transform = this.baseCanvas.transform;
2049
- this.listen.emit("transform", transform);
2050
- this.listen.emit("zoom", transform.scale);
2051
- this.listen.emit("pan", { x: transform.translateX, y: transform.translateY });
2052
- }
2053
2314
  reset() {
2054
- return this.baseCanvas.reset();
2055
- }
2056
- handleResize() {
2057
- return this.baseCanvas.handleResize();
2315
+ const result = resetTransform(this.canvas);
2316
+ if (result) {
2317
+ emitTransformEvents(this.event, this.canvas);
2318
+ }
2319
+ return result;
2058
2320
  }
2059
2321
  setZoom(zoomLevel) {
2060
- return withTransition(this.transformLayer, this.config, () => {
2061
- return withClampedZoom(this.config, (clamp) => {
2062
- const newScale = clamp(zoomLevel);
2063
- const newTransform = {
2064
- scale: newScale,
2065
- };
2066
- return this.updateTransform(newTransform);
2067
- });
2068
- });
2322
+ return setZoom(this, this.transformLayer, this.config, this.zoomToPoint.bind(this), zoomLevel);
2069
2323
  }
2070
2324
  canvasToContent(x, y) {
2071
- return this.baseCanvas.canvasToContent(x, y);
2325
+ const matrix = createMatrix(this.canvas.transform.scale, this.canvas.transform.translateX, this.canvas.transform.translateY);
2326
+ return canvasToContent(x, y, matrix);
2072
2327
  }
2073
2328
  zoomToPoint(x, y, targetScale) {
2074
- return withTransition(this.transformLayer, this.config, () => {
2075
- const result = this.baseCanvas.zoomToPoint(x, y, targetScale);
2076
- if (result) {
2077
- this.emitTransformEvents();
2078
- }
2079
- return result;
2080
- });
2329
+ return zoomToPoint(this.canvas, this.transformLayer, this.config, x, y, targetScale);
2081
2330
  }
2082
2331
  resetView() {
2083
- const result = this.baseCanvas.resetView ? this.baseCanvas.resetView() : false;
2084
- if (result) {
2085
- this.emitTransformEvents();
2086
- }
2087
- return result;
2332
+ return resetView(this.canvas, this.transformLayer, this.config);
2088
2333
  }
2089
2334
  resetViewToCenter() {
2090
- return withTransition(this.transformLayer, this.config, () => {
2091
- return withClampedZoom(this.config, (clamp) => {
2092
- const newScale = clamp(1.0);
2093
- const center = getViewportCenter(this);
2094
- const result = this.zoomToPoint(center.x, center.y, newScale);
2095
- if (result) {
2096
- this.emitTransformEvents();
2097
- }
2098
- return result;
2099
- });
2100
- });
2101
- }
2102
- zoomToFitContent() {
2103
- return withTransition(this.transformLayer, this.config, () => {
2104
- const result = this.baseCanvas.zoomToFitContent();
2105
- if (result) {
2106
- this.emitTransformEvents();
2107
- }
2108
- return result;
2109
- });
2335
+ return resetViewToCenter(this, this.transformLayer, this.config, this.zoomToPoint.bind(this));
2110
2336
  }
2111
- // Pan methods
2112
2337
  panLeft(distance) {
2113
- const panDistance = distance ?? this.config.keyboardPanStep;
2114
- const newTransform = {
2115
- translateX: this.baseCanvas.transform.translateX + panDistance,
2116
- };
2117
- return this.updateTransform(newTransform);
2338
+ return (panLeft(this.canvas, this.config, this.updateTransform.bind(this)) ||
2339
+ (distance ? panLeft(this.canvas, { ...this.config, keyboardPanStep: distance }, this.updateTransform.bind(this)) : false));
2118
2340
  }
2119
2341
  panRight(distance) {
2120
- const panDistance = distance ?? this.config.keyboardPanStep;
2121
- const newTransform = {
2122
- translateX: this.baseCanvas.transform.translateX - panDistance,
2123
- };
2124
- return this.updateTransform(newTransform);
2342
+ return (panRight(this.canvas, this.config, this.updateTransform.bind(this)) ||
2343
+ (distance ? panRight(this.canvas, { ...this.config, keyboardPanStep: distance }, this.updateTransform.bind(this)) : false));
2125
2344
  }
2126
2345
  panUp(distance) {
2127
- const panDistance = distance ?? this.config.keyboardPanStep;
2128
- const newTransform = {
2129
- translateY: this.baseCanvas.transform.translateY + panDistance,
2130
- };
2131
- return this.updateTransform(newTransform);
2346
+ return (panUp(this.canvas, this.config, this.updateTransform.bind(this)) ||
2347
+ (distance ? panUp(this.canvas, { ...this.config, keyboardPanStep: distance }, this.updateTransform.bind(this)) : false));
2132
2348
  }
2133
2349
  panDown(distance) {
2134
- const panDistance = distance ?? this.config.keyboardPanStep;
2135
- const newTransform = {
2136
- translateY: this.baseCanvas.transform.translateY - panDistance,
2137
- };
2138
- return this.updateTransform(newTransform);
2350
+ return (panDown(this.canvas, this.config, this.updateTransform.bind(this)) ||
2351
+ (distance ? panDown(this.canvas, { ...this.config, keyboardPanStep: distance }, this.updateTransform.bind(this)) : false));
2139
2352
  }
2140
- // Zoom methods
2141
2353
  zoomIn(factor = 0.5) {
2142
- return withTransition(this.transformLayer, this.config, () => {
2143
- return withClampedZoom(this.config, (clamp) => {
2144
- const newScale = clamp(this.baseCanvas.transform.scale * (1 + factor));
2145
- // Get the center of the viewport
2146
- const center = getViewportCenter(this);
2147
- return this.zoomToPoint(center.x, center.y, newScale);
2148
- });
2149
- });
2354
+ return zoomIn(this, this.transformLayer, this.config, this.zoomToPoint.bind(this), factor);
2150
2355
  }
2151
2356
  zoomOut(factor = 0.5) {
2152
- return withTransition(this.transformLayer, this.config, () => {
2153
- return withClampedZoom(this.config, (clamp) => {
2154
- const newScale = clamp(this.baseCanvas.transform.scale * (1 - factor));
2155
- // Get the center of the viewport
2156
- const center = getViewportCenter(this);
2157
- return this.zoomToPoint(center.x, center.y, newScale);
2158
- });
2159
- });
2357
+ return zoomOut(this, this.transformLayer, this.config, this.zoomToPoint.bind(this), factor);
2160
2358
  }
2161
2359
  resetZoom() {
2162
2360
  return this.resetViewToCenter();
@@ -2171,110 +2369,68 @@ class MarkupCanvas {
2171
2369
  isMouseDragEnabled() {
2172
2370
  return this.dragSetup?.isEnabled() ?? false;
2173
2371
  }
2174
- // Grid control methods
2175
2372
  toggleGrid() {
2176
- if (this.rulers?.toggleGrid) {
2177
- this.rulers.toggleGrid();
2178
- return true;
2373
+ const result = toggleGrid(this.rulers);
2374
+ if (result) {
2375
+ this.event.emit("gridVisibility", this.isGridVisible());
2179
2376
  }
2180
- return false;
2377
+ return result;
2181
2378
  }
2182
2379
  showGrid() {
2183
- if (this.rulers?.gridOverlay) {
2184
- this.rulers.gridOverlay.style.display = "block";
2185
- return true;
2380
+ const result = showGrid(this.rulers);
2381
+ if (result) {
2382
+ this.event.emit("gridVisibility", true);
2186
2383
  }
2187
- return false;
2384
+ return result;
2188
2385
  }
2189
2386
  hideGrid() {
2190
- if (this.rulers?.gridOverlay) {
2191
- this.rulers.gridOverlay.style.display = "none";
2192
- return true;
2387
+ const result = hideGrid(this.rulers);
2388
+ if (result) {
2389
+ this.event.emit("gridVisibility", false);
2193
2390
  }
2194
- return false;
2391
+ return result;
2195
2392
  }
2196
2393
  isGridVisible() {
2197
- if (this.rulers?.gridOverlay) {
2198
- return this.rulers.gridOverlay.style.display !== "none";
2199
- }
2200
- return false;
2394
+ return isGridVisible(this.rulers);
2201
2395
  }
2202
- // Ruler control methods
2203
2396
  toggleRulers() {
2204
- if (this.rulers) {
2205
- const areVisible = this.areRulersVisible();
2206
- if (areVisible) {
2207
- this.rulers.hide();
2208
- }
2209
- else {
2210
- this.rulers.show();
2211
- }
2212
- return true;
2397
+ const result = toggleRulers(this.rulers, () => this.areRulersVisible());
2398
+ if (result) {
2399
+ this.event.emit("rulersVisibility", this.areRulersVisible());
2213
2400
  }
2214
- return false;
2401
+ return result;
2215
2402
  }
2216
2403
  showRulers() {
2217
- if (this.rulers) {
2218
- this.rulers.show();
2219
- return true;
2404
+ const result = showRulers(this.rulers);
2405
+ if (result) {
2406
+ this.event.emit("rulersVisibility", true);
2220
2407
  }
2221
- return false;
2408
+ return result;
2222
2409
  }
2223
2410
  hideRulers() {
2224
- if (this.rulers) {
2225
- this.rulers.hide();
2226
- return true;
2411
+ const result = hideRulers(this.rulers);
2412
+ if (result) {
2413
+ this.event.emit("rulersVisibility", false);
2227
2414
  }
2228
- return false;
2415
+ return result;
2229
2416
  }
2230
2417
  areRulersVisible() {
2231
- if (this.rulers?.horizontalRuler) {
2232
- return this.rulers.horizontalRuler.style.display !== "none";
2233
- }
2234
- return false;
2418
+ return areRulersVisible(this.rulers);
2235
2419
  }
2236
- // Utility methods
2237
2420
  centerContent() {
2238
- return withTransition(this.transformLayer, this.config, () => {
2239
- const bounds = this.baseCanvas.getBounds();
2240
- const centerX = (bounds.width - bounds.contentWidth * this.baseCanvas.transform.scale) / 2;
2241
- const centerY = (bounds.height - bounds.contentHeight * this.baseCanvas.transform.scale) / 2;
2242
- return this.updateTransform({
2243
- translateX: centerX,
2244
- translateY: centerY,
2245
- });
2246
- });
2421
+ return centerContent(this.canvas, this.config, this.updateTransform.bind(this), this.transformLayer);
2247
2422
  }
2248
2423
  fitToScreen() {
2249
- return withTransition(this.transformLayer, this.config, () => {
2250
- const result = this.baseCanvas.zoomToFitContent();
2251
- if (result) {
2252
- this.emitTransformEvents();
2253
- }
2254
- return result;
2255
- });
2424
+ return fitToScreen(this.canvas, this.transformLayer, this.config);
2256
2425
  }
2257
2426
  getVisibleArea() {
2258
- const bounds = this.baseCanvas.getBounds();
2259
- return bounds.visibleArea;
2427
+ return getVisibleArea(this);
2260
2428
  }
2261
2429
  isPointVisible(x, y) {
2262
- const visibleArea = this.getVisibleArea();
2263
- return x >= visibleArea.x && x <= visibleArea.x + visibleArea.width && y >= visibleArea.y && y <= visibleArea.y + visibleArea.height;
2430
+ return isPointVisible(this, x, y);
2264
2431
  }
2265
2432
  scrollToPoint(x, y) {
2266
- return withTransition(this.transformLayer, this.config, () => {
2267
- const bounds = this.baseCanvas.getBounds();
2268
- const centerX = bounds.width / 2;
2269
- const centerY = bounds.height / 2;
2270
- // Calculate new translation to center the point
2271
- const newTranslateX = centerX - x * this.baseCanvas.transform.scale;
2272
- const newTranslateY = centerY - y * this.baseCanvas.transform.scale;
2273
- return this.updateTransform({
2274
- translateX: newTranslateX,
2275
- translateY: newTranslateY,
2276
- });
2277
- });
2433
+ return scrollToPoint(this.canvas, this.config, x, y, this.updateTransform.bind(this), this.transformLayer);
2278
2434
  }
2279
2435
  // Configuration access
2280
2436
  getConfig() {
@@ -2285,28 +2441,28 @@ class MarkupCanvas {
2285
2441
  }
2286
2442
  // Theme management
2287
2443
  updateThemeMode(mode) {
2288
- const newConfig = {
2289
- ...this.config,
2290
- themeMode: mode,
2291
- };
2292
- this.config = createMarkupCanvasConfig(newConfig);
2293
- // Update canvas background color
2294
- const backgroundColor = getThemeValue(this.config, "canvasBackgroundColor");
2295
- this.baseCanvas.container.style.backgroundColor = backgroundColor;
2296
- // Update rulers if they exist
2297
- if (this.rulers) {
2298
- this.rulers.updateTheme(this.config);
2299
- }
2444
+ this.config = createMarkupCanvasConfig({ ...this.config, themeMode: mode });
2445
+ updateThemeMode(this.canvas.container, this.config, this.rulers, mode);
2446
+ }
2447
+ toggleThemeMode() {
2448
+ const currentMode = this.config.themeMode;
2449
+ const newMode = currentMode === "light" ? "dark" : "light";
2450
+ this.updateThemeMode(newMode);
2451
+ return newMode;
2452
+ }
2453
+ // Transition management
2454
+ updateTransition(enabled) {
2455
+ this.config = createMarkupCanvasConfig({ ...this.config, enableTransition: enabled });
2456
+ }
2457
+ toggleTransitionMode() {
2458
+ const newEnableTransition = toggleTransition(this.config.enableTransition);
2459
+ this.updateTransition(newEnableTransition);
2460
+ return newEnableTransition;
2300
2461
  }
2301
2462
  // Cleanup method
2302
2463
  cleanup() {
2303
- this.cleanupGlobalBinding();
2304
- // Cleanup postMessage listener
2305
- if (this.postMessageCleanup) {
2306
- this.postMessageCleanup();
2307
- this.postMessageCleanup = null;
2308
- }
2309
- this.cleanupFunctions.forEach((cleanup) => {
2464
+ cleanupWindowBinding(this.config);
2465
+ this.cleanupCallbacks.forEach((cleanup) => {
2310
2466
  try {
2311
2467
  cleanup();
2312
2468
  }
@@ -2314,22 +2470,22 @@ class MarkupCanvas {
2314
2470
  console.warn("Error during cleanup:", cleanupError);
2315
2471
  }
2316
2472
  });
2317
- this.cleanupFunctions = [];
2473
+ this.cleanupCallbacks = [];
2318
2474
  // Remove all event listeners
2319
2475
  this.removeAllListeners();
2320
2476
  }
2321
2477
  // Event emitter delegation methods
2322
2478
  on(event, handler) {
2323
- this.listen.on(event, handler);
2479
+ this.event.on(event, handler);
2324
2480
  }
2325
2481
  off(event, handler) {
2326
- this.listen.off(event, handler);
2482
+ this.event.off(event, handler);
2327
2483
  }
2328
2484
  emit(event, data) {
2329
- this.listen.emit(event, data);
2485
+ this.event.emit(event, data);
2330
2486
  }
2331
2487
  removeAllListeners() {
2332
- this.listen.removeAllListeners();
2488
+ this.event.removeAllListeners();
2333
2489
  }
2334
2490
  destroy() {
2335
2491
  this.cleanup();