@markup-canvas/core 1.3.2 → 1.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/MarkupCanvas.d.ts +4 -0
- package/dist/lib/events/keyboard/setupKeyboardEvents.d.ts +3 -1
- package/dist/lib/events/postMessage/processPostMessages.d.ts +3 -0
- package/dist/markup-canvas.cjs.js +153 -72
- package/dist/markup-canvas.esm.js +153 -72
- package/dist/markup-canvas.umd.js +151 -70
- package/dist/markup-canvas.umd.min.js +1 -1
- package/dist/types/window.d.ts +4 -1
- package/package.json +1 -1
- package/src/lib/MarkupCanvas.ts +62 -2
- package/src/lib/config/presets/editor-preset.ts +2 -2
- package/src/lib/events/keyboard/setupKeyboardEvents.ts +25 -1
- package/src/lib/events/postMessage/processPostMessages.ts +113 -0
- package/src/lib/events/postMessage/setupPostMessageEvents.ts +4 -82
- package/src/lib/rulers/createHorizontalRuler.ts +0 -1
- package/src/lib/rulers/createVerticalRuler.ts +0 -1
- package/src/lib/window/bindCanvasToWindow.ts +3 -0
- package/src/types/window.ts +4 -1
- /package/dist/lib/events/postMessage/{sendError.d.ts → sendPostMessageError.d.ts} +0 -0
- /package/src/lib/events/postMessage/{sendError.ts → sendPostMessageError.ts} +0 -0
|
@@ -11,6 +11,7 @@ export declare class MarkupCanvas {
|
|
|
11
11
|
private rulers;
|
|
12
12
|
private dragSetup;
|
|
13
13
|
private keyboardCleanup;
|
|
14
|
+
private textEditModeEnabled;
|
|
14
15
|
config: Required<MarkupCanvasConfig>;
|
|
15
16
|
event: EventEmitter<MarkupCanvasEvents>;
|
|
16
17
|
private _isReady;
|
|
@@ -52,6 +53,9 @@ export declare class MarkupCanvas {
|
|
|
52
53
|
enableKeyboard(): boolean;
|
|
53
54
|
disableKeyboard(): boolean;
|
|
54
55
|
isKeyboardEnabled(): boolean;
|
|
56
|
+
enableTextEditMode(): boolean;
|
|
57
|
+
disableTextEditMode(): boolean;
|
|
58
|
+
isTextEditModeEnabled(): boolean;
|
|
55
59
|
toggleGrid(): boolean;
|
|
56
60
|
showGrid(): boolean;
|
|
57
61
|
hideGrid(): boolean;
|
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
import type { MarkupCanvas } from "@/lib/MarkupCanvas.js";
|
|
2
2
|
import type { MarkupCanvasConfig } from "@/types/index.js";
|
|
3
|
-
export declare function setupKeyboardEvents(canvas: MarkupCanvas, config: Required<MarkupCanvasConfig
|
|
3
|
+
export declare function setupKeyboardEvents(canvas: MarkupCanvas, config: Required<MarkupCanvasConfig>, options?: {
|
|
4
|
+
textEditModeEnabled?: boolean;
|
|
5
|
+
}): () => void;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { MarkupCanvas } from "@/lib/MarkupCanvas.js";
|
|
2
|
+
import type { PostMessageAction } from "@/types/events";
|
|
3
|
+
export declare function processPostMessage(canvas: MarkupCanvas, action: PostMessageAction, payload: string | number | boolean | object, canvasName: string): void;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Markup Canvas
|
|
3
3
|
* High-performance markup canvas with zoom and pan capabilities
|
|
4
|
-
* @version 1.3.
|
|
4
|
+
* @version 1.3.4
|
|
5
5
|
*/
|
|
6
6
|
'use strict';
|
|
7
7
|
|
|
@@ -22,7 +22,7 @@ const EDITOR_PRESET = {
|
|
|
22
22
|
enableKeyboard: true,
|
|
23
23
|
bindKeyboardEventsTo: "document",
|
|
24
24
|
// Zoom behavior
|
|
25
|
-
zoomSpeed:
|
|
25
|
+
zoomSpeed: 4,
|
|
26
26
|
minZoom: 0.05,
|
|
27
27
|
maxZoom: 80,
|
|
28
28
|
enableTransition: false,
|
|
@@ -54,7 +54,7 @@ const EDITOR_PRESET = {
|
|
|
54
54
|
canvasBackgroundColorDark: "transparent",
|
|
55
55
|
// Ruler styling
|
|
56
56
|
rulerBackgroundColor: "oklch(100% 0 0 / 0.96)",
|
|
57
|
-
rulerBorderColor: "oklch(
|
|
57
|
+
rulerBorderColor: "oklch(0.322 0.0095 285.919)",
|
|
58
58
|
rulerTextColor: "oklch(70.5% 0.015 286.067)",
|
|
59
59
|
rulerTickColor: "oklch(92% 0.004 286.32)",
|
|
60
60
|
gridColor: "rgba(232, 86, 193, 0.5)",
|
|
@@ -948,7 +948,8 @@ function getAdaptiveZoomSpeed(canvas, baseSpeed) {
|
|
|
948
948
|
}
|
|
949
949
|
}
|
|
950
950
|
|
|
951
|
-
function setupKeyboardEvents(canvas, config) {
|
|
951
|
+
function setupKeyboardEvents(canvas, config, options) {
|
|
952
|
+
const textEditModeEnabled = options?.textEditModeEnabled ?? false;
|
|
952
953
|
function handleKeyDown(event) {
|
|
953
954
|
if (!(event instanceof KeyboardEvent))
|
|
954
955
|
return;
|
|
@@ -958,23 +959,38 @@ function setupKeyboardEvents(canvas, config) {
|
|
|
958
959
|
const newTransform = {};
|
|
959
960
|
switch (event.key) {
|
|
960
961
|
case "ArrowLeft":
|
|
962
|
+
if (textEditModeEnabled) {
|
|
963
|
+
return;
|
|
964
|
+
}
|
|
961
965
|
newTransform.translateX = canvas.transform.translateX + config.keyboardPanStep;
|
|
962
966
|
handled = true;
|
|
963
967
|
break;
|
|
964
968
|
case "ArrowRight":
|
|
969
|
+
if (textEditModeEnabled) {
|
|
970
|
+
return;
|
|
971
|
+
}
|
|
965
972
|
newTransform.translateX = canvas.transform.translateX - config.keyboardPanStep;
|
|
966
973
|
handled = true;
|
|
967
974
|
break;
|
|
968
975
|
case "ArrowUp":
|
|
976
|
+
if (textEditModeEnabled) {
|
|
977
|
+
return;
|
|
978
|
+
}
|
|
969
979
|
newTransform.translateY = canvas.transform.translateY + config.keyboardPanStep;
|
|
970
980
|
handled = true;
|
|
971
981
|
break;
|
|
972
982
|
case "ArrowDown":
|
|
983
|
+
if (textEditModeEnabled) {
|
|
984
|
+
return;
|
|
985
|
+
}
|
|
973
986
|
newTransform.translateY = canvas.transform.translateY - config.keyboardPanStep;
|
|
974
987
|
handled = true;
|
|
975
988
|
break;
|
|
976
989
|
case "=":
|
|
977
990
|
case "+":
|
|
991
|
+
if (textEditModeEnabled) {
|
|
992
|
+
return;
|
|
993
|
+
}
|
|
978
994
|
{
|
|
979
995
|
const adaptiveZoomStep = config.enableAdaptiveSpeed
|
|
980
996
|
? getAdaptiveZoomSpeed(canvas, config.keyboardZoomStep)
|
|
@@ -984,6 +1000,9 @@ function setupKeyboardEvents(canvas, config) {
|
|
|
984
1000
|
}
|
|
985
1001
|
break;
|
|
986
1002
|
case "-":
|
|
1003
|
+
if (textEditModeEnabled) {
|
|
1004
|
+
return;
|
|
1005
|
+
}
|
|
987
1006
|
{
|
|
988
1007
|
const adaptiveZoomStep = config.enableAdaptiveSpeed
|
|
989
1008
|
? getAdaptiveZoomSpeed(canvas, config.keyboardZoomStep)
|
|
@@ -1330,117 +1349,125 @@ function sendPostMessageError(canvasName, action, error) {
|
|
|
1330
1349
|
}, "*");
|
|
1331
1350
|
}
|
|
1332
1351
|
|
|
1333
|
-
function
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
}
|
|
1339
|
-
console.log("data", event.data);
|
|
1340
|
-
const canvasName = canvas.config.name || "markupCanvas";
|
|
1341
|
-
if (data.canvasName !== canvasName) {
|
|
1342
|
-
console.log("canvasName", data.canvasName, "!==", canvasName);
|
|
1343
|
-
return;
|
|
1344
|
-
}
|
|
1345
|
-
const action = data.action;
|
|
1346
|
-
const payload = data.data;
|
|
1347
|
-
try {
|
|
1348
|
-
// View methods
|
|
1349
|
-
if (action === "zoomIn") {
|
|
1350
|
-
console.log("zoomIn", payload);
|
|
1352
|
+
function processPostMessage(canvas, action, payload, canvasName) {
|
|
1353
|
+
try {
|
|
1354
|
+
// View methods
|
|
1355
|
+
switch (action) {
|
|
1356
|
+
case "zoomIn":
|
|
1351
1357
|
canvas.zoomIn(payload);
|
|
1352
|
-
|
|
1353
|
-
|
|
1358
|
+
break;
|
|
1359
|
+
case "zoomOut":
|
|
1354
1360
|
canvas.zoomOut(payload);
|
|
1355
|
-
|
|
1356
|
-
|
|
1361
|
+
break;
|
|
1362
|
+
case "setZoom": {
|
|
1357
1363
|
const zoomLevel = payload;
|
|
1358
1364
|
if (typeof zoomLevel !== "number" || zoomLevel <= 0) {
|
|
1359
1365
|
throw new Error(`Invalid zoom level: ${zoomLevel}. Must be a positive number.`);
|
|
1360
1366
|
}
|
|
1361
1367
|
canvas.setZoom(zoomLevel);
|
|
1368
|
+
break;
|
|
1362
1369
|
}
|
|
1363
|
-
|
|
1370
|
+
case "resetZoom":
|
|
1364
1371
|
canvas.resetZoom();
|
|
1365
|
-
|
|
1366
|
-
|
|
1372
|
+
break;
|
|
1373
|
+
case "panLeft":
|
|
1367
1374
|
canvas.panLeft(payload);
|
|
1368
|
-
|
|
1369
|
-
|
|
1375
|
+
break;
|
|
1376
|
+
case "panRight":
|
|
1370
1377
|
canvas.panRight(payload);
|
|
1371
|
-
|
|
1372
|
-
|
|
1378
|
+
break;
|
|
1379
|
+
case "panUp":
|
|
1373
1380
|
canvas.panUp(payload);
|
|
1374
|
-
|
|
1375
|
-
|
|
1381
|
+
break;
|
|
1382
|
+
case "panDown":
|
|
1376
1383
|
canvas.panDown(payload);
|
|
1377
|
-
|
|
1378
|
-
|
|
1384
|
+
break;
|
|
1385
|
+
case "fitToScreen":
|
|
1379
1386
|
canvas.fitToScreen();
|
|
1380
|
-
|
|
1381
|
-
|
|
1387
|
+
break;
|
|
1388
|
+
case "centerContent":
|
|
1382
1389
|
canvas.centerContent();
|
|
1390
|
+
break;
|
|
1391
|
+
case "panToPoint": {
|
|
1392
|
+
const point = payload;
|
|
1393
|
+
canvas.panToPoint(point.x, point.y);
|
|
1394
|
+
break;
|
|
1383
1395
|
}
|
|
1384
|
-
|
|
1385
|
-
canvas.panToPoint(payload.x, payload.y);
|
|
1386
|
-
}
|
|
1387
|
-
else if (action === "resetView") {
|
|
1396
|
+
case "resetView":
|
|
1388
1397
|
canvas.resetView();
|
|
1389
|
-
|
|
1390
|
-
|
|
1398
|
+
break;
|
|
1399
|
+
case "resetViewToCenter":
|
|
1391
1400
|
canvas.resetViewToCenter();
|
|
1392
|
-
|
|
1401
|
+
break;
|
|
1393
1402
|
// Ruler/Grid methods
|
|
1394
|
-
|
|
1403
|
+
case "toggleRulers":
|
|
1395
1404
|
canvas.toggleRulers();
|
|
1396
|
-
|
|
1397
|
-
|
|
1405
|
+
break;
|
|
1406
|
+
case "showRulers":
|
|
1398
1407
|
canvas.showRulers();
|
|
1399
|
-
|
|
1400
|
-
|
|
1408
|
+
break;
|
|
1409
|
+
case "hideRulers":
|
|
1401
1410
|
canvas.hideRulers();
|
|
1402
|
-
|
|
1403
|
-
|
|
1411
|
+
break;
|
|
1412
|
+
case "toggleGrid":
|
|
1404
1413
|
canvas.toggleGrid();
|
|
1405
|
-
|
|
1406
|
-
|
|
1414
|
+
break;
|
|
1415
|
+
case "showGrid":
|
|
1407
1416
|
canvas.showGrid();
|
|
1408
|
-
|
|
1409
|
-
|
|
1417
|
+
break;
|
|
1418
|
+
case "hideGrid":
|
|
1410
1419
|
canvas.hideGrid();
|
|
1411
|
-
|
|
1420
|
+
break;
|
|
1412
1421
|
// Config methods
|
|
1413
|
-
|
|
1422
|
+
case "updateThemeMode": {
|
|
1414
1423
|
const mode = payload;
|
|
1415
1424
|
if (mode !== "light" && mode !== "dark") {
|
|
1416
1425
|
throw new Error(`Invalid theme mode: ${mode}`);
|
|
1417
1426
|
}
|
|
1418
1427
|
canvas.updateThemeMode(mode);
|
|
1428
|
+
break;
|
|
1419
1429
|
}
|
|
1420
|
-
|
|
1430
|
+
case "toggleThemeMode": {
|
|
1421
1431
|
const currentConfig = canvas.getConfig();
|
|
1422
1432
|
const newMode = currentConfig.themeMode === "light" ? "dark" : "light";
|
|
1423
1433
|
canvas.updateThemeMode(newMode);
|
|
1434
|
+
break;
|
|
1424
1435
|
}
|
|
1425
1436
|
// Transition methods
|
|
1426
|
-
|
|
1437
|
+
case "updateTransition": {
|
|
1427
1438
|
const enabled = payload;
|
|
1428
1439
|
if (typeof enabled !== "boolean") {
|
|
1429
1440
|
throw new Error(`Invalid transition enabled value: ${enabled}. Must be a boolean.`);
|
|
1430
1441
|
}
|
|
1431
1442
|
canvas.updateTransition(enabled);
|
|
1443
|
+
break;
|
|
1432
1444
|
}
|
|
1433
|
-
|
|
1445
|
+
case "toggleTransitionMode":
|
|
1434
1446
|
canvas.toggleTransitionMode();
|
|
1435
|
-
|
|
1436
|
-
|
|
1447
|
+
break;
|
|
1448
|
+
default:
|
|
1437
1449
|
throw new Error(`Unknown action: ${action}`);
|
|
1438
|
-
}
|
|
1439
1450
|
}
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1451
|
+
}
|
|
1452
|
+
catch (error) {
|
|
1453
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1454
|
+
sendPostMessageError(canvasName, action, errorMessage);
|
|
1455
|
+
}
|
|
1456
|
+
}
|
|
1457
|
+
|
|
1458
|
+
function setupPostMessageEvents(canvas) {
|
|
1459
|
+
const handleMessage = (event) => {
|
|
1460
|
+
const data = event.data;
|
|
1461
|
+
if (!["markup-canvas", "application"].includes(data.source)) {
|
|
1462
|
+
return;
|
|
1443
1463
|
}
|
|
1464
|
+
const canvasName = canvas.config.name || "markupCanvas";
|
|
1465
|
+
if (data.canvasName !== canvasName) {
|
|
1466
|
+
return;
|
|
1467
|
+
}
|
|
1468
|
+
const action = data.action;
|
|
1469
|
+
const payload = data.data;
|
|
1470
|
+
processPostMessage(canvas, action, payload, canvasName);
|
|
1444
1471
|
};
|
|
1445
1472
|
if (typeof window !== "undefined") {
|
|
1446
1473
|
window.addEventListener("message", handleMessage);
|
|
@@ -1741,7 +1768,6 @@ function createHorizontalRuler(config) {
|
|
|
1741
1768
|
height: ${config.rulerSize}px;
|
|
1742
1769
|
background: var(--ruler-background-color);
|
|
1743
1770
|
border-bottom: 1px solid var(--ruler-border-color);
|
|
1744
|
-
border-right: 1px solid var(--ruler-border-color);
|
|
1745
1771
|
z-index: ${RULER_Z_INDEX.RULERS};
|
|
1746
1772
|
pointer-events: none;
|
|
1747
1773
|
font-family: ${config.rulerFontFamily};
|
|
@@ -1763,7 +1789,6 @@ function createVerticalRuler(config) {
|
|
|
1763
1789
|
width: ${config.rulerSize}px;
|
|
1764
1790
|
background: var(--ruler-background-color);
|
|
1765
1791
|
border-right: 1px solid var(--ruler-border-color);
|
|
1766
|
-
border-bottom: 1px solid var(--ruler-border-color);
|
|
1767
1792
|
z-index: ${RULER_Z_INDEX.RULERS};
|
|
1768
1793
|
pointer-events: none;
|
|
1769
1794
|
font-family: ${config.rulerFontFamily};
|
|
@@ -2165,6 +2190,9 @@ function bindCanvasToWindow(canvas, config) {
|
|
|
2165
2190
|
enable: canvas.enableKeyboard.bind(canvas),
|
|
2166
2191
|
disable: canvas.disableKeyboard.bind(canvas),
|
|
2167
2192
|
isEnabled: canvas.isKeyboardEnabled.bind(canvas),
|
|
2193
|
+
enableTextEditMode: canvas.enableTextEditMode.bind(canvas),
|
|
2194
|
+
disableTextEditMode: canvas.disableTextEditMode.bind(canvas),
|
|
2195
|
+
isTextEditModeEnabled: canvas.isTextEditModeEnabled.bind(canvas),
|
|
2168
2196
|
},
|
|
2169
2197
|
// Grid group
|
|
2170
2198
|
grid: {
|
|
@@ -2239,6 +2267,7 @@ class MarkupCanvas {
|
|
|
2239
2267
|
this.rulers = null;
|
|
2240
2268
|
this.dragSetup = null;
|
|
2241
2269
|
this.keyboardCleanup = null;
|
|
2270
|
+
this.textEditModeEnabled = false;
|
|
2242
2271
|
this.event = new EventEmitter();
|
|
2243
2272
|
this._isReady = false;
|
|
2244
2273
|
if (!container) {
|
|
@@ -2290,7 +2319,9 @@ class MarkupCanvas {
|
|
|
2290
2319
|
}
|
|
2291
2320
|
// Keyboard events
|
|
2292
2321
|
withFeatureEnabled(this.config, "enableKeyboard", () => {
|
|
2293
|
-
const keyboardCleanup = setupKeyboardEvents(this, this.config
|
|
2322
|
+
const keyboardCleanup = setupKeyboardEvents(this, this.config, {
|
|
2323
|
+
textEditModeEnabled: this.textEditModeEnabled,
|
|
2324
|
+
});
|
|
2294
2325
|
this.keyboardCleanup = keyboardCleanup;
|
|
2295
2326
|
this.cleanupCallbacks.push(keyboardCleanup);
|
|
2296
2327
|
});
|
|
@@ -2404,7 +2435,9 @@ class MarkupCanvas {
|
|
|
2404
2435
|
if (this.keyboardCleanup) {
|
|
2405
2436
|
return true; // Already enabled
|
|
2406
2437
|
}
|
|
2407
|
-
this.keyboardCleanup = setupKeyboardEvents(this, this.config
|
|
2438
|
+
this.keyboardCleanup = setupKeyboardEvents(this, this.config, {
|
|
2439
|
+
textEditModeEnabled: this.textEditModeEnabled,
|
|
2440
|
+
});
|
|
2408
2441
|
this.cleanupCallbacks.push(this.keyboardCleanup);
|
|
2409
2442
|
return true;
|
|
2410
2443
|
}
|
|
@@ -2419,6 +2452,54 @@ class MarkupCanvas {
|
|
|
2419
2452
|
isKeyboardEnabled() {
|
|
2420
2453
|
return this.keyboardCleanup !== null;
|
|
2421
2454
|
}
|
|
2455
|
+
// Text edit mode control methods
|
|
2456
|
+
enableTextEditMode() {
|
|
2457
|
+
if (this.textEditModeEnabled) {
|
|
2458
|
+
return true; // Already enabled
|
|
2459
|
+
}
|
|
2460
|
+
this.textEditModeEnabled = true;
|
|
2461
|
+
// If keyboard is currently enabled, re-setup with new option
|
|
2462
|
+
if (this.keyboardCleanup) {
|
|
2463
|
+
// Remove old cleanup from callbacks
|
|
2464
|
+
const index = this.cleanupCallbacks.indexOf(this.keyboardCleanup);
|
|
2465
|
+
if (index > -1) {
|
|
2466
|
+
this.cleanupCallbacks.splice(index, 1);
|
|
2467
|
+
}
|
|
2468
|
+
// Cleanup old handler
|
|
2469
|
+
this.keyboardCleanup();
|
|
2470
|
+
// Setup new handler with text edit mode enabled
|
|
2471
|
+
this.keyboardCleanup = setupKeyboardEvents(this, this.config, {
|
|
2472
|
+
textEditModeEnabled: true,
|
|
2473
|
+
});
|
|
2474
|
+
this.cleanupCallbacks.push(this.keyboardCleanup);
|
|
2475
|
+
}
|
|
2476
|
+
return true;
|
|
2477
|
+
}
|
|
2478
|
+
disableTextEditMode() {
|
|
2479
|
+
if (!this.textEditModeEnabled) {
|
|
2480
|
+
return true; // Already disabled
|
|
2481
|
+
}
|
|
2482
|
+
this.textEditModeEnabled = false;
|
|
2483
|
+
// If keyboard is currently enabled, re-setup with new option
|
|
2484
|
+
if (this.keyboardCleanup) {
|
|
2485
|
+
// Remove old cleanup from callbacks
|
|
2486
|
+
const index = this.cleanupCallbacks.indexOf(this.keyboardCleanup);
|
|
2487
|
+
if (index > -1) {
|
|
2488
|
+
this.cleanupCallbacks.splice(index, 1);
|
|
2489
|
+
}
|
|
2490
|
+
// Cleanup old handler
|
|
2491
|
+
this.keyboardCleanup();
|
|
2492
|
+
// Setup new handler with text edit mode disabled
|
|
2493
|
+
this.keyboardCleanup = setupKeyboardEvents(this, this.config, {
|
|
2494
|
+
textEditModeEnabled: false,
|
|
2495
|
+
});
|
|
2496
|
+
this.cleanupCallbacks.push(this.keyboardCleanup);
|
|
2497
|
+
}
|
|
2498
|
+
return true;
|
|
2499
|
+
}
|
|
2500
|
+
isTextEditModeEnabled() {
|
|
2501
|
+
return this.textEditModeEnabled;
|
|
2502
|
+
}
|
|
2422
2503
|
toggleGrid() {
|
|
2423
2504
|
const result = toggleGrid(this.rulers);
|
|
2424
2505
|
if (result) {
|