@myoc/excalidraw 0.19.543 → 0.19.545
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/CHANGELOG.md +104 -0
- package/dist/dev/{chunk-VQRWPJBP.js → chunk-CK7JCUHP.js} +2 -2
- package/dist/dev/{chunk-6OYO4QVO.js → chunk-GWV63UBO.js} +15 -3
- package/dist/dev/{chunk-6OYO4QVO.js.map → chunk-GWV63UBO.js.map} +1 -1
- package/dist/dev/data/{image-MKDSIQJM.js → image-LHD6YZAK.js} +3 -3
- package/dist/dev/index.css +0 -15
- package/dist/dev/index.css.map +2 -2
- package/dist/dev/index.js +152 -62
- package/dist/dev/index.js.map +3 -3
- package/dist/dev/subset-shared.chunk.js +1 -1
- package/dist/dev/subset-worker.chunk.js +1 -1
- package/dist/prod/{chunk-FAEGDXCJ.js → chunk-BNH2QDIK.js} +1 -1
- package/dist/prod/{chunk-6XZBDSSD.js → chunk-EPJN7Y7U.js} +2 -2
- package/dist/prod/data/image-Y62LQRXV.js +1 -0
- package/dist/prod/index.css +1 -1
- package/dist/prod/index.js +13 -13
- package/dist/prod/subset-shared.chunk.js +1 -1
- package/dist/prod/subset-worker.chunk.js +1 -1
- package/dist/types/common/src/constants.d.ts +1 -1
- package/dist/types/excalidraw/clipboard.d.ts +1 -0
- package/package.json +4 -4
- package/dist/prod/data/image-UN6HXAW6.js +0 -1
- /package/dist/dev/{chunk-VQRWPJBP.js.map → chunk-CK7JCUHP.js.map} +0 -0
- /package/dist/dev/data/{image-MKDSIQJM.js.map → image-LHD6YZAK.js.map} +0 -0
package/dist/dev/index.js
CHANGED
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
canvasToBlob,
|
|
15
15
|
constrainScrollState,
|
|
16
16
|
createFile,
|
|
17
|
+
dataURLToFile,
|
|
17
18
|
dataURLToString,
|
|
18
19
|
encodePngMetadata,
|
|
19
20
|
exportToCanvas,
|
|
@@ -64,10 +65,10 @@ import {
|
|
|
64
65
|
serializeAsJSON,
|
|
65
66
|
strokeRectWithRotation_simple,
|
|
66
67
|
zoomToFitBounds
|
|
67
|
-
} from "./chunk-
|
|
68
|
+
} from "./chunk-GWV63UBO.js";
|
|
68
69
|
import {
|
|
69
70
|
define_import_meta_env_default
|
|
70
|
-
} from "./chunk-
|
|
71
|
+
} from "./chunk-CK7JCUHP.js";
|
|
71
72
|
import {
|
|
72
73
|
en_default
|
|
73
74
|
} from "./chunk-35XUJXYN.js";
|
|
@@ -10337,9 +10338,11 @@ import {
|
|
|
10337
10338
|
isInitializedImageElement
|
|
10338
10339
|
} from "@excalidraw/element";
|
|
10339
10340
|
import { getContainingFrame } from "@excalidraw/element";
|
|
10341
|
+
var WEB_EXCALIDRAW_CLIPBOARD_MIME_TYPE = `web ${MIME_TYPES2.excalidrawClipboard}`;
|
|
10340
10342
|
var probablySupportsClipboardReadText = "clipboard" in navigator && "readText" in navigator.clipboard;
|
|
10341
10343
|
var probablySupportsClipboardWriteText = "clipboard" in navigator && "writeText" in navigator.clipboard;
|
|
10342
10344
|
var probablySupportsClipboardBlob = "clipboard" in navigator && "write" in navigator.clipboard && "ClipboardItem" in window && "toBlob" in HTMLCanvasElement.prototype;
|
|
10345
|
+
var supportsClipboardBlob = () => "clipboard" in navigator && "write" in navigator.clipboard && "ClipboardItem" in window && "toBlob" in HTMLCanvasElement.prototype;
|
|
10343
10346
|
var clipboardContainsElements = (contents) => {
|
|
10344
10347
|
if ([
|
|
10345
10348
|
EXPORT_DATA_TYPES.excalidraw,
|
|
@@ -10434,8 +10437,69 @@ var serializeAsClipboardJSON = ({
|
|
|
10434
10437
|
};
|
|
10435
10438
|
return JSON.stringify(contents);
|
|
10436
10439
|
};
|
|
10440
|
+
var convertImageFileToPNG = async (file2) => {
|
|
10441
|
+
const bitmap = await createImageBitmap(file2);
|
|
10442
|
+
try {
|
|
10443
|
+
const canvas = document.createElement("canvas");
|
|
10444
|
+
canvas.width = bitmap.width;
|
|
10445
|
+
canvas.height = bitmap.height;
|
|
10446
|
+
const context = canvas.getContext("2d");
|
|
10447
|
+
if (!context) {
|
|
10448
|
+
throw new Error("Could not create a canvas context for clipboard image");
|
|
10449
|
+
}
|
|
10450
|
+
context.drawImage(bitmap, 0, 0);
|
|
10451
|
+
return await new Promise((resolve, reject) => {
|
|
10452
|
+
canvas.toBlob((blob) => {
|
|
10453
|
+
if (blob) {
|
|
10454
|
+
resolve(blob);
|
|
10455
|
+
} else {
|
|
10456
|
+
reject(new Error("Could not encode clipboard image as PNG"));
|
|
10457
|
+
}
|
|
10458
|
+
}, MIME_TYPES2.png);
|
|
10459
|
+
});
|
|
10460
|
+
} finally {
|
|
10461
|
+
bitmap.close();
|
|
10462
|
+
}
|
|
10463
|
+
};
|
|
10437
10464
|
var copyToClipboard = async (elements, files, clipboardEvent) => {
|
|
10438
10465
|
const json = serializeAsClipboardJSON({ elements, files });
|
|
10466
|
+
const imageFile = elements.length === 1 && isInitializedImageElement(elements[0]) ? files?.[elements[0].fileId] : null;
|
|
10467
|
+
const clipboardFile = imageFile && isSupportedImageFileType(imageFile.mimeType) && imageFile.dataURL ? dataURLToFile(imageFile.dataURL, imageFile.fileName) : null;
|
|
10468
|
+
if (clipboardFile) {
|
|
10469
|
+
const clipboardImagePNG = clipboardFile.type === MIME_TYPES2.png ? clipboardFile : convertImageFileToPNG(clipboardFile);
|
|
10470
|
+
if (supportsClipboardBlob()) {
|
|
10471
|
+
try {
|
|
10472
|
+
await navigator.clipboard.write([
|
|
10473
|
+
new ClipboardItem({
|
|
10474
|
+
[WEB_EXCALIDRAW_CLIPBOARD_MIME_TYPE]: new Blob([json], {
|
|
10475
|
+
type: MIME_TYPES2.excalidrawClipboard
|
|
10476
|
+
}),
|
|
10477
|
+
[MIME_TYPES2.png]: clipboardImagePNG
|
|
10478
|
+
})
|
|
10479
|
+
]);
|
|
10480
|
+
return;
|
|
10481
|
+
} catch (error) {
|
|
10482
|
+
console.error("Error copying image with ClipboardItem", error);
|
|
10483
|
+
}
|
|
10484
|
+
}
|
|
10485
|
+
if (clipboardEvent?.clipboardData?.items) {
|
|
10486
|
+
try {
|
|
10487
|
+
const clipboardImageFile = clipboardFile.type === MIME_TYPES2.png ? clipboardFile : new File(
|
|
10488
|
+
[await clipboardImagePNG],
|
|
10489
|
+
`${clipboardFile.name.replace(/\.[^/.]+$/, "") || "image"}.png`,
|
|
10490
|
+
{ type: MIME_TYPES2.png }
|
|
10491
|
+
);
|
|
10492
|
+
clipboardEvent.clipboardData.items.add(clipboardImageFile);
|
|
10493
|
+
await copyTextToSystemClipboard(
|
|
10494
|
+
{ [MIME_TYPES2.excalidrawClipboard]: json },
|
|
10495
|
+
clipboardEvent
|
|
10496
|
+
);
|
|
10497
|
+
return;
|
|
10498
|
+
} catch (error) {
|
|
10499
|
+
console.error("Error copying image to clipboard event", error);
|
|
10500
|
+
}
|
|
10501
|
+
}
|
|
10502
|
+
}
|
|
10439
10503
|
await copyTextToSystemClipboard(
|
|
10440
10504
|
{
|
|
10441
10505
|
[MIME_TYPES2.excalidrawClipboard]: json,
|
|
@@ -10511,11 +10575,21 @@ var readSystemClipboard = async () => {
|
|
|
10511
10575
|
}
|
|
10512
10576
|
for (const item of clipboardItems) {
|
|
10513
10577
|
for (const type of item.types) {
|
|
10578
|
+
if (type === WEB_EXCALIDRAW_CLIPBOARD_MIME_TYPE) {
|
|
10579
|
+
try {
|
|
10580
|
+
types[MIME_TYPES2.excalidrawClipboard] = await (await item.getType(type)).text();
|
|
10581
|
+
} catch (error) {
|
|
10582
|
+
console.warn(
|
|
10583
|
+
`Cannot retrieve ${type} from clipboardItem: ${error.message}`
|
|
10584
|
+
);
|
|
10585
|
+
}
|
|
10586
|
+
continue;
|
|
10587
|
+
}
|
|
10514
10588
|
if (!isMemberOf(ALLOWED_PASTE_MIME_TYPES, type)) {
|
|
10515
10589
|
continue;
|
|
10516
10590
|
}
|
|
10517
10591
|
try {
|
|
10518
|
-
if (type === MIME_TYPES2.text || type === MIME_TYPES2.html) {
|
|
10592
|
+
if (type === MIME_TYPES2.text || type === MIME_TYPES2.html || type === MIME_TYPES2.excalidrawClipboard) {
|
|
10519
10593
|
types[type] = await (await item.getType(type)).text();
|
|
10520
10594
|
} else if (isSupportedImageFileType(type)) {
|
|
10521
10595
|
const imageBlob = await item.getType(type);
|
|
@@ -10764,10 +10838,10 @@ var parseDataTransferEvent = async (event) => {
|
|
|
10764
10838
|
});
|
|
10765
10839
|
};
|
|
10766
10840
|
var parseClipboard = async (dataList, isPlainPaste = false) => {
|
|
10767
|
-
const
|
|
10768
|
-
|
|
10769
|
-
isPlainPaste
|
|
10841
|
+
const excalidrawClipboardData = dataList.getData(
|
|
10842
|
+
MIME_TYPES2.excalidrawClipboard
|
|
10770
10843
|
);
|
|
10844
|
+
const parsedEventData = excalidrawClipboardData ? { type: "text", value: excalidrawClipboardData } : await parseClipboardEventTextData(dataList, isPlainPaste);
|
|
10771
10845
|
if (parsedEventData.type === "mixedContent") {
|
|
10772
10846
|
return {
|
|
10773
10847
|
mixedContent: parsedEventData.value
|
|
@@ -10970,7 +11044,7 @@ var exportCanvas = async (type, elements, appState, files, {
|
|
|
10970
11044
|
let blob = canvasToBlob(tempCanvas);
|
|
10971
11045
|
if (appState.exportEmbedScene) {
|
|
10972
11046
|
blob = blob.then(
|
|
10973
|
-
(blob2) => import("./data/image-
|
|
11047
|
+
(blob2) => import("./data/image-LHD6YZAK.js").then(
|
|
10974
11048
|
({ encodePngMetadata: encodePngMetadata2 }) => encodePngMetadata2({
|
|
10975
11049
|
blob: blob2,
|
|
10976
11050
|
metadata: serializeAsJSON(elements, appState, files, "local")
|
|
@@ -15206,7 +15280,12 @@ import { arrayToMap as arrayToMap23, findIndex, findLastIndex as findLastIndex2
|
|
|
15206
15280
|
import { isFiniteNumber } from "@excalidraw/math";
|
|
15207
15281
|
|
|
15208
15282
|
// ../element/src/gif.ts
|
|
15209
|
-
import {
|
|
15283
|
+
import { decodeAnimated } from "@discourse/gif";
|
|
15284
|
+
var GIF_WORKER_FILENAME = "gif.worker.js";
|
|
15285
|
+
var gifWorkerUrl = new URL(
|
|
15286
|
+
GIF_WORKER_FILENAME,
|
|
15287
|
+
import.meta.url
|
|
15288
|
+
).toString();
|
|
15210
15289
|
|
|
15211
15290
|
// ../element/src/image.ts
|
|
15212
15291
|
import {
|
|
@@ -31724,21 +31803,34 @@ var GifPlaybackControls = ({
|
|
|
31724
31803
|
app.ensureGifPlaybackLoop();
|
|
31725
31804
|
}
|
|
31726
31805
|
};
|
|
31727
|
-
const
|
|
31728
|
-
(
|
|
31729
|
-
|
|
31806
|
+
const deferredGifControls = app.scene.getNonDeletedElements().flatMap((element) => {
|
|
31807
|
+
if (!isInitializedImageElement4(element) || files[element.fileId]?.mimeType !== MIME_TYPES10.gif || app.imageCache.get(element.fileId)?.gifDecodeStatus !== "deferred") {
|
|
31808
|
+
return [];
|
|
31809
|
+
}
|
|
31730
31810
|
const position = getGifControlPosition(element, liveAppState);
|
|
31731
|
-
return
|
|
31732
|
-
|
|
31733
|
-
|
|
31734
|
-
|
|
31735
|
-
|
|
31736
|
-
|
|
31737
|
-
|
|
31738
|
-
|
|
31739
|
-
|
|
31740
|
-
|
|
31741
|
-
|
|
31811
|
+
return [
|
|
31812
|
+
/* @__PURE__ */ jsx113(
|
|
31813
|
+
"div",
|
|
31814
|
+
{
|
|
31815
|
+
className: "gif-playback-controls gif-playback-controls--deferred",
|
|
31816
|
+
style: position,
|
|
31817
|
+
onPointerDown: (event) => event.stopPropagation(),
|
|
31818
|
+
children: /* @__PURE__ */ jsx113(
|
|
31819
|
+
"button",
|
|
31820
|
+
{
|
|
31821
|
+
type: "button",
|
|
31822
|
+
className: "gif-playback-controls__load-large",
|
|
31823
|
+
title: "Load Large GIF",
|
|
31824
|
+
onClick: () => {
|
|
31825
|
+
app.loadDeferredGif(element.fileId);
|
|
31826
|
+
},
|
|
31827
|
+
children: "Load Large GIF"
|
|
31828
|
+
}
|
|
31829
|
+
)
|
|
31830
|
+
},
|
|
31831
|
+
element.id
|
|
31832
|
+
)
|
|
31833
|
+
];
|
|
31742
31834
|
});
|
|
31743
31835
|
const selectedElements = app.scene.getSelectedElements(liveAppState);
|
|
31744
31836
|
const selectedElementControls = () => {
|
|
@@ -31769,29 +31861,6 @@ var GifPlaybackControls = ({
|
|
|
31769
31861
|
leftTop.y - liveAppState.offsetTop + 16
|
|
31770
31862
|
)
|
|
31771
31863
|
);
|
|
31772
|
-
if (cacheEntry?.gifDecodeStatus === "deferred") {
|
|
31773
|
-
const position = getGifControlPosition(selectedElement, liveAppState);
|
|
31774
|
-
return /* @__PURE__ */ jsx113(
|
|
31775
|
-
"div",
|
|
31776
|
-
{
|
|
31777
|
-
className: "gif-playback-controls gif-playback-controls--deferred",
|
|
31778
|
-
style: position,
|
|
31779
|
-
onPointerDown: (event) => event.stopPropagation(),
|
|
31780
|
-
children: /* @__PURE__ */ jsx113(
|
|
31781
|
-
"button",
|
|
31782
|
-
{
|
|
31783
|
-
type: "button",
|
|
31784
|
-
className: "gif-playback-controls__load-large",
|
|
31785
|
-
title: "Load Large GIF",
|
|
31786
|
-
onClick: () => {
|
|
31787
|
-
app.loadDeferredGif(selectedElement.fileId);
|
|
31788
|
-
},
|
|
31789
|
-
children: "Load Large GIF"
|
|
31790
|
-
}
|
|
31791
|
-
)
|
|
31792
|
-
}
|
|
31793
|
-
);
|
|
31794
|
-
}
|
|
31795
31864
|
if (cacheEntry?.gifDecodeStatus === "pending") {
|
|
31796
31865
|
return null;
|
|
31797
31866
|
}
|
|
@@ -32138,7 +32207,7 @@ var GifPlaybackControls = ({
|
|
|
32138
32207
|
);
|
|
32139
32208
|
};
|
|
32140
32209
|
return /* @__PURE__ */ jsxs59(Fragment18, { children: [
|
|
32141
|
-
|
|
32210
|
+
deferredGifControls,
|
|
32142
32211
|
selectedElementControls()
|
|
32143
32212
|
] });
|
|
32144
32213
|
};
|
|
@@ -37559,9 +37628,30 @@ var App = class _App extends React41.Component {
|
|
|
37559
37628
|
if (event && (!(elementUnderCursor instanceof HTMLCanvasElement) || isWritableElement4(target))) {
|
|
37560
37629
|
return;
|
|
37561
37630
|
}
|
|
37562
|
-
|
|
37563
|
-
|
|
37564
|
-
|
|
37631
|
+
let dataTransferList = await parseDataTransferEvent(event);
|
|
37632
|
+
let filesList = dataTransferList.getFiles();
|
|
37633
|
+
let data = await parseClipboard(dataTransferList, isPlainPaste);
|
|
37634
|
+
if (!data.elements && filesList.length > 0 && !isPlainPaste) {
|
|
37635
|
+
try {
|
|
37636
|
+
const systemClipboard = await readSystemClipboard();
|
|
37637
|
+
const excalidrawJSON = systemClipboard[MIME_TYPES11.excalidrawClipboard];
|
|
37638
|
+
if (typeof excalidrawJSON === "string") {
|
|
37639
|
+
dataTransferList = await parseDataTransferEvent(
|
|
37640
|
+
createPasteEvent({
|
|
37641
|
+
types: {
|
|
37642
|
+
[MIME_TYPES11.excalidrawClipboard]: excalidrawJSON
|
|
37643
|
+
}
|
|
37644
|
+
})
|
|
37645
|
+
);
|
|
37646
|
+
filesList = dataTransferList.getFiles();
|
|
37647
|
+
data = await parseClipboard(dataTransferList, isPlainPaste);
|
|
37648
|
+
}
|
|
37649
|
+
} catch (error) {
|
|
37650
|
+
console.warn(
|
|
37651
|
+
`Could not read editable image clipboard data: ${error.message}`
|
|
37652
|
+
);
|
|
37653
|
+
}
|
|
37654
|
+
}
|
|
37565
37655
|
if (this.state.viewModeEnabled) {
|
|
37566
37656
|
if (!this.containsImagePaste(data, filesList, isPlainPaste)) {
|
|
37567
37657
|
return;
|
|
@@ -44062,6 +44152,19 @@ var App = class _App extends React41.Component {
|
|
|
44062
44152
|
return;
|
|
44063
44153
|
}
|
|
44064
44154
|
}
|
|
44155
|
+
if (data.elements) {
|
|
44156
|
+
const elements = data.programmaticAPI ? convertToExcalidrawElements(
|
|
44157
|
+
data.elements
|
|
44158
|
+
) : data.elements;
|
|
44159
|
+
this.addElementsFromPasteOrLibrary({
|
|
44160
|
+
elements,
|
|
44161
|
+
files: data.files || null,
|
|
44162
|
+
position: this.editorInterface.formFactor === "desktop" ? "cursor" : "center",
|
|
44163
|
+
retainSeed: isPlainPaste,
|
|
44164
|
+
preserveFrameChildrenOrder: true
|
|
44165
|
+
});
|
|
44166
|
+
return;
|
|
44167
|
+
}
|
|
44065
44168
|
const imageFiles = dataTransferFiles.map((data2) => data2.file);
|
|
44066
44169
|
if (imageFiles.length === 0 && data.text && !isPlainPaste) {
|
|
44067
44170
|
const trimmedText = data.text.trim();
|
|
@@ -44077,19 +44180,6 @@ var App = class _App extends React41.Component {
|
|
|
44077
44180
|
}
|
|
44078
44181
|
return;
|
|
44079
44182
|
}
|
|
44080
|
-
if (data.elements) {
|
|
44081
|
-
const elements = data.programmaticAPI ? convertToExcalidrawElements(
|
|
44082
|
-
data.elements
|
|
44083
|
-
) : data.elements;
|
|
44084
|
-
this.addElementsFromPasteOrLibrary({
|
|
44085
|
-
elements,
|
|
44086
|
-
files: data.files || null,
|
|
44087
|
-
position: this.editorInterface.formFactor === "desktop" ? "cursor" : "center",
|
|
44088
|
-
retainSeed: isPlainPaste,
|
|
44089
|
-
preserveFrameChildrenOrder: true
|
|
44090
|
-
});
|
|
44091
|
-
return;
|
|
44092
|
-
}
|
|
44093
44183
|
if (!data.text) {
|
|
44094
44184
|
return;
|
|
44095
44185
|
}
|