@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
|
@@ -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
|
const EDITOR_PRESET = {
|
|
7
7
|
// Canvas dimensions
|
|
@@ -18,7 +18,7 @@ const EDITOR_PRESET = {
|
|
|
18
18
|
enableKeyboard: true,
|
|
19
19
|
bindKeyboardEventsTo: "document",
|
|
20
20
|
// Zoom behavior
|
|
21
|
-
zoomSpeed:
|
|
21
|
+
zoomSpeed: 4,
|
|
22
22
|
minZoom: 0.05,
|
|
23
23
|
maxZoom: 80,
|
|
24
24
|
enableTransition: false,
|
|
@@ -50,7 +50,7 @@ const EDITOR_PRESET = {
|
|
|
50
50
|
canvasBackgroundColorDark: "transparent",
|
|
51
51
|
// Ruler styling
|
|
52
52
|
rulerBackgroundColor: "oklch(100% 0 0 / 0.96)",
|
|
53
|
-
rulerBorderColor: "oklch(
|
|
53
|
+
rulerBorderColor: "oklch(0.322 0.0095 285.919)",
|
|
54
54
|
rulerTextColor: "oklch(70.5% 0.015 286.067)",
|
|
55
55
|
rulerTickColor: "oklch(92% 0.004 286.32)",
|
|
56
56
|
gridColor: "rgba(232, 86, 193, 0.5)",
|
|
@@ -944,7 +944,8 @@ function getAdaptiveZoomSpeed(canvas, baseSpeed) {
|
|
|
944
944
|
}
|
|
945
945
|
}
|
|
946
946
|
|
|
947
|
-
function setupKeyboardEvents(canvas, config) {
|
|
947
|
+
function setupKeyboardEvents(canvas, config, options) {
|
|
948
|
+
const textEditModeEnabled = options?.textEditModeEnabled ?? false;
|
|
948
949
|
function handleKeyDown(event) {
|
|
949
950
|
if (!(event instanceof KeyboardEvent))
|
|
950
951
|
return;
|
|
@@ -954,23 +955,38 @@ function setupKeyboardEvents(canvas, config) {
|
|
|
954
955
|
const newTransform = {};
|
|
955
956
|
switch (event.key) {
|
|
956
957
|
case "ArrowLeft":
|
|
958
|
+
if (textEditModeEnabled) {
|
|
959
|
+
return;
|
|
960
|
+
}
|
|
957
961
|
newTransform.translateX = canvas.transform.translateX + config.keyboardPanStep;
|
|
958
962
|
handled = true;
|
|
959
963
|
break;
|
|
960
964
|
case "ArrowRight":
|
|
965
|
+
if (textEditModeEnabled) {
|
|
966
|
+
return;
|
|
967
|
+
}
|
|
961
968
|
newTransform.translateX = canvas.transform.translateX - config.keyboardPanStep;
|
|
962
969
|
handled = true;
|
|
963
970
|
break;
|
|
964
971
|
case "ArrowUp":
|
|
972
|
+
if (textEditModeEnabled) {
|
|
973
|
+
return;
|
|
974
|
+
}
|
|
965
975
|
newTransform.translateY = canvas.transform.translateY + config.keyboardPanStep;
|
|
966
976
|
handled = true;
|
|
967
977
|
break;
|
|
968
978
|
case "ArrowDown":
|
|
979
|
+
if (textEditModeEnabled) {
|
|
980
|
+
return;
|
|
981
|
+
}
|
|
969
982
|
newTransform.translateY = canvas.transform.translateY - config.keyboardPanStep;
|
|
970
983
|
handled = true;
|
|
971
984
|
break;
|
|
972
985
|
case "=":
|
|
973
986
|
case "+":
|
|
987
|
+
if (textEditModeEnabled) {
|
|
988
|
+
return;
|
|
989
|
+
}
|
|
974
990
|
{
|
|
975
991
|
const adaptiveZoomStep = config.enableAdaptiveSpeed
|
|
976
992
|
? getAdaptiveZoomSpeed(canvas, config.keyboardZoomStep)
|
|
@@ -980,6 +996,9 @@ function setupKeyboardEvents(canvas, config) {
|
|
|
980
996
|
}
|
|
981
997
|
break;
|
|
982
998
|
case "-":
|
|
999
|
+
if (textEditModeEnabled) {
|
|
1000
|
+
return;
|
|
1001
|
+
}
|
|
983
1002
|
{
|
|
984
1003
|
const adaptiveZoomStep = config.enableAdaptiveSpeed
|
|
985
1004
|
? getAdaptiveZoomSpeed(canvas, config.keyboardZoomStep)
|
|
@@ -1326,117 +1345,125 @@ function sendPostMessageError(canvasName, action, error) {
|
|
|
1326
1345
|
}, "*");
|
|
1327
1346
|
}
|
|
1328
1347
|
|
|
1329
|
-
function
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
}
|
|
1335
|
-
console.log("data", event.data);
|
|
1336
|
-
const canvasName = canvas.config.name || "markupCanvas";
|
|
1337
|
-
if (data.canvasName !== canvasName) {
|
|
1338
|
-
console.log("canvasName", data.canvasName, "!==", canvasName);
|
|
1339
|
-
return;
|
|
1340
|
-
}
|
|
1341
|
-
const action = data.action;
|
|
1342
|
-
const payload = data.data;
|
|
1343
|
-
try {
|
|
1344
|
-
// View methods
|
|
1345
|
-
if (action === "zoomIn") {
|
|
1346
|
-
console.log("zoomIn", payload);
|
|
1348
|
+
function processPostMessage(canvas, action, payload, canvasName) {
|
|
1349
|
+
try {
|
|
1350
|
+
// View methods
|
|
1351
|
+
switch (action) {
|
|
1352
|
+
case "zoomIn":
|
|
1347
1353
|
canvas.zoomIn(payload);
|
|
1348
|
-
|
|
1349
|
-
|
|
1354
|
+
break;
|
|
1355
|
+
case "zoomOut":
|
|
1350
1356
|
canvas.zoomOut(payload);
|
|
1351
|
-
|
|
1352
|
-
|
|
1357
|
+
break;
|
|
1358
|
+
case "setZoom": {
|
|
1353
1359
|
const zoomLevel = payload;
|
|
1354
1360
|
if (typeof zoomLevel !== "number" || zoomLevel <= 0) {
|
|
1355
1361
|
throw new Error(`Invalid zoom level: ${zoomLevel}. Must be a positive number.`);
|
|
1356
1362
|
}
|
|
1357
1363
|
canvas.setZoom(zoomLevel);
|
|
1364
|
+
break;
|
|
1358
1365
|
}
|
|
1359
|
-
|
|
1366
|
+
case "resetZoom":
|
|
1360
1367
|
canvas.resetZoom();
|
|
1361
|
-
|
|
1362
|
-
|
|
1368
|
+
break;
|
|
1369
|
+
case "panLeft":
|
|
1363
1370
|
canvas.panLeft(payload);
|
|
1364
|
-
|
|
1365
|
-
|
|
1371
|
+
break;
|
|
1372
|
+
case "panRight":
|
|
1366
1373
|
canvas.panRight(payload);
|
|
1367
|
-
|
|
1368
|
-
|
|
1374
|
+
break;
|
|
1375
|
+
case "panUp":
|
|
1369
1376
|
canvas.panUp(payload);
|
|
1370
|
-
|
|
1371
|
-
|
|
1377
|
+
break;
|
|
1378
|
+
case "panDown":
|
|
1372
1379
|
canvas.panDown(payload);
|
|
1373
|
-
|
|
1374
|
-
|
|
1380
|
+
break;
|
|
1381
|
+
case "fitToScreen":
|
|
1375
1382
|
canvas.fitToScreen();
|
|
1376
|
-
|
|
1377
|
-
|
|
1383
|
+
break;
|
|
1384
|
+
case "centerContent":
|
|
1378
1385
|
canvas.centerContent();
|
|
1386
|
+
break;
|
|
1387
|
+
case "panToPoint": {
|
|
1388
|
+
const point = payload;
|
|
1389
|
+
canvas.panToPoint(point.x, point.y);
|
|
1390
|
+
break;
|
|
1379
1391
|
}
|
|
1380
|
-
|
|
1381
|
-
canvas.panToPoint(payload.x, payload.y);
|
|
1382
|
-
}
|
|
1383
|
-
else if (action === "resetView") {
|
|
1392
|
+
case "resetView":
|
|
1384
1393
|
canvas.resetView();
|
|
1385
|
-
|
|
1386
|
-
|
|
1394
|
+
break;
|
|
1395
|
+
case "resetViewToCenter":
|
|
1387
1396
|
canvas.resetViewToCenter();
|
|
1388
|
-
|
|
1397
|
+
break;
|
|
1389
1398
|
// Ruler/Grid methods
|
|
1390
|
-
|
|
1399
|
+
case "toggleRulers":
|
|
1391
1400
|
canvas.toggleRulers();
|
|
1392
|
-
|
|
1393
|
-
|
|
1401
|
+
break;
|
|
1402
|
+
case "showRulers":
|
|
1394
1403
|
canvas.showRulers();
|
|
1395
|
-
|
|
1396
|
-
|
|
1404
|
+
break;
|
|
1405
|
+
case "hideRulers":
|
|
1397
1406
|
canvas.hideRulers();
|
|
1398
|
-
|
|
1399
|
-
|
|
1407
|
+
break;
|
|
1408
|
+
case "toggleGrid":
|
|
1400
1409
|
canvas.toggleGrid();
|
|
1401
|
-
|
|
1402
|
-
|
|
1410
|
+
break;
|
|
1411
|
+
case "showGrid":
|
|
1403
1412
|
canvas.showGrid();
|
|
1404
|
-
|
|
1405
|
-
|
|
1413
|
+
break;
|
|
1414
|
+
case "hideGrid":
|
|
1406
1415
|
canvas.hideGrid();
|
|
1407
|
-
|
|
1416
|
+
break;
|
|
1408
1417
|
// Config methods
|
|
1409
|
-
|
|
1418
|
+
case "updateThemeMode": {
|
|
1410
1419
|
const mode = payload;
|
|
1411
1420
|
if (mode !== "light" && mode !== "dark") {
|
|
1412
1421
|
throw new Error(`Invalid theme mode: ${mode}`);
|
|
1413
1422
|
}
|
|
1414
1423
|
canvas.updateThemeMode(mode);
|
|
1424
|
+
break;
|
|
1415
1425
|
}
|
|
1416
|
-
|
|
1426
|
+
case "toggleThemeMode": {
|
|
1417
1427
|
const currentConfig = canvas.getConfig();
|
|
1418
1428
|
const newMode = currentConfig.themeMode === "light" ? "dark" : "light";
|
|
1419
1429
|
canvas.updateThemeMode(newMode);
|
|
1430
|
+
break;
|
|
1420
1431
|
}
|
|
1421
1432
|
// Transition methods
|
|
1422
|
-
|
|
1433
|
+
case "updateTransition": {
|
|
1423
1434
|
const enabled = payload;
|
|
1424
1435
|
if (typeof enabled !== "boolean") {
|
|
1425
1436
|
throw new Error(`Invalid transition enabled value: ${enabled}. Must be a boolean.`);
|
|
1426
1437
|
}
|
|
1427
1438
|
canvas.updateTransition(enabled);
|
|
1439
|
+
break;
|
|
1428
1440
|
}
|
|
1429
|
-
|
|
1441
|
+
case "toggleTransitionMode":
|
|
1430
1442
|
canvas.toggleTransitionMode();
|
|
1431
|
-
|
|
1432
|
-
|
|
1443
|
+
break;
|
|
1444
|
+
default:
|
|
1433
1445
|
throw new Error(`Unknown action: ${action}`);
|
|
1434
|
-
}
|
|
1435
1446
|
}
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1447
|
+
}
|
|
1448
|
+
catch (error) {
|
|
1449
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1450
|
+
sendPostMessageError(canvasName, action, errorMessage);
|
|
1451
|
+
}
|
|
1452
|
+
}
|
|
1453
|
+
|
|
1454
|
+
function setupPostMessageEvents(canvas) {
|
|
1455
|
+
const handleMessage = (event) => {
|
|
1456
|
+
const data = event.data;
|
|
1457
|
+
if (!["markup-canvas", "application"].includes(data.source)) {
|
|
1458
|
+
return;
|
|
1439
1459
|
}
|
|
1460
|
+
const canvasName = canvas.config.name || "markupCanvas";
|
|
1461
|
+
if (data.canvasName !== canvasName) {
|
|
1462
|
+
return;
|
|
1463
|
+
}
|
|
1464
|
+
const action = data.action;
|
|
1465
|
+
const payload = data.data;
|
|
1466
|
+
processPostMessage(canvas, action, payload, canvasName);
|
|
1440
1467
|
};
|
|
1441
1468
|
if (typeof window !== "undefined") {
|
|
1442
1469
|
window.addEventListener("message", handleMessage);
|
|
@@ -1737,7 +1764,6 @@ function createHorizontalRuler(config) {
|
|
|
1737
1764
|
height: ${config.rulerSize}px;
|
|
1738
1765
|
background: var(--ruler-background-color);
|
|
1739
1766
|
border-bottom: 1px solid var(--ruler-border-color);
|
|
1740
|
-
border-right: 1px solid var(--ruler-border-color);
|
|
1741
1767
|
z-index: ${RULER_Z_INDEX.RULERS};
|
|
1742
1768
|
pointer-events: none;
|
|
1743
1769
|
font-family: ${config.rulerFontFamily};
|
|
@@ -1759,7 +1785,6 @@ function createVerticalRuler(config) {
|
|
|
1759
1785
|
width: ${config.rulerSize}px;
|
|
1760
1786
|
background: var(--ruler-background-color);
|
|
1761
1787
|
border-right: 1px solid var(--ruler-border-color);
|
|
1762
|
-
border-bottom: 1px solid var(--ruler-border-color);
|
|
1763
1788
|
z-index: ${RULER_Z_INDEX.RULERS};
|
|
1764
1789
|
pointer-events: none;
|
|
1765
1790
|
font-family: ${config.rulerFontFamily};
|
|
@@ -2161,6 +2186,9 @@ function bindCanvasToWindow(canvas, config) {
|
|
|
2161
2186
|
enable: canvas.enableKeyboard.bind(canvas),
|
|
2162
2187
|
disable: canvas.disableKeyboard.bind(canvas),
|
|
2163
2188
|
isEnabled: canvas.isKeyboardEnabled.bind(canvas),
|
|
2189
|
+
enableTextEditMode: canvas.enableTextEditMode.bind(canvas),
|
|
2190
|
+
disableTextEditMode: canvas.disableTextEditMode.bind(canvas),
|
|
2191
|
+
isTextEditModeEnabled: canvas.isTextEditModeEnabled.bind(canvas),
|
|
2164
2192
|
},
|
|
2165
2193
|
// Grid group
|
|
2166
2194
|
grid: {
|
|
@@ -2235,6 +2263,7 @@ class MarkupCanvas {
|
|
|
2235
2263
|
this.rulers = null;
|
|
2236
2264
|
this.dragSetup = null;
|
|
2237
2265
|
this.keyboardCleanup = null;
|
|
2266
|
+
this.textEditModeEnabled = false;
|
|
2238
2267
|
this.event = new EventEmitter();
|
|
2239
2268
|
this._isReady = false;
|
|
2240
2269
|
if (!container) {
|
|
@@ -2286,7 +2315,9 @@ class MarkupCanvas {
|
|
|
2286
2315
|
}
|
|
2287
2316
|
// Keyboard events
|
|
2288
2317
|
withFeatureEnabled(this.config, "enableKeyboard", () => {
|
|
2289
|
-
const keyboardCleanup = setupKeyboardEvents(this, this.config
|
|
2318
|
+
const keyboardCleanup = setupKeyboardEvents(this, this.config, {
|
|
2319
|
+
textEditModeEnabled: this.textEditModeEnabled,
|
|
2320
|
+
});
|
|
2290
2321
|
this.keyboardCleanup = keyboardCleanup;
|
|
2291
2322
|
this.cleanupCallbacks.push(keyboardCleanup);
|
|
2292
2323
|
});
|
|
@@ -2400,7 +2431,9 @@ class MarkupCanvas {
|
|
|
2400
2431
|
if (this.keyboardCleanup) {
|
|
2401
2432
|
return true; // Already enabled
|
|
2402
2433
|
}
|
|
2403
|
-
this.keyboardCleanup = setupKeyboardEvents(this, this.config
|
|
2434
|
+
this.keyboardCleanup = setupKeyboardEvents(this, this.config, {
|
|
2435
|
+
textEditModeEnabled: this.textEditModeEnabled,
|
|
2436
|
+
});
|
|
2404
2437
|
this.cleanupCallbacks.push(this.keyboardCleanup);
|
|
2405
2438
|
return true;
|
|
2406
2439
|
}
|
|
@@ -2415,6 +2448,54 @@ class MarkupCanvas {
|
|
|
2415
2448
|
isKeyboardEnabled() {
|
|
2416
2449
|
return this.keyboardCleanup !== null;
|
|
2417
2450
|
}
|
|
2451
|
+
// Text edit mode control methods
|
|
2452
|
+
enableTextEditMode() {
|
|
2453
|
+
if (this.textEditModeEnabled) {
|
|
2454
|
+
return true; // Already enabled
|
|
2455
|
+
}
|
|
2456
|
+
this.textEditModeEnabled = true;
|
|
2457
|
+
// If keyboard is currently enabled, re-setup with new option
|
|
2458
|
+
if (this.keyboardCleanup) {
|
|
2459
|
+
// Remove old cleanup from callbacks
|
|
2460
|
+
const index = this.cleanupCallbacks.indexOf(this.keyboardCleanup);
|
|
2461
|
+
if (index > -1) {
|
|
2462
|
+
this.cleanupCallbacks.splice(index, 1);
|
|
2463
|
+
}
|
|
2464
|
+
// Cleanup old handler
|
|
2465
|
+
this.keyboardCleanup();
|
|
2466
|
+
// Setup new handler with text edit mode enabled
|
|
2467
|
+
this.keyboardCleanup = setupKeyboardEvents(this, this.config, {
|
|
2468
|
+
textEditModeEnabled: true,
|
|
2469
|
+
});
|
|
2470
|
+
this.cleanupCallbacks.push(this.keyboardCleanup);
|
|
2471
|
+
}
|
|
2472
|
+
return true;
|
|
2473
|
+
}
|
|
2474
|
+
disableTextEditMode() {
|
|
2475
|
+
if (!this.textEditModeEnabled) {
|
|
2476
|
+
return true; // Already disabled
|
|
2477
|
+
}
|
|
2478
|
+
this.textEditModeEnabled = false;
|
|
2479
|
+
// If keyboard is currently enabled, re-setup with new option
|
|
2480
|
+
if (this.keyboardCleanup) {
|
|
2481
|
+
// Remove old cleanup from callbacks
|
|
2482
|
+
const index = this.cleanupCallbacks.indexOf(this.keyboardCleanup);
|
|
2483
|
+
if (index > -1) {
|
|
2484
|
+
this.cleanupCallbacks.splice(index, 1);
|
|
2485
|
+
}
|
|
2486
|
+
// Cleanup old handler
|
|
2487
|
+
this.keyboardCleanup();
|
|
2488
|
+
// Setup new handler with text edit mode disabled
|
|
2489
|
+
this.keyboardCleanup = setupKeyboardEvents(this, this.config, {
|
|
2490
|
+
textEditModeEnabled: false,
|
|
2491
|
+
});
|
|
2492
|
+
this.cleanupCallbacks.push(this.keyboardCleanup);
|
|
2493
|
+
}
|
|
2494
|
+
return true;
|
|
2495
|
+
}
|
|
2496
|
+
isTextEditModeEnabled() {
|
|
2497
|
+
return this.textEditModeEnabled;
|
|
2498
|
+
}
|
|
2418
2499
|
toggleGrid() {
|
|
2419
2500
|
const result = toggleGrid(this.rulers);
|
|
2420
2501
|
if (result) {
|