@excalidraw/excalidraw 0.17.1-7441-4e2c539 → 0.17.1-7500-ac247a0
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/browser/dev/excalidraw-assets-dev/{chunk-SUHLFFEF.js → chunk-KGZXLFLR.js} +12342 -12294
- package/dist/browser/dev/excalidraw-assets-dev/chunk-KGZXLFLR.js.map +7 -0
- package/dist/browser/dev/excalidraw-assets-dev/{image-NOPDRTTM.css → image-3MFRCKYM.css} +3929 -3929
- package/dist/browser/dev/excalidraw-assets-dev/image-3MFRCKYM.css.map +7 -0
- package/dist/browser/dev/excalidraw-assets-dev/{image-HYNUJ3XL.js → image-5TVMINCA.js} +2 -2
- package/dist/browser/dev/index.js +17 -7
- package/dist/browser/prod/excalidraw-assets/chunk-4YN2HN3S.js +257 -0
- package/dist/browser/prod/excalidraw-assets/{image-DZ6B4AID.js → image-LTLHTTSE.js} +1 -1
- package/dist/browser/prod/excalidraw-assets/image-QBL334OA.css +1 -0
- package/dist/browser/prod/index.js +1 -1
- package/dist/dev/index.js +785 -740
- package/dist/dev/index.js.map +4 -4
- package/dist/excalidraw/actions/actionAddToLibrary.d.ts +3 -3
- package/dist/excalidraw/actions/actionBoundText.d.ts +2 -2
- package/dist/excalidraw/actions/actionCanvas.d.ts +12 -12
- package/dist/excalidraw/actions/actionClipboard.d.ts +7 -7
- package/dist/excalidraw/actions/actionDeleteSelected.d.ts +3 -3
- package/dist/excalidraw/actions/actionElementLock.d.ts +2 -2
- package/dist/excalidraw/actions/actionExport.d.ts +8 -8
- package/dist/excalidraw/actions/actionFinalize.d.ts +2 -2
- package/dist/excalidraw/actions/actionFrame.d.ts +3 -3
- package/dist/excalidraw/actions/actionGroup.d.ts +2 -2
- package/dist/excalidraw/actions/actionLinearEditor.d.ts +1 -1
- package/dist/excalidraw/actions/actionMenu.d.ts +2 -2
- package/dist/excalidraw/actions/actionNavigate.d.ts +2 -2
- package/dist/excalidraw/actions/actionProperties.d.ts +13 -13
- package/dist/excalidraw/actions/actionSelectAll.d.ts +1 -1
- package/dist/excalidraw/actions/actionStyles.d.ts +1 -1
- package/dist/excalidraw/actions/actionToggleGridMode.d.ts +1 -1
- package/dist/excalidraw/actions/actionToggleObjectsSnapMode.d.ts +1 -1
- package/dist/excalidraw/actions/actionToggleStats.d.ts +1 -1
- package/dist/excalidraw/actions/actionToggleViewMode.d.ts +1 -1
- package/dist/excalidraw/actions/actionToggleZenMode.d.ts +1 -1
- package/dist/excalidraw/components/App.d.ts +9 -1
- package/dist/excalidraw/components/App.js +91 -71
- package/dist/excalidraw/components/ImageExportDialog.js +1 -1
- package/dist/excalidraw/components/PublishLibrary.js +1 -1
- package/dist/excalidraw/components/Sidebar/Sidebar.d.ts +1 -1
- package/dist/excalidraw/components/dropdownMenu/common.d.ts +1 -1
- package/dist/excalidraw/constants.d.ts +2 -0
- package/dist/excalidraw/constants.js +4 -0
- package/dist/excalidraw/data/index.js +1 -1
- package/dist/excalidraw/element/Hyperlink.d.ts +1 -1
- package/dist/excalidraw/element/embeddable.d.ts +1 -1
- package/dist/excalidraw/element/linearElementEditor.d.ts +1 -1
- package/dist/excalidraw/emitter.d.ts +5 -9
- package/dist/excalidraw/emitter.js +12 -12
- package/dist/excalidraw/frame.js +1 -1
- package/dist/excalidraw/hooks/useLibraryItemSvg.js +1 -1
- package/dist/excalidraw/index.d.ts +9 -4
- package/dist/excalidraw/index.js +9 -4
- package/dist/excalidraw/scene/export.js +1 -1
- package/dist/excalidraw/types.d.ts +1 -1
- package/dist/excalidraw/utils.d.ts +7 -1
- package/dist/excalidraw/utils.js +15 -0
- package/dist/prod/index.js +30 -30
- package/dist/utils/bbox.d.ts +2 -2
- package/dist/utils/export.d.ts +3 -9
- package/dist/utils/export.js +13 -9
- package/dist/utils/index.d.ts +3 -0
- package/dist/utils/index.js +3 -0
- package/dist/utils/withinBounds.d.ts +1 -1
- package/dist/utils/withinBounds.js +1 -3
- package/package.json +1 -1
- package/dist/browser/dev/excalidraw-assets-dev/chunk-SUHLFFEF.js.map +0 -7
- package/dist/browser/dev/excalidraw-assets-dev/image-NOPDRTTM.css.map +0 -7
- package/dist/browser/prod/excalidraw-assets/chunk-HE2P7BQ6.js +0 -257
- package/dist/browser/prod/excalidraw-assets/image-J2QCCYAR.css +0 -1
- /package/dist/browser/dev/excalidraw-assets-dev/{image-HYNUJ3XL.js.map → image-5TVMINCA.js.map} +0 -0
package/dist/dev/index.js
CHANGED
|
@@ -411,7 +411,7 @@ var init_colors = __esm({
|
|
|
411
411
|
});
|
|
412
412
|
|
|
413
413
|
// constants.ts
|
|
414
|
-
var isDarwin, isWindows, isAndroid, isFirefox, isChrome, isSafari, isBrave, APP_NAME, DRAGGING_THRESHOLD, LINE_CONFIRM_THRESHOLD, ELEMENT_SHIFT_TRANSLATE_AMOUNT, ELEMENT_TRANSLATE_AMOUNT, TEXT_TO_CENTER_SNAP_THRESHOLD, SHIFT_LOCKING_ANGLE, CURSOR_TYPE, POINTER_BUTTON, POINTER_EVENTS, YOUTUBE_STATES, ENV, CLASSES, FONT_FAMILY, THEME, FRAME_STYLE, WINDOWS_EMOJI_FALLBACK_FONT, MIN_FONT_SIZE, DEFAULT_FONT_SIZE, DEFAULT_FONT_FAMILY, DEFAULT_TEXT_ALIGN, DEFAULT_VERTICAL_ALIGN, GRID_SIZE, IMAGE_MIME_TYPES, ALLOWED_PASTE_MIME_TYPES, MIME_TYPES, EXPORT_IMAGE_TYPES, EXPORT_DATA_TYPES, EXPORT_SOURCE, IMAGE_RENDER_TIMEOUT, TAP_TWICE_TIMEOUT, TOUCH_CTX_MENU_TIMEOUT, SCROLL_TIMEOUT, ZOOM_STEP, MIN_ZOOM, HYPERLINK_TOOLTIP_DELAY, THEME_FILTER, URL_QUERY_KEYS, URL_HASH_KEYS, DEFAULT_UI_OPTIONS, MQ_MAX_WIDTH_PORTRAIT, MQ_MAX_WIDTH_LANDSCAPE, MQ_MAX_HEIGHT_LANDSCAPE, MQ_RIGHT_SIDEBAR_MIN_WIDTH, LIBRARY_SIDEBAR_WIDTH, MAX_DECIMALS_FOR_SVG_EXPORT, EXPORT_SCALES, DEFAULT_EXPORT_PADDING, DEFAULT_MAX_IMAGE_WIDTH_OR_HEIGHT, MAX_ALLOWED_FILE_BYTES, SVG_NS, VERSIONS, BOUND_TEXT_PADDING, ARROW_LABEL_WIDTH_FRACTION, ARROW_LABEL_FONT_SIZE_TO_MIN_WIDTH_RATIO, VERTICAL_ALIGN, TEXT_ALIGN, ELEMENT_READY_TO_ERASE_OPACITY, DEFAULT_PROPORTIONAL_RADIUS, DEFAULT_ADAPTIVE_RADIUS, ROUNDNESS, PRECEDING_ELEMENT_KEY, ROUGHNESS, STROKE_WIDTH, DEFAULT_ELEMENT_PROPS, LIBRARY_SIDEBAR_TAB, DEFAULT_SIDEBAR, LIBRARY_DISABLED_TYPES, TOOL_TYPE, EDITOR_LS_KEYS;
|
|
414
|
+
var isDarwin, isWindows, isAndroid, isFirefox, isChrome, isSafari, isIOS, isBrave, APP_NAME, DRAGGING_THRESHOLD, LINE_CONFIRM_THRESHOLD, ELEMENT_SHIFT_TRANSLATE_AMOUNT, ELEMENT_TRANSLATE_AMOUNT, TEXT_TO_CENTER_SNAP_THRESHOLD, SHIFT_LOCKING_ANGLE, CURSOR_TYPE, POINTER_BUTTON, POINTER_EVENTS, YOUTUBE_STATES, ENV, CLASSES, FONT_FAMILY, THEME, FRAME_STYLE, WINDOWS_EMOJI_FALLBACK_FONT, MIN_FONT_SIZE, DEFAULT_FONT_SIZE, DEFAULT_FONT_FAMILY, DEFAULT_TEXT_ALIGN, DEFAULT_VERTICAL_ALIGN, GRID_SIZE, IMAGE_MIME_TYPES, ALLOWED_PASTE_MIME_TYPES, MIME_TYPES, EXPORT_IMAGE_TYPES, EXPORT_DATA_TYPES, EXPORT_SOURCE, IMAGE_RENDER_TIMEOUT, TAP_TWICE_TIMEOUT, TOUCH_CTX_MENU_TIMEOUT, SCROLL_TIMEOUT, ZOOM_STEP, MIN_ZOOM, HYPERLINK_TOOLTIP_DELAY, THEME_FILTER, URL_QUERY_KEYS, URL_HASH_KEYS, DEFAULT_UI_OPTIONS, MQ_MAX_WIDTH_PORTRAIT, MQ_MAX_WIDTH_LANDSCAPE, MQ_MAX_HEIGHT_LANDSCAPE, MQ_RIGHT_SIDEBAR_MIN_WIDTH, LIBRARY_SIDEBAR_WIDTH, MAX_DECIMALS_FOR_SVG_EXPORT, EXPORT_SCALES, DEFAULT_EXPORT_PADDING, DEFAULT_MAX_IMAGE_WIDTH_OR_HEIGHT, MAX_ALLOWED_FILE_BYTES, SVG_NS, VERSIONS, BOUND_TEXT_PADDING, ARROW_LABEL_WIDTH_FRACTION, ARROW_LABEL_FONT_SIZE_TO_MIN_WIDTH_RATIO, VERTICAL_ALIGN, TEXT_ALIGN, ELEMENT_READY_TO_ERASE_OPACITY, DEFAULT_PROPORTIONAL_RADIUS, DEFAULT_ADAPTIVE_RADIUS, ROUNDNESS, PRECEDING_ELEMENT_KEY, ROUGHNESS, STROKE_WIDTH, DEFAULT_ELEMENT_PROPS, LIBRARY_SIDEBAR_TAB, DEFAULT_SIDEBAR, LIBRARY_DISABLED_TYPES, TOOL_TYPE, EDITOR_LS_KEYS;
|
|
415
415
|
var init_constants = __esm({
|
|
416
416
|
"constants.ts"() {
|
|
417
417
|
"use strict";
|
|
@@ -424,6 +424,8 @@ var init_constants = __esm({
|
|
|
424
424
|
isFirefox = "netscape" in window && navigator.userAgent.indexOf("rv:") > 1 && navigator.userAgent.indexOf("Gecko") > 1;
|
|
425
425
|
isChrome = navigator.userAgent.indexOf("Chrome") !== -1;
|
|
426
426
|
isSafari = !isChrome && navigator.userAgent.indexOf("Safari") !== -1;
|
|
427
|
+
isIOS = /iPad|iPhone/.test(navigator.platform) || // iPadOS 13+
|
|
428
|
+
navigator.userAgent.includes("Mac") && "ontouchend" in document;
|
|
427
429
|
isBrave = () => navigator.brave?.isBrave?.name === "isBrave";
|
|
428
430
|
APP_NAME = "Excalidraw";
|
|
429
431
|
DRAGGING_THRESHOLD = 10;
|
|
@@ -445,7 +447,8 @@ var init_constants = __esm({
|
|
|
445
447
|
MAIN: 0,
|
|
446
448
|
WHEEL: 1,
|
|
447
449
|
SECONDARY: 2,
|
|
448
|
-
TOUCH: -1
|
|
450
|
+
TOUCH: -1,
|
|
451
|
+
ERASER: 5
|
|
449
452
|
};
|
|
450
453
|
POINTER_EVENTS = {
|
|
451
454
|
enabled: "all",
|
|
@@ -743,6 +746,16 @@ var init_InitializeApp = __esm({
|
|
|
743
746
|
// utils.ts
|
|
744
747
|
import { unstable_batchedUpdates } from "react-dom";
|
|
745
748
|
import React3 from "react";
|
|
749
|
+
function addEventListener(target, type, listener, options) {
|
|
750
|
+
if (!target) {
|
|
751
|
+
return () => {
|
|
752
|
+
};
|
|
753
|
+
}
|
|
754
|
+
target?.addEventListener?.(type, listener, options);
|
|
755
|
+
return () => {
|
|
756
|
+
target?.removeEventListener?.(type, listener, options);
|
|
757
|
+
};
|
|
758
|
+
}
|
|
746
759
|
var mockDateTime, getDateTime, capitalizeString, isToolIcon, isInputLike, isInteractive, isWritableElement, getFontFamilyString, getFontString, debounce, throttleRAF, easeOut, easeOutInterpolate, easeToValuesRAF, chunk, distance, updateActiveTool, getShortcutKey, viewportCoordsToSceneCoords, sceneCoordsToViewportCoords, getGlobalCSSVariable, RS_LTR_CHARS, RS_RTL_CHARS, RE_RTL_CHECK, isRTL, tupleToCoors, muteFSAbortError, findIndex, findLastIndex, isTransparent, withBatchedUpdates, withBatchedUpdatesThrottled, getNearestScrollableContainer, focusNearestParent, bytesToHexString, getUpdatedTimestamp, arrayToMap, arrayToMapWithIndex, isTestEnv, wrapEvent, updateObject, getFrame, isPromiseLike, queryFocusableElements, _defaultIsShallowComparatorFallback, isShallowEqual, composeEventHandlers, assertNever, memoize, isRenderThrottlingEnabled, isMemberOf, cloneJSON, isFiniteNumber, updateStable;
|
|
747
760
|
var init_utils = __esm({
|
|
748
761
|
"utils.ts"() {
|
|
@@ -16575,6 +16588,177 @@ var init_math = __esm({
|
|
|
16575
16588
|
}
|
|
16576
16589
|
});
|
|
16577
16590
|
|
|
16591
|
+
// ../utils/bbox.ts
|
|
16592
|
+
function getBBox(line) {
|
|
16593
|
+
return [
|
|
16594
|
+
Math.min(line[0][0], line[1][0]),
|
|
16595
|
+
Math.min(line[0][1], line[1][1]),
|
|
16596
|
+
Math.max(line[0][0], line[1][0]),
|
|
16597
|
+
Math.max(line[0][1], line[1][1])
|
|
16598
|
+
];
|
|
16599
|
+
}
|
|
16600
|
+
function crossProduct(a, b) {
|
|
16601
|
+
return a[0] * b[1] - b[0] * a[1];
|
|
16602
|
+
}
|
|
16603
|
+
function doBBoxesIntersect(a, b) {
|
|
16604
|
+
return a[0] <= b[2] && a[2] >= b[0] && a[1] <= b[3] && a[3] >= b[1];
|
|
16605
|
+
}
|
|
16606
|
+
function translate(a, b) {
|
|
16607
|
+
return [a[0] - b[0], a[1] - b[1]];
|
|
16608
|
+
}
|
|
16609
|
+
function isPointOnLine(l, p) {
|
|
16610
|
+
const p1 = translate(l[1], l[0]);
|
|
16611
|
+
const p2 = translate(p, l[0]);
|
|
16612
|
+
const r = crossProduct(p1, p2);
|
|
16613
|
+
return Math.abs(r) < EPSILON;
|
|
16614
|
+
}
|
|
16615
|
+
function isPointRightOfLine(l, p) {
|
|
16616
|
+
const p1 = translate(l[1], l[0]);
|
|
16617
|
+
const p2 = translate(p, l[0]);
|
|
16618
|
+
return crossProduct(p1, p2) < 0;
|
|
16619
|
+
}
|
|
16620
|
+
function isLineSegmentTouchingOrCrossingLine(a, b) {
|
|
16621
|
+
return isPointOnLine(a, b[0]) || isPointOnLine(a, b[1]) || (isPointRightOfLine(a, b[0]) ? !isPointRightOfLine(a, b[1]) : isPointRightOfLine(a, b[1]));
|
|
16622
|
+
}
|
|
16623
|
+
function doLineSegmentsIntersect(a, b) {
|
|
16624
|
+
return doBBoxesIntersect(getBBox(a), getBBox(b)) && isLineSegmentTouchingOrCrossingLine(a, b) && isLineSegmentTouchingOrCrossingLine(b, a);
|
|
16625
|
+
}
|
|
16626
|
+
var EPSILON;
|
|
16627
|
+
var init_bbox = __esm({
|
|
16628
|
+
"../utils/bbox.ts"() {
|
|
16629
|
+
"use strict";
|
|
16630
|
+
init_define_import_meta_env();
|
|
16631
|
+
EPSILON = 1e-6;
|
|
16632
|
+
}
|
|
16633
|
+
});
|
|
16634
|
+
|
|
16635
|
+
// ../utils/withinBounds.ts
|
|
16636
|
+
var getNonLinearElementRelativePoints, getElementRelativePoints, getMinMaxPoints, getRotatedBBox, isElementInsideBBox, elementPartiallyOverlapsWithOrContainsBBox, elementsOverlappingBBox;
|
|
16637
|
+
var init_withinBounds = __esm({
|
|
16638
|
+
"../utils/withinBounds.ts"() {
|
|
16639
|
+
"use strict";
|
|
16640
|
+
init_define_import_meta_env();
|
|
16641
|
+
init_excalidraw();
|
|
16642
|
+
getNonLinearElementRelativePoints = (element) => {
|
|
16643
|
+
if (element.type === "diamond") {
|
|
16644
|
+
return [
|
|
16645
|
+
[element.width / 2, 0],
|
|
16646
|
+
[element.width, element.height / 2],
|
|
16647
|
+
[element.width / 2, element.height],
|
|
16648
|
+
[0, element.height / 2]
|
|
16649
|
+
];
|
|
16650
|
+
}
|
|
16651
|
+
return [
|
|
16652
|
+
[0, 0],
|
|
16653
|
+
[0 + element.width, 0],
|
|
16654
|
+
[0 + element.width, element.height],
|
|
16655
|
+
[0, element.height]
|
|
16656
|
+
];
|
|
16657
|
+
};
|
|
16658
|
+
getElementRelativePoints = (element) => {
|
|
16659
|
+
if (isLinearElement(element) || isFreeDrawElement(element)) {
|
|
16660
|
+
return element.points;
|
|
16661
|
+
}
|
|
16662
|
+
return getNonLinearElementRelativePoints(element);
|
|
16663
|
+
};
|
|
16664
|
+
getMinMaxPoints = (points) => {
|
|
16665
|
+
const ret = points.reduce(
|
|
16666
|
+
(limits, [x, y]) => {
|
|
16667
|
+
limits.minY = Math.min(limits.minY, y);
|
|
16668
|
+
limits.minX = Math.min(limits.minX, x);
|
|
16669
|
+
limits.maxX = Math.max(limits.maxX, x);
|
|
16670
|
+
limits.maxY = Math.max(limits.maxY, y);
|
|
16671
|
+
return limits;
|
|
16672
|
+
},
|
|
16673
|
+
{
|
|
16674
|
+
minX: Infinity,
|
|
16675
|
+
minY: Infinity,
|
|
16676
|
+
maxX: -Infinity,
|
|
16677
|
+
maxY: -Infinity,
|
|
16678
|
+
cx: 0,
|
|
16679
|
+
cy: 0
|
|
16680
|
+
}
|
|
16681
|
+
);
|
|
16682
|
+
ret.cx = (ret.maxX + ret.minX) / 2;
|
|
16683
|
+
ret.cy = (ret.maxY + ret.minY) / 2;
|
|
16684
|
+
return ret;
|
|
16685
|
+
};
|
|
16686
|
+
getRotatedBBox = (element) => {
|
|
16687
|
+
const points = getElementRelativePoints(element);
|
|
16688
|
+
const { cx, cy } = getMinMaxPoints(points);
|
|
16689
|
+
const centerPoint2 = [cx, cy];
|
|
16690
|
+
const rotatedPoints = points.map(
|
|
16691
|
+
(point2) => rotatePoint([point2[0], point2[1]], centerPoint2, element.angle)
|
|
16692
|
+
);
|
|
16693
|
+
const { minX, minY, maxX, maxY } = getMinMaxPoints(rotatedPoints);
|
|
16694
|
+
return [
|
|
16695
|
+
minX + element.x,
|
|
16696
|
+
minY + element.y,
|
|
16697
|
+
maxX + element.x,
|
|
16698
|
+
maxY + element.y
|
|
16699
|
+
];
|
|
16700
|
+
};
|
|
16701
|
+
isElementInsideBBox = (element, bbox, eitherDirection = false) => {
|
|
16702
|
+
const elementBBox = getRotatedBBox(element);
|
|
16703
|
+
const elementInsideBbox = bbox[0] <= elementBBox[0] && bbox[2] >= elementBBox[2] && bbox[1] <= elementBBox[1] && bbox[3] >= elementBBox[3];
|
|
16704
|
+
if (!eitherDirection) {
|
|
16705
|
+
return elementInsideBbox;
|
|
16706
|
+
}
|
|
16707
|
+
if (elementInsideBbox) {
|
|
16708
|
+
return true;
|
|
16709
|
+
}
|
|
16710
|
+
return elementBBox[0] <= bbox[0] && elementBBox[2] >= bbox[2] && elementBBox[1] <= bbox[1] && elementBBox[3] >= bbox[3];
|
|
16711
|
+
};
|
|
16712
|
+
elementPartiallyOverlapsWithOrContainsBBox = (element, bbox) => {
|
|
16713
|
+
const elementBBox = getRotatedBBox(element);
|
|
16714
|
+
return (isValueInRange(elementBBox[0], bbox[0], bbox[2]) || isValueInRange(bbox[0], elementBBox[0], elementBBox[2])) && (isValueInRange(elementBBox[1], bbox[1], bbox[3]) || isValueInRange(bbox[1], elementBBox[1], elementBBox[3]));
|
|
16715
|
+
};
|
|
16716
|
+
elementsOverlappingBBox = ({
|
|
16717
|
+
elements,
|
|
16718
|
+
bounds,
|
|
16719
|
+
type,
|
|
16720
|
+
errorMargin = 0
|
|
16721
|
+
}) => {
|
|
16722
|
+
if (isExcalidrawElement(bounds)) {
|
|
16723
|
+
bounds = getElementBounds(bounds);
|
|
16724
|
+
}
|
|
16725
|
+
const adjustedBBox = [
|
|
16726
|
+
bounds[0] - errorMargin,
|
|
16727
|
+
bounds[1] - errorMargin,
|
|
16728
|
+
bounds[2] + errorMargin,
|
|
16729
|
+
bounds[3] + errorMargin
|
|
16730
|
+
];
|
|
16731
|
+
const includedElementSet = /* @__PURE__ */ new Set();
|
|
16732
|
+
for (const element of elements) {
|
|
16733
|
+
if (includedElementSet.has(element.id)) {
|
|
16734
|
+
continue;
|
|
16735
|
+
}
|
|
16736
|
+
const isOverlaping = type === "overlap" ? elementPartiallyOverlapsWithOrContainsBBox(element, adjustedBBox) : type === "inside" ? isElementInsideBBox(element, adjustedBBox) : isElementInsideBBox(element, adjustedBBox, true);
|
|
16737
|
+
if (isOverlaping) {
|
|
16738
|
+
includedElementSet.add(element.id);
|
|
16739
|
+
if (element.boundElements) {
|
|
16740
|
+
for (const boundElement of element.boundElements) {
|
|
16741
|
+
includedElementSet.add(boundElement.id);
|
|
16742
|
+
}
|
|
16743
|
+
}
|
|
16744
|
+
if (isTextElement(element) && element.containerId) {
|
|
16745
|
+
includedElementSet.add(element.containerId);
|
|
16746
|
+
}
|
|
16747
|
+
if (isArrowElement(element)) {
|
|
16748
|
+
if (element.startBinding) {
|
|
16749
|
+
includedElementSet.add(element.startBinding.elementId);
|
|
16750
|
+
}
|
|
16751
|
+
if (element.endBinding) {
|
|
16752
|
+
includedElementSet.add(element.endBinding?.elementId);
|
|
16753
|
+
}
|
|
16754
|
+
}
|
|
16755
|
+
}
|
|
16756
|
+
}
|
|
16757
|
+
return elements.filter((element) => includedElementSet.has(element.id));
|
|
16758
|
+
};
|
|
16759
|
+
}
|
|
16760
|
+
});
|
|
16761
|
+
|
|
16578
16762
|
// data/filesystem.ts
|
|
16579
16763
|
import {
|
|
16580
16764
|
fileOpen as _fileOpen,
|
|
@@ -17798,7 +17982,7 @@ var init_export = __esm({
|
|
|
17798
17982
|
init_appState();
|
|
17799
17983
|
init_json();
|
|
17800
17984
|
init_image2();
|
|
17801
|
-
|
|
17985
|
+
init_utils2();
|
|
17802
17986
|
init_frame();
|
|
17803
17987
|
init_element();
|
|
17804
17988
|
init_mutateElement();
|
|
@@ -18093,578 +18277,6 @@ var init_export = __esm({
|
|
|
18093
18277
|
}
|
|
18094
18278
|
});
|
|
18095
18279
|
|
|
18096
|
-
// ../utils/bbox.ts
|
|
18097
|
-
function getBBox(line) {
|
|
18098
|
-
return [
|
|
18099
|
-
Math.min(line[0][0], line[1][0]),
|
|
18100
|
-
Math.min(line[0][1], line[1][1]),
|
|
18101
|
-
Math.max(line[0][0], line[1][0]),
|
|
18102
|
-
Math.max(line[0][1], line[1][1])
|
|
18103
|
-
];
|
|
18104
|
-
}
|
|
18105
|
-
function crossProduct(a, b) {
|
|
18106
|
-
return a[0] * b[1] - b[0] * a[1];
|
|
18107
|
-
}
|
|
18108
|
-
function doBBoxesIntersect(a, b) {
|
|
18109
|
-
return a[0] <= b[2] && a[2] >= b[0] && a[1] <= b[3] && a[3] >= b[1];
|
|
18110
|
-
}
|
|
18111
|
-
function translate(a, b) {
|
|
18112
|
-
return [a[0] - b[0], a[1] - b[1]];
|
|
18113
|
-
}
|
|
18114
|
-
function isPointOnLine(l, p) {
|
|
18115
|
-
const p1 = translate(l[1], l[0]);
|
|
18116
|
-
const p2 = translate(p, l[0]);
|
|
18117
|
-
const r = crossProduct(p1, p2);
|
|
18118
|
-
return Math.abs(r) < EPSILON;
|
|
18119
|
-
}
|
|
18120
|
-
function isPointRightOfLine(l, p) {
|
|
18121
|
-
const p1 = translate(l[1], l[0]);
|
|
18122
|
-
const p2 = translate(p, l[0]);
|
|
18123
|
-
return crossProduct(p1, p2) < 0;
|
|
18124
|
-
}
|
|
18125
|
-
function isLineSegmentTouchingOrCrossingLine(a, b) {
|
|
18126
|
-
return isPointOnLine(a, b[0]) || isPointOnLine(a, b[1]) || (isPointRightOfLine(a, b[0]) ? !isPointRightOfLine(a, b[1]) : isPointRightOfLine(a, b[1]));
|
|
18127
|
-
}
|
|
18128
|
-
function doLineSegmentsIntersect(a, b) {
|
|
18129
|
-
return doBBoxesIntersect(getBBox(a), getBBox(b)) && isLineSegmentTouchingOrCrossingLine(a, b) && isLineSegmentTouchingOrCrossingLine(b, a);
|
|
18130
|
-
}
|
|
18131
|
-
var EPSILON;
|
|
18132
|
-
var init_bbox = __esm({
|
|
18133
|
-
"../utils/bbox.ts"() {
|
|
18134
|
-
"use strict";
|
|
18135
|
-
init_define_import_meta_env();
|
|
18136
|
-
EPSILON = 1e-6;
|
|
18137
|
-
}
|
|
18138
|
-
});
|
|
18139
|
-
|
|
18140
|
-
// ../utils/withinBounds.ts
|
|
18141
|
-
var getNonLinearElementRelativePoints, getElementRelativePoints, getMinMaxPoints, getRotatedBBox, isElementInsideBBox, elementPartiallyOverlapsWithOrContainsBBox, elementsOverlappingBBox;
|
|
18142
|
-
var init_withinBounds = __esm({
|
|
18143
|
-
"../utils/withinBounds.ts"() {
|
|
18144
|
-
"use strict";
|
|
18145
|
-
init_define_import_meta_env();
|
|
18146
|
-
init_typeChecks();
|
|
18147
|
-
init_math();
|
|
18148
|
-
init_bounds();
|
|
18149
|
-
getNonLinearElementRelativePoints = (element) => {
|
|
18150
|
-
if (element.type === "diamond") {
|
|
18151
|
-
return [
|
|
18152
|
-
[element.width / 2, 0],
|
|
18153
|
-
[element.width, element.height / 2],
|
|
18154
|
-
[element.width / 2, element.height],
|
|
18155
|
-
[0, element.height / 2]
|
|
18156
|
-
];
|
|
18157
|
-
}
|
|
18158
|
-
return [
|
|
18159
|
-
[0, 0],
|
|
18160
|
-
[0 + element.width, 0],
|
|
18161
|
-
[0 + element.width, element.height],
|
|
18162
|
-
[0, element.height]
|
|
18163
|
-
];
|
|
18164
|
-
};
|
|
18165
|
-
getElementRelativePoints = (element) => {
|
|
18166
|
-
if (isLinearElement(element) || isFreeDrawElement(element)) {
|
|
18167
|
-
return element.points;
|
|
18168
|
-
}
|
|
18169
|
-
return getNonLinearElementRelativePoints(element);
|
|
18170
|
-
};
|
|
18171
|
-
getMinMaxPoints = (points) => {
|
|
18172
|
-
const ret = points.reduce(
|
|
18173
|
-
(limits, [x, y]) => {
|
|
18174
|
-
limits.minY = Math.min(limits.minY, y);
|
|
18175
|
-
limits.minX = Math.min(limits.minX, x);
|
|
18176
|
-
limits.maxX = Math.max(limits.maxX, x);
|
|
18177
|
-
limits.maxY = Math.max(limits.maxY, y);
|
|
18178
|
-
return limits;
|
|
18179
|
-
},
|
|
18180
|
-
{
|
|
18181
|
-
minX: Infinity,
|
|
18182
|
-
minY: Infinity,
|
|
18183
|
-
maxX: -Infinity,
|
|
18184
|
-
maxY: -Infinity,
|
|
18185
|
-
cx: 0,
|
|
18186
|
-
cy: 0
|
|
18187
|
-
}
|
|
18188
|
-
);
|
|
18189
|
-
ret.cx = (ret.maxX + ret.minX) / 2;
|
|
18190
|
-
ret.cy = (ret.maxY + ret.minY) / 2;
|
|
18191
|
-
return ret;
|
|
18192
|
-
};
|
|
18193
|
-
getRotatedBBox = (element) => {
|
|
18194
|
-
const points = getElementRelativePoints(element);
|
|
18195
|
-
const { cx, cy } = getMinMaxPoints(points);
|
|
18196
|
-
const centerPoint2 = [cx, cy];
|
|
18197
|
-
const rotatedPoints = points.map(
|
|
18198
|
-
(point2) => rotatePoint([point2[0], point2[1]], centerPoint2, element.angle)
|
|
18199
|
-
);
|
|
18200
|
-
const { minX, minY, maxX, maxY } = getMinMaxPoints(rotatedPoints);
|
|
18201
|
-
return [
|
|
18202
|
-
minX + element.x,
|
|
18203
|
-
minY + element.y,
|
|
18204
|
-
maxX + element.x,
|
|
18205
|
-
maxY + element.y
|
|
18206
|
-
];
|
|
18207
|
-
};
|
|
18208
|
-
isElementInsideBBox = (element, bbox, eitherDirection = false) => {
|
|
18209
|
-
const elementBBox = getRotatedBBox(element);
|
|
18210
|
-
const elementInsideBbox = bbox[0] <= elementBBox[0] && bbox[2] >= elementBBox[2] && bbox[1] <= elementBBox[1] && bbox[3] >= elementBBox[3];
|
|
18211
|
-
if (!eitherDirection) {
|
|
18212
|
-
return elementInsideBbox;
|
|
18213
|
-
}
|
|
18214
|
-
if (elementInsideBbox) {
|
|
18215
|
-
return true;
|
|
18216
|
-
}
|
|
18217
|
-
return elementBBox[0] <= bbox[0] && elementBBox[2] >= bbox[2] && elementBBox[1] <= bbox[1] && elementBBox[3] >= bbox[3];
|
|
18218
|
-
};
|
|
18219
|
-
elementPartiallyOverlapsWithOrContainsBBox = (element, bbox) => {
|
|
18220
|
-
const elementBBox = getRotatedBBox(element);
|
|
18221
|
-
return (isValueInRange(elementBBox[0], bbox[0], bbox[2]) || isValueInRange(bbox[0], elementBBox[0], elementBBox[2])) && (isValueInRange(elementBBox[1], bbox[1], bbox[3]) || isValueInRange(bbox[1], elementBBox[1], elementBBox[3]));
|
|
18222
|
-
};
|
|
18223
|
-
elementsOverlappingBBox = ({
|
|
18224
|
-
elements,
|
|
18225
|
-
bounds,
|
|
18226
|
-
type,
|
|
18227
|
-
errorMargin = 0
|
|
18228
|
-
}) => {
|
|
18229
|
-
if (isExcalidrawElement(bounds)) {
|
|
18230
|
-
bounds = getElementBounds(bounds);
|
|
18231
|
-
}
|
|
18232
|
-
const adjustedBBox = [
|
|
18233
|
-
bounds[0] - errorMargin,
|
|
18234
|
-
bounds[1] - errorMargin,
|
|
18235
|
-
bounds[2] + errorMargin,
|
|
18236
|
-
bounds[3] + errorMargin
|
|
18237
|
-
];
|
|
18238
|
-
const includedElementSet = /* @__PURE__ */ new Set();
|
|
18239
|
-
for (const element of elements) {
|
|
18240
|
-
if (includedElementSet.has(element.id)) {
|
|
18241
|
-
continue;
|
|
18242
|
-
}
|
|
18243
|
-
const isOverlaping = type === "overlap" ? elementPartiallyOverlapsWithOrContainsBBox(element, adjustedBBox) : type === "inside" ? isElementInsideBBox(element, adjustedBBox) : isElementInsideBBox(element, adjustedBBox, true);
|
|
18244
|
-
if (isOverlaping) {
|
|
18245
|
-
includedElementSet.add(element.id);
|
|
18246
|
-
if (element.boundElements) {
|
|
18247
|
-
for (const boundElement of element.boundElements) {
|
|
18248
|
-
includedElementSet.add(boundElement.id);
|
|
18249
|
-
}
|
|
18250
|
-
}
|
|
18251
|
-
if (isTextElement(element) && element.containerId) {
|
|
18252
|
-
includedElementSet.add(element.containerId);
|
|
18253
|
-
}
|
|
18254
|
-
if (isArrowElement(element)) {
|
|
18255
|
-
if (element.startBinding) {
|
|
18256
|
-
includedElementSet.add(element.startBinding.elementId);
|
|
18257
|
-
}
|
|
18258
|
-
if (element.endBinding) {
|
|
18259
|
-
includedElementSet.add(element.endBinding?.elementId);
|
|
18260
|
-
}
|
|
18261
|
-
}
|
|
18262
|
-
}
|
|
18263
|
-
}
|
|
18264
|
-
return elements.filter((element) => includedElementSet.has(element.id));
|
|
18265
|
-
};
|
|
18266
|
-
}
|
|
18267
|
-
});
|
|
18268
|
-
|
|
18269
|
-
// hooks/useLibraryItemSvg.ts
|
|
18270
|
-
import { atom as atom4, useAtom as useAtom8 } from "jotai";
|
|
18271
|
-
import { useEffect as useEffect14, useState as useState8 } from "react";
|
|
18272
|
-
var libraryItemSvgsCache, exportLibraryItemToSvg, useLibraryItemSvg, useLibraryCache;
|
|
18273
|
-
var init_useLibraryItemSvg = __esm({
|
|
18274
|
-
"hooks/useLibraryItemSvg.ts"() {
|
|
18275
|
-
"use strict";
|
|
18276
|
-
init_define_import_meta_env();
|
|
18277
|
-
init_colors();
|
|
18278
|
-
init_jotai();
|
|
18279
|
-
init_export2();
|
|
18280
|
-
libraryItemSvgsCache = atom4(/* @__PURE__ */ new Map());
|
|
18281
|
-
exportLibraryItemToSvg = async (elements) => {
|
|
18282
|
-
return await exportToSvg2({
|
|
18283
|
-
elements,
|
|
18284
|
-
appState: {
|
|
18285
|
-
exportBackground: false,
|
|
18286
|
-
viewBackgroundColor: COLOR_PALETTE.white
|
|
18287
|
-
},
|
|
18288
|
-
files: null,
|
|
18289
|
-
renderEmbeddables: false
|
|
18290
|
-
});
|
|
18291
|
-
};
|
|
18292
|
-
useLibraryItemSvg = (id, elements, svgCache) => {
|
|
18293
|
-
const [svg, setSvg] = useState8();
|
|
18294
|
-
useEffect14(() => {
|
|
18295
|
-
if (elements) {
|
|
18296
|
-
if (id) {
|
|
18297
|
-
const cachedSvg = svgCache.get(id);
|
|
18298
|
-
if (cachedSvg) {
|
|
18299
|
-
setSvg(cachedSvg);
|
|
18300
|
-
} else {
|
|
18301
|
-
(async () => {
|
|
18302
|
-
const exportedSvg = await exportLibraryItemToSvg(elements);
|
|
18303
|
-
exportedSvg.querySelector(".style-fonts")?.remove();
|
|
18304
|
-
if (exportedSvg) {
|
|
18305
|
-
svgCache.set(id, exportedSvg);
|
|
18306
|
-
setSvg(exportedSvg);
|
|
18307
|
-
}
|
|
18308
|
-
})();
|
|
18309
|
-
}
|
|
18310
|
-
} else {
|
|
18311
|
-
(async () => {
|
|
18312
|
-
const exportedSvg = await exportLibraryItemToSvg(elements);
|
|
18313
|
-
setSvg(exportedSvg);
|
|
18314
|
-
})();
|
|
18315
|
-
}
|
|
18316
|
-
}
|
|
18317
|
-
}, [id, elements, svgCache, setSvg]);
|
|
18318
|
-
return svg;
|
|
18319
|
-
};
|
|
18320
|
-
useLibraryCache = () => {
|
|
18321
|
-
const [svgCache] = useAtom8(libraryItemSvgsCache, jotaiScope);
|
|
18322
|
-
const clearLibraryCache = () => svgCache.clear();
|
|
18323
|
-
const deleteItemsFromLibraryCache = (items) => {
|
|
18324
|
-
items.forEach((item) => svgCache.delete(item));
|
|
18325
|
-
};
|
|
18326
|
-
return {
|
|
18327
|
-
clearLibraryCache,
|
|
18328
|
-
deleteItemsFromLibraryCache,
|
|
18329
|
-
svgCache
|
|
18330
|
-
};
|
|
18331
|
-
};
|
|
18332
|
-
}
|
|
18333
|
-
});
|
|
18334
|
-
|
|
18335
|
-
// data/library.ts
|
|
18336
|
-
import { atom as atom5 } from "jotai";
|
|
18337
|
-
import { useEffect as useEffect15, useRef as useRef11 } from "react";
|
|
18338
|
-
var libraryItemsAtom, cloneLibraryItems, isUniqueItem, mergeLibraryItems, Library, library_default, distributeLibraryItemsOnSquareGrid, parseLibraryTokensFromUrl, useHandleLibrary;
|
|
18339
|
-
var init_library = __esm({
|
|
18340
|
-
"data/library.ts"() {
|
|
18341
|
-
"use strict";
|
|
18342
|
-
init_define_import_meta_env();
|
|
18343
|
-
init_blob();
|
|
18344
|
-
init_restore();
|
|
18345
|
-
init_jotai();
|
|
18346
|
-
init_bounds();
|
|
18347
|
-
init_errors();
|
|
18348
|
-
init_i18n();
|
|
18349
|
-
init_constants();
|
|
18350
|
-
init_useLibraryItemSvg();
|
|
18351
|
-
init_utils();
|
|
18352
|
-
libraryItemsAtom = atom5({ status: "loaded", isInitialized: true, libraryItems: [] });
|
|
18353
|
-
cloneLibraryItems = (libraryItems) => cloneJSON(libraryItems);
|
|
18354
|
-
isUniqueItem = (existingLibraryItems, targetLibraryItem) => {
|
|
18355
|
-
return !existingLibraryItems.find((libraryItem) => {
|
|
18356
|
-
if (libraryItem.elements.length !== targetLibraryItem.elements.length) {
|
|
18357
|
-
return false;
|
|
18358
|
-
}
|
|
18359
|
-
return libraryItem.elements.every((libItemExcalidrawItem, idx) => {
|
|
18360
|
-
return libItemExcalidrawItem.id === targetLibraryItem.elements[idx].id && libItemExcalidrawItem.versionNonce === targetLibraryItem.elements[idx].versionNonce;
|
|
18361
|
-
});
|
|
18362
|
-
});
|
|
18363
|
-
};
|
|
18364
|
-
mergeLibraryItems = (localItems, otherItems) => {
|
|
18365
|
-
const newItems = [];
|
|
18366
|
-
for (const item of otherItems) {
|
|
18367
|
-
if (isUniqueItem(localItems, item)) {
|
|
18368
|
-
newItems.push(item);
|
|
18369
|
-
}
|
|
18370
|
-
}
|
|
18371
|
-
return [...newItems, ...localItems];
|
|
18372
|
-
};
|
|
18373
|
-
Library = class {
|
|
18374
|
-
/** latest libraryItems */
|
|
18375
|
-
lastLibraryItems = [];
|
|
18376
|
-
/** indicates whether library is initialized with library items (has gone
|
|
18377
|
-
* though at least one update) */
|
|
18378
|
-
isInitialized = false;
|
|
18379
|
-
app;
|
|
18380
|
-
constructor(app) {
|
|
18381
|
-
this.app = app;
|
|
18382
|
-
}
|
|
18383
|
-
updateQueue = [];
|
|
18384
|
-
getLastUpdateTask = () => {
|
|
18385
|
-
return this.updateQueue[this.updateQueue.length - 1];
|
|
18386
|
-
};
|
|
18387
|
-
notifyListeners = () => {
|
|
18388
|
-
if (this.updateQueue.length > 0) {
|
|
18389
|
-
jotaiStore.set(libraryItemsAtom, {
|
|
18390
|
-
status: "loading",
|
|
18391
|
-
libraryItems: this.lastLibraryItems,
|
|
18392
|
-
isInitialized: this.isInitialized
|
|
18393
|
-
});
|
|
18394
|
-
} else {
|
|
18395
|
-
this.isInitialized = true;
|
|
18396
|
-
jotaiStore.set(libraryItemsAtom, {
|
|
18397
|
-
status: "loaded",
|
|
18398
|
-
libraryItems: this.lastLibraryItems,
|
|
18399
|
-
isInitialized: this.isInitialized
|
|
18400
|
-
});
|
|
18401
|
-
try {
|
|
18402
|
-
this.app.props.onLibraryChange?.(
|
|
18403
|
-
cloneLibraryItems(this.lastLibraryItems)
|
|
18404
|
-
);
|
|
18405
|
-
} catch (error) {
|
|
18406
|
-
console.error(error);
|
|
18407
|
-
}
|
|
18408
|
-
}
|
|
18409
|
-
};
|
|
18410
|
-
/** call on excalidraw instance unmount */
|
|
18411
|
-
destroy = () => {
|
|
18412
|
-
this.isInitialized = false;
|
|
18413
|
-
this.updateQueue = [];
|
|
18414
|
-
this.lastLibraryItems = [];
|
|
18415
|
-
jotaiStore.set(libraryItemSvgsCache, /* @__PURE__ */ new Map());
|
|
18416
|
-
};
|
|
18417
|
-
resetLibrary = () => {
|
|
18418
|
-
return this.setLibrary([]);
|
|
18419
|
-
};
|
|
18420
|
-
/**
|
|
18421
|
-
* @returns latest cloned libraryItems. Awaits all in-progress updates first.
|
|
18422
|
-
*/
|
|
18423
|
-
getLatestLibrary = () => {
|
|
18424
|
-
return new Promise(async (resolve) => {
|
|
18425
|
-
try {
|
|
18426
|
-
const libraryItems = await (this.getLastUpdateTask() || this.lastLibraryItems);
|
|
18427
|
-
if (this.updateQueue.length > 0) {
|
|
18428
|
-
resolve(this.getLatestLibrary());
|
|
18429
|
-
} else {
|
|
18430
|
-
resolve(cloneLibraryItems(libraryItems));
|
|
18431
|
-
}
|
|
18432
|
-
} catch (error) {
|
|
18433
|
-
return resolve(this.lastLibraryItems);
|
|
18434
|
-
}
|
|
18435
|
-
});
|
|
18436
|
-
};
|
|
18437
|
-
// NOTE this is a high-level public API (exposed on ExcalidrawAPI) with
|
|
18438
|
-
// a slight overhead (always restoring library items). For internal use
|
|
18439
|
-
// where merging isn't needed, use `library.setLibrary()` directly.
|
|
18440
|
-
updateLibrary = async ({
|
|
18441
|
-
libraryItems,
|
|
18442
|
-
prompt = false,
|
|
18443
|
-
merge = false,
|
|
18444
|
-
openLibraryMenu = false,
|
|
18445
|
-
defaultStatus = "unpublished"
|
|
18446
|
-
}) => {
|
|
18447
|
-
if (openLibraryMenu) {
|
|
18448
|
-
this.app.setState({
|
|
18449
|
-
openSidebar: { name: DEFAULT_SIDEBAR.name, tab: LIBRARY_SIDEBAR_TAB }
|
|
18450
|
-
});
|
|
18451
|
-
}
|
|
18452
|
-
return this.setLibrary(() => {
|
|
18453
|
-
return new Promise(async (resolve, reject) => {
|
|
18454
|
-
try {
|
|
18455
|
-
const source = await (typeof libraryItems === "function" && !(libraryItems instanceof Blob) ? libraryItems(this.lastLibraryItems) : libraryItems);
|
|
18456
|
-
let nextItems;
|
|
18457
|
-
if (source instanceof Blob) {
|
|
18458
|
-
nextItems = await loadLibraryFromBlob(source, defaultStatus);
|
|
18459
|
-
} else {
|
|
18460
|
-
nextItems = restoreLibraryItems(source, defaultStatus);
|
|
18461
|
-
}
|
|
18462
|
-
if (!prompt || window.confirm(
|
|
18463
|
-
t("alerts.confirmAddLibrary", {
|
|
18464
|
-
numShapes: nextItems.length
|
|
18465
|
-
})
|
|
18466
|
-
)) {
|
|
18467
|
-
if (prompt) {
|
|
18468
|
-
this.app.focusContainer();
|
|
18469
|
-
}
|
|
18470
|
-
if (merge) {
|
|
18471
|
-
resolve(mergeLibraryItems(this.lastLibraryItems, nextItems));
|
|
18472
|
-
} else {
|
|
18473
|
-
resolve(nextItems);
|
|
18474
|
-
}
|
|
18475
|
-
} else {
|
|
18476
|
-
reject(new AbortError());
|
|
18477
|
-
}
|
|
18478
|
-
} catch (error) {
|
|
18479
|
-
reject(error);
|
|
18480
|
-
}
|
|
18481
|
-
});
|
|
18482
|
-
});
|
|
18483
|
-
};
|
|
18484
|
-
setLibrary = (libraryItems) => {
|
|
18485
|
-
const task = new Promise(async (resolve, reject) => {
|
|
18486
|
-
try {
|
|
18487
|
-
await this.getLastUpdateTask();
|
|
18488
|
-
if (typeof libraryItems === "function") {
|
|
18489
|
-
libraryItems = libraryItems(this.lastLibraryItems);
|
|
18490
|
-
}
|
|
18491
|
-
this.lastLibraryItems = cloneLibraryItems(await libraryItems);
|
|
18492
|
-
resolve(this.lastLibraryItems);
|
|
18493
|
-
} catch (error) {
|
|
18494
|
-
reject(error);
|
|
18495
|
-
}
|
|
18496
|
-
}).catch((error) => {
|
|
18497
|
-
if (error.name === "AbortError") {
|
|
18498
|
-
console.warn("Library update aborted by user");
|
|
18499
|
-
return this.lastLibraryItems;
|
|
18500
|
-
}
|
|
18501
|
-
throw error;
|
|
18502
|
-
}).finally(() => {
|
|
18503
|
-
this.updateQueue = this.updateQueue.filter((_task) => _task !== task);
|
|
18504
|
-
this.notifyListeners();
|
|
18505
|
-
});
|
|
18506
|
-
this.updateQueue.push(task);
|
|
18507
|
-
this.notifyListeners();
|
|
18508
|
-
return task;
|
|
18509
|
-
};
|
|
18510
|
-
};
|
|
18511
|
-
library_default = Library;
|
|
18512
|
-
distributeLibraryItemsOnSquareGrid = (libraryItems) => {
|
|
18513
|
-
const PADDING = 50;
|
|
18514
|
-
const ITEMS_PER_ROW = Math.ceil(Math.sqrt(libraryItems.length));
|
|
18515
|
-
const resElements = [];
|
|
18516
|
-
const getMaxHeightPerRow = (row2) => {
|
|
18517
|
-
const maxHeight = libraryItems.slice(row2 * ITEMS_PER_ROW, row2 * ITEMS_PER_ROW + ITEMS_PER_ROW).reduce((acc, item) => {
|
|
18518
|
-
const { height } = getCommonBoundingBox(item.elements);
|
|
18519
|
-
return Math.max(acc, height);
|
|
18520
|
-
}, 0);
|
|
18521
|
-
return maxHeight;
|
|
18522
|
-
};
|
|
18523
|
-
const getMaxWidthPerCol = (targetCol) => {
|
|
18524
|
-
let index2 = 0;
|
|
18525
|
-
let currCol = 0;
|
|
18526
|
-
let maxWidth = 0;
|
|
18527
|
-
for (const item of libraryItems) {
|
|
18528
|
-
if (index2 % ITEMS_PER_ROW === 0) {
|
|
18529
|
-
currCol = 0;
|
|
18530
|
-
}
|
|
18531
|
-
if (currCol === targetCol) {
|
|
18532
|
-
const { width } = getCommonBoundingBox(item.elements);
|
|
18533
|
-
maxWidth = Math.max(maxWidth, width);
|
|
18534
|
-
}
|
|
18535
|
-
index2++;
|
|
18536
|
-
currCol++;
|
|
18537
|
-
}
|
|
18538
|
-
return maxWidth;
|
|
18539
|
-
};
|
|
18540
|
-
let colOffsetX = 0;
|
|
18541
|
-
let rowOffsetY = 0;
|
|
18542
|
-
let maxHeightCurrRow = 0;
|
|
18543
|
-
let maxWidthCurrCol = 0;
|
|
18544
|
-
let index = 0;
|
|
18545
|
-
let col = 0;
|
|
18546
|
-
let row = 0;
|
|
18547
|
-
for (const item of libraryItems) {
|
|
18548
|
-
if (index && index % ITEMS_PER_ROW === 0) {
|
|
18549
|
-
rowOffsetY += maxHeightCurrRow + PADDING;
|
|
18550
|
-
colOffsetX = 0;
|
|
18551
|
-
col = 0;
|
|
18552
|
-
row++;
|
|
18553
|
-
}
|
|
18554
|
-
if (col === 0) {
|
|
18555
|
-
maxHeightCurrRow = getMaxHeightPerRow(row);
|
|
18556
|
-
}
|
|
18557
|
-
maxWidthCurrCol = getMaxWidthPerCol(col);
|
|
18558
|
-
const { minX, minY, width, height } = getCommonBoundingBox(item.elements);
|
|
18559
|
-
const offsetCenterX = (maxWidthCurrCol - width) / 2;
|
|
18560
|
-
const offsetCenterY = (maxHeightCurrRow - height) / 2;
|
|
18561
|
-
resElements.push(
|
|
18562
|
-
...item.elements.map((element) => ({
|
|
18563
|
-
...element,
|
|
18564
|
-
x: element.x + // offset for column
|
|
18565
|
-
colOffsetX + // offset to center in given square grid
|
|
18566
|
-
offsetCenterX - // subtract minX so that given item starts at 0 coord
|
|
18567
|
-
minX,
|
|
18568
|
-
y: element.y + // offset for row
|
|
18569
|
-
rowOffsetY + // offset to center in given square grid
|
|
18570
|
-
offsetCenterY - // subtract minY so that given item starts at 0 coord
|
|
18571
|
-
minY
|
|
18572
|
-
}))
|
|
18573
|
-
);
|
|
18574
|
-
colOffsetX += maxWidthCurrCol + PADDING;
|
|
18575
|
-
index++;
|
|
18576
|
-
col++;
|
|
18577
|
-
}
|
|
18578
|
-
return resElements;
|
|
18579
|
-
};
|
|
18580
|
-
parseLibraryTokensFromUrl = () => {
|
|
18581
|
-
const libraryUrl = (
|
|
18582
|
-
// current
|
|
18583
|
-
new URLSearchParams(window.location.hash.slice(1)).get(
|
|
18584
|
-
URL_HASH_KEYS.addLibrary
|
|
18585
|
-
) || // legacy, kept for compat reasons
|
|
18586
|
-
new URLSearchParams(window.location.search).get(URL_QUERY_KEYS.addLibrary)
|
|
18587
|
-
);
|
|
18588
|
-
const idToken = libraryUrl ? new URLSearchParams(window.location.hash.slice(1)).get("token") : null;
|
|
18589
|
-
return libraryUrl ? { libraryUrl, idToken } : null;
|
|
18590
|
-
};
|
|
18591
|
-
useHandleLibrary = ({
|
|
18592
|
-
excalidrawAPI,
|
|
18593
|
-
getInitialLibraryItems
|
|
18594
|
-
}) => {
|
|
18595
|
-
const getInitialLibraryRef = useRef11(getInitialLibraryItems);
|
|
18596
|
-
useEffect15(() => {
|
|
18597
|
-
if (!excalidrawAPI) {
|
|
18598
|
-
return;
|
|
18599
|
-
}
|
|
18600
|
-
const importLibraryFromURL = async ({
|
|
18601
|
-
libraryUrl,
|
|
18602
|
-
idToken
|
|
18603
|
-
}) => {
|
|
18604
|
-
const libraryPromise = new Promise(async (resolve, reject) => {
|
|
18605
|
-
try {
|
|
18606
|
-
const request = await fetch(decodeURIComponent(libraryUrl));
|
|
18607
|
-
const blob = await request.blob();
|
|
18608
|
-
resolve(blob);
|
|
18609
|
-
} catch (error) {
|
|
18610
|
-
reject(error);
|
|
18611
|
-
}
|
|
18612
|
-
});
|
|
18613
|
-
const shouldPrompt = idToken !== excalidrawAPI.id;
|
|
18614
|
-
await (shouldPrompt && document.hidden ? new Promise((resolve) => {
|
|
18615
|
-
window.addEventListener("focus", () => resolve(), {
|
|
18616
|
-
once: true
|
|
18617
|
-
});
|
|
18618
|
-
}) : null);
|
|
18619
|
-
try {
|
|
18620
|
-
await excalidrawAPI.updateLibrary({
|
|
18621
|
-
libraryItems: libraryPromise,
|
|
18622
|
-
prompt: shouldPrompt,
|
|
18623
|
-
merge: true,
|
|
18624
|
-
defaultStatus: "published",
|
|
18625
|
-
openLibraryMenu: true
|
|
18626
|
-
});
|
|
18627
|
-
} catch (error) {
|
|
18628
|
-
throw error;
|
|
18629
|
-
} finally {
|
|
18630
|
-
if (window.location.hash.includes(URL_HASH_KEYS.addLibrary)) {
|
|
18631
|
-
const hash = new URLSearchParams(window.location.hash.slice(1));
|
|
18632
|
-
hash.delete(URL_HASH_KEYS.addLibrary);
|
|
18633
|
-
window.history.replaceState({}, APP_NAME, `#${hash.toString()}`);
|
|
18634
|
-
} else if (window.location.search.includes(URL_QUERY_KEYS.addLibrary)) {
|
|
18635
|
-
const query = new URLSearchParams(window.location.search);
|
|
18636
|
-
query.delete(URL_QUERY_KEYS.addLibrary);
|
|
18637
|
-
window.history.replaceState({}, APP_NAME, `?${query.toString()}`);
|
|
18638
|
-
}
|
|
18639
|
-
}
|
|
18640
|
-
};
|
|
18641
|
-
const onHashChange = (event) => {
|
|
18642
|
-
event.preventDefault();
|
|
18643
|
-
const libraryUrlTokens2 = parseLibraryTokensFromUrl();
|
|
18644
|
-
if (libraryUrlTokens2) {
|
|
18645
|
-
event.stopImmediatePropagation();
|
|
18646
|
-
window.history.replaceState({}, "", event.oldURL);
|
|
18647
|
-
importLibraryFromURL(libraryUrlTokens2);
|
|
18648
|
-
}
|
|
18649
|
-
};
|
|
18650
|
-
if (getInitialLibraryRef.current) {
|
|
18651
|
-
excalidrawAPI.updateLibrary({
|
|
18652
|
-
libraryItems: getInitialLibraryRef.current()
|
|
18653
|
-
});
|
|
18654
|
-
}
|
|
18655
|
-
const libraryUrlTokens = parseLibraryTokensFromUrl();
|
|
18656
|
-
if (libraryUrlTokens) {
|
|
18657
|
-
importLibraryFromURL(libraryUrlTokens);
|
|
18658
|
-
}
|
|
18659
|
-
window.addEventListener("hashchange" /* HASHCHANGE */, onHashChange);
|
|
18660
|
-
return () => {
|
|
18661
|
-
window.removeEventListener("hashchange" /* HASHCHANGE */, onHashChange);
|
|
18662
|
-
};
|
|
18663
|
-
}, [excalidrawAPI]);
|
|
18664
|
-
};
|
|
18665
|
-
}
|
|
18666
|
-
});
|
|
18667
|
-
|
|
18668
18280
|
// ../utils/export.ts
|
|
18669
18281
|
var exportToCanvas2, exportToBlob, exportToSvg2, exportToClipboard;
|
|
18670
18282
|
var init_export2 = __esm({
|
|
@@ -18672,18 +18284,10 @@ var init_export2 = __esm({
|
|
|
18672
18284
|
"use strict";
|
|
18673
18285
|
init_define_import_meta_env();
|
|
18674
18286
|
init_export();
|
|
18675
|
-
|
|
18676
|
-
init_restore();
|
|
18677
|
-
init_constants();
|
|
18287
|
+
init_excalidraw();
|
|
18678
18288
|
init_image();
|
|
18679
18289
|
init_json();
|
|
18680
18290
|
init_clipboard();
|
|
18681
|
-
init_bbox();
|
|
18682
|
-
init_withinBounds();
|
|
18683
|
-
init_json();
|
|
18684
|
-
init_blob();
|
|
18685
|
-
init_renderElement();
|
|
18686
|
-
init_library();
|
|
18687
18291
|
exportToCanvas2 = ({
|
|
18688
18292
|
elements,
|
|
18689
18293
|
appState,
|
|
@@ -18814,6 +18418,17 @@ var init_export2 = __esm({
|
|
|
18814
18418
|
}
|
|
18815
18419
|
});
|
|
18816
18420
|
|
|
18421
|
+
// ../utils/index.ts
|
|
18422
|
+
var init_utils2 = __esm({
|
|
18423
|
+
"../utils/index.ts"() {
|
|
18424
|
+
"use strict";
|
|
18425
|
+
init_define_import_meta_env();
|
|
18426
|
+
init_bbox();
|
|
18427
|
+
init_withinBounds();
|
|
18428
|
+
init_export2();
|
|
18429
|
+
}
|
|
18430
|
+
});
|
|
18431
|
+
|
|
18817
18432
|
// frame.ts
|
|
18818
18433
|
function isElementIntersectingFrame(element, frame) {
|
|
18819
18434
|
const frameLineSegments = getElementLineSegments(frame);
|
|
@@ -18839,7 +18454,7 @@ var init_frame = __esm({
|
|
|
18839
18454
|
init_groups();
|
|
18840
18455
|
init_Scene();
|
|
18841
18456
|
init_bounds();
|
|
18842
|
-
|
|
18457
|
+
init_utils2();
|
|
18843
18458
|
init_typeChecks();
|
|
18844
18459
|
bindElementsToFramesAfterDuplication = (nextElements, oldElements, oldIdToDuplicatedId) => {
|
|
18845
18460
|
const nextElementMap = arrayToMap(nextElements);
|
|
@@ -21914,7 +21529,7 @@ var init_ProjectName = __esm({
|
|
|
21914
21529
|
});
|
|
21915
21530
|
|
|
21916
21531
|
// components/ProjectName.tsx
|
|
21917
|
-
import { useState as
|
|
21532
|
+
import { useState as useState8 } from "react";
|
|
21918
21533
|
import { jsx as jsx26, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
21919
21534
|
var ProjectName;
|
|
21920
21535
|
var init_ProjectName2 = __esm({
|
|
@@ -21928,7 +21543,7 @@ var init_ProjectName2 = __esm({
|
|
|
21928
21543
|
init_keys();
|
|
21929
21544
|
ProjectName = (props) => {
|
|
21930
21545
|
const { id } = useExcalidrawContainer();
|
|
21931
|
-
const [fileName, setFileName] =
|
|
21546
|
+
const [fileName, setFileName] = useState8(props.value);
|
|
21932
21547
|
const handleBlur = (event) => {
|
|
21933
21548
|
if (!props.ignoreFocus) {
|
|
21934
21549
|
focusNearestParent(event.target);
|
|
@@ -22021,7 +21636,7 @@ var init_data = __esm({
|
|
|
22021
21636
|
init_element();
|
|
22022
21637
|
init_typeChecks();
|
|
22023
21638
|
init_i18n();
|
|
22024
|
-
|
|
21639
|
+
init_utils2();
|
|
22025
21640
|
init_scene();
|
|
22026
21641
|
init_export();
|
|
22027
21642
|
init_utils();
|
|
@@ -22934,7 +22549,7 @@ var init_Avatar = __esm({
|
|
|
22934
22549
|
});
|
|
22935
22550
|
|
|
22936
22551
|
// components/Avatar.tsx
|
|
22937
|
-
import { useState as
|
|
22552
|
+
import { useState as useState9 } from "react";
|
|
22938
22553
|
import clsx14 from "clsx";
|
|
22939
22554
|
import { jsx as jsx32 } from "react/jsx-runtime";
|
|
22940
22555
|
var Avatar;
|
|
@@ -22953,7 +22568,7 @@ var init_Avatar2 = __esm({
|
|
|
22953
22568
|
isCurrentUser
|
|
22954
22569
|
}) => {
|
|
22955
22570
|
const shortName = getNameInitial(name);
|
|
22956
|
-
const [error, setError] =
|
|
22571
|
+
const [error, setError] = useState9(false);
|
|
22957
22572
|
const loadImg = !error && src;
|
|
22958
22573
|
const style = loadImg ? void 0 : { background: color };
|
|
22959
22574
|
return /* @__PURE__ */ jsx32(
|
|
@@ -24618,6 +24233,405 @@ var init_manager = __esm({
|
|
|
24618
24233
|
}
|
|
24619
24234
|
});
|
|
24620
24235
|
|
|
24236
|
+
// hooks/useLibraryItemSvg.ts
|
|
24237
|
+
import { atom as atom4, useAtom as useAtom8 } from "jotai";
|
|
24238
|
+
import { useEffect as useEffect14, useState as useState10 } from "react";
|
|
24239
|
+
var libraryItemSvgsCache, exportLibraryItemToSvg, useLibraryItemSvg, useLibraryCache;
|
|
24240
|
+
var init_useLibraryItemSvg = __esm({
|
|
24241
|
+
"hooks/useLibraryItemSvg.ts"() {
|
|
24242
|
+
"use strict";
|
|
24243
|
+
init_define_import_meta_env();
|
|
24244
|
+
init_colors();
|
|
24245
|
+
init_jotai();
|
|
24246
|
+
init_utils2();
|
|
24247
|
+
libraryItemSvgsCache = atom4(/* @__PURE__ */ new Map());
|
|
24248
|
+
exportLibraryItemToSvg = async (elements) => {
|
|
24249
|
+
return await exportToSvg2({
|
|
24250
|
+
elements,
|
|
24251
|
+
appState: {
|
|
24252
|
+
exportBackground: false,
|
|
24253
|
+
viewBackgroundColor: COLOR_PALETTE.white
|
|
24254
|
+
},
|
|
24255
|
+
files: null,
|
|
24256
|
+
renderEmbeddables: false
|
|
24257
|
+
});
|
|
24258
|
+
};
|
|
24259
|
+
useLibraryItemSvg = (id, elements, svgCache) => {
|
|
24260
|
+
const [svg, setSvg] = useState10();
|
|
24261
|
+
useEffect14(() => {
|
|
24262
|
+
if (elements) {
|
|
24263
|
+
if (id) {
|
|
24264
|
+
const cachedSvg = svgCache.get(id);
|
|
24265
|
+
if (cachedSvg) {
|
|
24266
|
+
setSvg(cachedSvg);
|
|
24267
|
+
} else {
|
|
24268
|
+
(async () => {
|
|
24269
|
+
const exportedSvg = await exportLibraryItemToSvg(elements);
|
|
24270
|
+
exportedSvg.querySelector(".style-fonts")?.remove();
|
|
24271
|
+
if (exportedSvg) {
|
|
24272
|
+
svgCache.set(id, exportedSvg);
|
|
24273
|
+
setSvg(exportedSvg);
|
|
24274
|
+
}
|
|
24275
|
+
})();
|
|
24276
|
+
}
|
|
24277
|
+
} else {
|
|
24278
|
+
(async () => {
|
|
24279
|
+
const exportedSvg = await exportLibraryItemToSvg(elements);
|
|
24280
|
+
setSvg(exportedSvg);
|
|
24281
|
+
})();
|
|
24282
|
+
}
|
|
24283
|
+
}
|
|
24284
|
+
}, [id, elements, svgCache, setSvg]);
|
|
24285
|
+
return svg;
|
|
24286
|
+
};
|
|
24287
|
+
useLibraryCache = () => {
|
|
24288
|
+
const [svgCache] = useAtom8(libraryItemSvgsCache, jotaiScope);
|
|
24289
|
+
const clearLibraryCache = () => svgCache.clear();
|
|
24290
|
+
const deleteItemsFromLibraryCache = (items) => {
|
|
24291
|
+
items.forEach((item) => svgCache.delete(item));
|
|
24292
|
+
};
|
|
24293
|
+
return {
|
|
24294
|
+
clearLibraryCache,
|
|
24295
|
+
deleteItemsFromLibraryCache,
|
|
24296
|
+
svgCache
|
|
24297
|
+
};
|
|
24298
|
+
};
|
|
24299
|
+
}
|
|
24300
|
+
});
|
|
24301
|
+
|
|
24302
|
+
// data/library.ts
|
|
24303
|
+
import { atom as atom5 } from "jotai";
|
|
24304
|
+
import { useEffect as useEffect15, useRef as useRef11 } from "react";
|
|
24305
|
+
var libraryItemsAtom, cloneLibraryItems, isUniqueItem, mergeLibraryItems, Library, library_default, distributeLibraryItemsOnSquareGrid, parseLibraryTokensFromUrl, useHandleLibrary;
|
|
24306
|
+
var init_library = __esm({
|
|
24307
|
+
"data/library.ts"() {
|
|
24308
|
+
"use strict";
|
|
24309
|
+
init_define_import_meta_env();
|
|
24310
|
+
init_blob();
|
|
24311
|
+
init_restore();
|
|
24312
|
+
init_jotai();
|
|
24313
|
+
init_bounds();
|
|
24314
|
+
init_errors();
|
|
24315
|
+
init_i18n();
|
|
24316
|
+
init_constants();
|
|
24317
|
+
init_useLibraryItemSvg();
|
|
24318
|
+
init_utils();
|
|
24319
|
+
libraryItemsAtom = atom5({ status: "loaded", isInitialized: true, libraryItems: [] });
|
|
24320
|
+
cloneLibraryItems = (libraryItems) => cloneJSON(libraryItems);
|
|
24321
|
+
isUniqueItem = (existingLibraryItems, targetLibraryItem) => {
|
|
24322
|
+
return !existingLibraryItems.find((libraryItem) => {
|
|
24323
|
+
if (libraryItem.elements.length !== targetLibraryItem.elements.length) {
|
|
24324
|
+
return false;
|
|
24325
|
+
}
|
|
24326
|
+
return libraryItem.elements.every((libItemExcalidrawItem, idx) => {
|
|
24327
|
+
return libItemExcalidrawItem.id === targetLibraryItem.elements[idx].id && libItemExcalidrawItem.versionNonce === targetLibraryItem.elements[idx].versionNonce;
|
|
24328
|
+
});
|
|
24329
|
+
});
|
|
24330
|
+
};
|
|
24331
|
+
mergeLibraryItems = (localItems, otherItems) => {
|
|
24332
|
+
const newItems = [];
|
|
24333
|
+
for (const item of otherItems) {
|
|
24334
|
+
if (isUniqueItem(localItems, item)) {
|
|
24335
|
+
newItems.push(item);
|
|
24336
|
+
}
|
|
24337
|
+
}
|
|
24338
|
+
return [...newItems, ...localItems];
|
|
24339
|
+
};
|
|
24340
|
+
Library = class {
|
|
24341
|
+
/** latest libraryItems */
|
|
24342
|
+
lastLibraryItems = [];
|
|
24343
|
+
/** indicates whether library is initialized with library items (has gone
|
|
24344
|
+
* though at least one update) */
|
|
24345
|
+
isInitialized = false;
|
|
24346
|
+
app;
|
|
24347
|
+
constructor(app) {
|
|
24348
|
+
this.app = app;
|
|
24349
|
+
}
|
|
24350
|
+
updateQueue = [];
|
|
24351
|
+
getLastUpdateTask = () => {
|
|
24352
|
+
return this.updateQueue[this.updateQueue.length - 1];
|
|
24353
|
+
};
|
|
24354
|
+
notifyListeners = () => {
|
|
24355
|
+
if (this.updateQueue.length > 0) {
|
|
24356
|
+
jotaiStore.set(libraryItemsAtom, {
|
|
24357
|
+
status: "loading",
|
|
24358
|
+
libraryItems: this.lastLibraryItems,
|
|
24359
|
+
isInitialized: this.isInitialized
|
|
24360
|
+
});
|
|
24361
|
+
} else {
|
|
24362
|
+
this.isInitialized = true;
|
|
24363
|
+
jotaiStore.set(libraryItemsAtom, {
|
|
24364
|
+
status: "loaded",
|
|
24365
|
+
libraryItems: this.lastLibraryItems,
|
|
24366
|
+
isInitialized: this.isInitialized
|
|
24367
|
+
});
|
|
24368
|
+
try {
|
|
24369
|
+
this.app.props.onLibraryChange?.(
|
|
24370
|
+
cloneLibraryItems(this.lastLibraryItems)
|
|
24371
|
+
);
|
|
24372
|
+
} catch (error) {
|
|
24373
|
+
console.error(error);
|
|
24374
|
+
}
|
|
24375
|
+
}
|
|
24376
|
+
};
|
|
24377
|
+
/** call on excalidraw instance unmount */
|
|
24378
|
+
destroy = () => {
|
|
24379
|
+
this.isInitialized = false;
|
|
24380
|
+
this.updateQueue = [];
|
|
24381
|
+
this.lastLibraryItems = [];
|
|
24382
|
+
jotaiStore.set(libraryItemSvgsCache, /* @__PURE__ */ new Map());
|
|
24383
|
+
};
|
|
24384
|
+
resetLibrary = () => {
|
|
24385
|
+
return this.setLibrary([]);
|
|
24386
|
+
};
|
|
24387
|
+
/**
|
|
24388
|
+
* @returns latest cloned libraryItems. Awaits all in-progress updates first.
|
|
24389
|
+
*/
|
|
24390
|
+
getLatestLibrary = () => {
|
|
24391
|
+
return new Promise(async (resolve) => {
|
|
24392
|
+
try {
|
|
24393
|
+
const libraryItems = await (this.getLastUpdateTask() || this.lastLibraryItems);
|
|
24394
|
+
if (this.updateQueue.length > 0) {
|
|
24395
|
+
resolve(this.getLatestLibrary());
|
|
24396
|
+
} else {
|
|
24397
|
+
resolve(cloneLibraryItems(libraryItems));
|
|
24398
|
+
}
|
|
24399
|
+
} catch (error) {
|
|
24400
|
+
return resolve(this.lastLibraryItems);
|
|
24401
|
+
}
|
|
24402
|
+
});
|
|
24403
|
+
};
|
|
24404
|
+
// NOTE this is a high-level public API (exposed on ExcalidrawAPI) with
|
|
24405
|
+
// a slight overhead (always restoring library items). For internal use
|
|
24406
|
+
// where merging isn't needed, use `library.setLibrary()` directly.
|
|
24407
|
+
updateLibrary = async ({
|
|
24408
|
+
libraryItems,
|
|
24409
|
+
prompt = false,
|
|
24410
|
+
merge = false,
|
|
24411
|
+
openLibraryMenu = false,
|
|
24412
|
+
defaultStatus = "unpublished"
|
|
24413
|
+
}) => {
|
|
24414
|
+
if (openLibraryMenu) {
|
|
24415
|
+
this.app.setState({
|
|
24416
|
+
openSidebar: { name: DEFAULT_SIDEBAR.name, tab: LIBRARY_SIDEBAR_TAB }
|
|
24417
|
+
});
|
|
24418
|
+
}
|
|
24419
|
+
return this.setLibrary(() => {
|
|
24420
|
+
return new Promise(async (resolve, reject) => {
|
|
24421
|
+
try {
|
|
24422
|
+
const source = await (typeof libraryItems === "function" && !(libraryItems instanceof Blob) ? libraryItems(this.lastLibraryItems) : libraryItems);
|
|
24423
|
+
let nextItems;
|
|
24424
|
+
if (source instanceof Blob) {
|
|
24425
|
+
nextItems = await loadLibraryFromBlob(source, defaultStatus);
|
|
24426
|
+
} else {
|
|
24427
|
+
nextItems = restoreLibraryItems(source, defaultStatus);
|
|
24428
|
+
}
|
|
24429
|
+
if (!prompt || window.confirm(
|
|
24430
|
+
t("alerts.confirmAddLibrary", {
|
|
24431
|
+
numShapes: nextItems.length
|
|
24432
|
+
})
|
|
24433
|
+
)) {
|
|
24434
|
+
if (prompt) {
|
|
24435
|
+
this.app.focusContainer();
|
|
24436
|
+
}
|
|
24437
|
+
if (merge) {
|
|
24438
|
+
resolve(mergeLibraryItems(this.lastLibraryItems, nextItems));
|
|
24439
|
+
} else {
|
|
24440
|
+
resolve(nextItems);
|
|
24441
|
+
}
|
|
24442
|
+
} else {
|
|
24443
|
+
reject(new AbortError());
|
|
24444
|
+
}
|
|
24445
|
+
} catch (error) {
|
|
24446
|
+
reject(error);
|
|
24447
|
+
}
|
|
24448
|
+
});
|
|
24449
|
+
});
|
|
24450
|
+
};
|
|
24451
|
+
setLibrary = (libraryItems) => {
|
|
24452
|
+
const task = new Promise(async (resolve, reject) => {
|
|
24453
|
+
try {
|
|
24454
|
+
await this.getLastUpdateTask();
|
|
24455
|
+
if (typeof libraryItems === "function") {
|
|
24456
|
+
libraryItems = libraryItems(this.lastLibraryItems);
|
|
24457
|
+
}
|
|
24458
|
+
this.lastLibraryItems = cloneLibraryItems(await libraryItems);
|
|
24459
|
+
resolve(this.lastLibraryItems);
|
|
24460
|
+
} catch (error) {
|
|
24461
|
+
reject(error);
|
|
24462
|
+
}
|
|
24463
|
+
}).catch((error) => {
|
|
24464
|
+
if (error.name === "AbortError") {
|
|
24465
|
+
console.warn("Library update aborted by user");
|
|
24466
|
+
return this.lastLibraryItems;
|
|
24467
|
+
}
|
|
24468
|
+
throw error;
|
|
24469
|
+
}).finally(() => {
|
|
24470
|
+
this.updateQueue = this.updateQueue.filter((_task) => _task !== task);
|
|
24471
|
+
this.notifyListeners();
|
|
24472
|
+
});
|
|
24473
|
+
this.updateQueue.push(task);
|
|
24474
|
+
this.notifyListeners();
|
|
24475
|
+
return task;
|
|
24476
|
+
};
|
|
24477
|
+
};
|
|
24478
|
+
library_default = Library;
|
|
24479
|
+
distributeLibraryItemsOnSquareGrid = (libraryItems) => {
|
|
24480
|
+
const PADDING = 50;
|
|
24481
|
+
const ITEMS_PER_ROW = Math.ceil(Math.sqrt(libraryItems.length));
|
|
24482
|
+
const resElements = [];
|
|
24483
|
+
const getMaxHeightPerRow = (row2) => {
|
|
24484
|
+
const maxHeight = libraryItems.slice(row2 * ITEMS_PER_ROW, row2 * ITEMS_PER_ROW + ITEMS_PER_ROW).reduce((acc, item) => {
|
|
24485
|
+
const { height } = getCommonBoundingBox(item.elements);
|
|
24486
|
+
return Math.max(acc, height);
|
|
24487
|
+
}, 0);
|
|
24488
|
+
return maxHeight;
|
|
24489
|
+
};
|
|
24490
|
+
const getMaxWidthPerCol = (targetCol) => {
|
|
24491
|
+
let index2 = 0;
|
|
24492
|
+
let currCol = 0;
|
|
24493
|
+
let maxWidth = 0;
|
|
24494
|
+
for (const item of libraryItems) {
|
|
24495
|
+
if (index2 % ITEMS_PER_ROW === 0) {
|
|
24496
|
+
currCol = 0;
|
|
24497
|
+
}
|
|
24498
|
+
if (currCol === targetCol) {
|
|
24499
|
+
const { width } = getCommonBoundingBox(item.elements);
|
|
24500
|
+
maxWidth = Math.max(maxWidth, width);
|
|
24501
|
+
}
|
|
24502
|
+
index2++;
|
|
24503
|
+
currCol++;
|
|
24504
|
+
}
|
|
24505
|
+
return maxWidth;
|
|
24506
|
+
};
|
|
24507
|
+
let colOffsetX = 0;
|
|
24508
|
+
let rowOffsetY = 0;
|
|
24509
|
+
let maxHeightCurrRow = 0;
|
|
24510
|
+
let maxWidthCurrCol = 0;
|
|
24511
|
+
let index = 0;
|
|
24512
|
+
let col = 0;
|
|
24513
|
+
let row = 0;
|
|
24514
|
+
for (const item of libraryItems) {
|
|
24515
|
+
if (index && index % ITEMS_PER_ROW === 0) {
|
|
24516
|
+
rowOffsetY += maxHeightCurrRow + PADDING;
|
|
24517
|
+
colOffsetX = 0;
|
|
24518
|
+
col = 0;
|
|
24519
|
+
row++;
|
|
24520
|
+
}
|
|
24521
|
+
if (col === 0) {
|
|
24522
|
+
maxHeightCurrRow = getMaxHeightPerRow(row);
|
|
24523
|
+
}
|
|
24524
|
+
maxWidthCurrCol = getMaxWidthPerCol(col);
|
|
24525
|
+
const { minX, minY, width, height } = getCommonBoundingBox(item.elements);
|
|
24526
|
+
const offsetCenterX = (maxWidthCurrCol - width) / 2;
|
|
24527
|
+
const offsetCenterY = (maxHeightCurrRow - height) / 2;
|
|
24528
|
+
resElements.push(
|
|
24529
|
+
...item.elements.map((element) => ({
|
|
24530
|
+
...element,
|
|
24531
|
+
x: element.x + // offset for column
|
|
24532
|
+
colOffsetX + // offset to center in given square grid
|
|
24533
|
+
offsetCenterX - // subtract minX so that given item starts at 0 coord
|
|
24534
|
+
minX,
|
|
24535
|
+
y: element.y + // offset for row
|
|
24536
|
+
rowOffsetY + // offset to center in given square grid
|
|
24537
|
+
offsetCenterY - // subtract minY so that given item starts at 0 coord
|
|
24538
|
+
minY
|
|
24539
|
+
}))
|
|
24540
|
+
);
|
|
24541
|
+
colOffsetX += maxWidthCurrCol + PADDING;
|
|
24542
|
+
index++;
|
|
24543
|
+
col++;
|
|
24544
|
+
}
|
|
24545
|
+
return resElements;
|
|
24546
|
+
};
|
|
24547
|
+
parseLibraryTokensFromUrl = () => {
|
|
24548
|
+
const libraryUrl = (
|
|
24549
|
+
// current
|
|
24550
|
+
new URLSearchParams(window.location.hash.slice(1)).get(
|
|
24551
|
+
URL_HASH_KEYS.addLibrary
|
|
24552
|
+
) || // legacy, kept for compat reasons
|
|
24553
|
+
new URLSearchParams(window.location.search).get(URL_QUERY_KEYS.addLibrary)
|
|
24554
|
+
);
|
|
24555
|
+
const idToken = libraryUrl ? new URLSearchParams(window.location.hash.slice(1)).get("token") : null;
|
|
24556
|
+
return libraryUrl ? { libraryUrl, idToken } : null;
|
|
24557
|
+
};
|
|
24558
|
+
useHandleLibrary = ({
|
|
24559
|
+
excalidrawAPI,
|
|
24560
|
+
getInitialLibraryItems
|
|
24561
|
+
}) => {
|
|
24562
|
+
const getInitialLibraryRef = useRef11(getInitialLibraryItems);
|
|
24563
|
+
useEffect15(() => {
|
|
24564
|
+
if (!excalidrawAPI) {
|
|
24565
|
+
return;
|
|
24566
|
+
}
|
|
24567
|
+
const importLibraryFromURL = async ({
|
|
24568
|
+
libraryUrl,
|
|
24569
|
+
idToken
|
|
24570
|
+
}) => {
|
|
24571
|
+
const libraryPromise = new Promise(async (resolve, reject) => {
|
|
24572
|
+
try {
|
|
24573
|
+
const request = await fetch(decodeURIComponent(libraryUrl));
|
|
24574
|
+
const blob = await request.blob();
|
|
24575
|
+
resolve(blob);
|
|
24576
|
+
} catch (error) {
|
|
24577
|
+
reject(error);
|
|
24578
|
+
}
|
|
24579
|
+
});
|
|
24580
|
+
const shouldPrompt = idToken !== excalidrawAPI.id;
|
|
24581
|
+
await (shouldPrompt && document.hidden ? new Promise((resolve) => {
|
|
24582
|
+
window.addEventListener("focus", () => resolve(), {
|
|
24583
|
+
once: true
|
|
24584
|
+
});
|
|
24585
|
+
}) : null);
|
|
24586
|
+
try {
|
|
24587
|
+
await excalidrawAPI.updateLibrary({
|
|
24588
|
+
libraryItems: libraryPromise,
|
|
24589
|
+
prompt: shouldPrompt,
|
|
24590
|
+
merge: true,
|
|
24591
|
+
defaultStatus: "published",
|
|
24592
|
+
openLibraryMenu: true
|
|
24593
|
+
});
|
|
24594
|
+
} catch (error) {
|
|
24595
|
+
throw error;
|
|
24596
|
+
} finally {
|
|
24597
|
+
if (window.location.hash.includes(URL_HASH_KEYS.addLibrary)) {
|
|
24598
|
+
const hash = new URLSearchParams(window.location.hash.slice(1));
|
|
24599
|
+
hash.delete(URL_HASH_KEYS.addLibrary);
|
|
24600
|
+
window.history.replaceState({}, APP_NAME, `#${hash.toString()}`);
|
|
24601
|
+
} else if (window.location.search.includes(URL_QUERY_KEYS.addLibrary)) {
|
|
24602
|
+
const query = new URLSearchParams(window.location.search);
|
|
24603
|
+
query.delete(URL_QUERY_KEYS.addLibrary);
|
|
24604
|
+
window.history.replaceState({}, APP_NAME, `?${query.toString()}`);
|
|
24605
|
+
}
|
|
24606
|
+
}
|
|
24607
|
+
};
|
|
24608
|
+
const onHashChange = (event) => {
|
|
24609
|
+
event.preventDefault();
|
|
24610
|
+
const libraryUrlTokens2 = parseLibraryTokensFromUrl();
|
|
24611
|
+
if (libraryUrlTokens2) {
|
|
24612
|
+
event.stopImmediatePropagation();
|
|
24613
|
+
window.history.replaceState({}, "", event.oldURL);
|
|
24614
|
+
importLibraryFromURL(libraryUrlTokens2);
|
|
24615
|
+
}
|
|
24616
|
+
};
|
|
24617
|
+
if (getInitialLibraryRef.current) {
|
|
24618
|
+
excalidrawAPI.updateLibrary({
|
|
24619
|
+
libraryItems: getInitialLibraryRef.current()
|
|
24620
|
+
});
|
|
24621
|
+
}
|
|
24622
|
+
const libraryUrlTokens = parseLibraryTokensFromUrl();
|
|
24623
|
+
if (libraryUrlTokens) {
|
|
24624
|
+
importLibraryFromURL(libraryUrlTokens);
|
|
24625
|
+
}
|
|
24626
|
+
window.addEventListener("hashchange" /* HASHCHANGE */, onHashChange);
|
|
24627
|
+
return () => {
|
|
24628
|
+
window.removeEventListener("hashchange" /* HASHCHANGE */, onHashChange);
|
|
24629
|
+
};
|
|
24630
|
+
}, [excalidrawAPI]);
|
|
24631
|
+
};
|
|
24632
|
+
}
|
|
24633
|
+
});
|
|
24634
|
+
|
|
24621
24635
|
// gesture.ts
|
|
24622
24636
|
var getCenter, getDistance, sum;
|
|
24623
24637
|
var init_gesture = __esm({
|
|
@@ -26364,7 +26378,7 @@ var init_PublishLibrary2 = __esm({
|
|
|
26364
26378
|
init_Dialog2();
|
|
26365
26379
|
init_i18n();
|
|
26366
26380
|
init_Trans();
|
|
26367
|
-
|
|
26381
|
+
init_utils2();
|
|
26368
26382
|
init_constants();
|
|
26369
26383
|
init_blob();
|
|
26370
26384
|
init_utils();
|
|
@@ -28061,7 +28075,7 @@ var init_ImageExportDialog2 = __esm({
|
|
|
28061
28075
|
init_filesystem();
|
|
28062
28076
|
init_i18n();
|
|
28063
28077
|
init_scene();
|
|
28064
|
-
|
|
28078
|
+
init_utils2();
|
|
28065
28079
|
init_icons();
|
|
28066
28080
|
init_Dialog2();
|
|
28067
28081
|
init_RadioGroup2();
|
|
@@ -35450,12 +35464,6 @@ var init_emitter = __esm({
|
|
|
35450
35464
|
init_define_import_meta_env();
|
|
35451
35465
|
Emitter = class {
|
|
35452
35466
|
subscribers = [];
|
|
35453
|
-
value;
|
|
35454
|
-
updateOnChangeOnly;
|
|
35455
|
-
constructor(opts) {
|
|
35456
|
-
this.updateOnChangeOnly = opts?.updateOnChangeOnly ?? false;
|
|
35457
|
-
this.value = opts?.initialState;
|
|
35458
|
-
}
|
|
35459
35467
|
/**
|
|
35460
35468
|
* Attaches subscriber
|
|
35461
35469
|
*
|
|
@@ -35466,6 +35474,12 @@ var init_emitter = __esm({
|
|
|
35466
35474
|
this.subscribers.push(..._handlers);
|
|
35467
35475
|
return () => this.off(_handlers);
|
|
35468
35476
|
}
|
|
35477
|
+
once(...handlers) {
|
|
35478
|
+
const _handlers = handlers.flat().filter((item) => typeof item === "function");
|
|
35479
|
+
_handlers.push(() => detach());
|
|
35480
|
+
const detach = this.on(..._handlers);
|
|
35481
|
+
return detach;
|
|
35482
|
+
}
|
|
35469
35483
|
off(...handlers) {
|
|
35470
35484
|
const _handlers = handlers.flat();
|
|
35471
35485
|
this.subscribers = this.subscribers.filter(
|
|
@@ -35473,15 +35487,13 @@ var init_emitter = __esm({
|
|
|
35473
35487
|
);
|
|
35474
35488
|
}
|
|
35475
35489
|
trigger(...payload) {
|
|
35476
|
-
|
|
35477
|
-
|
|
35490
|
+
for (const handler of this.subscribers) {
|
|
35491
|
+
handler(...payload);
|
|
35478
35492
|
}
|
|
35479
|
-
this
|
|
35480
|
-
return this.subscribers.map((handler) => handler(...payload));
|
|
35493
|
+
return this;
|
|
35481
35494
|
}
|
|
35482
|
-
|
|
35495
|
+
clear() {
|
|
35483
35496
|
this.subscribers = [];
|
|
35484
|
-
this.value = void 0;
|
|
35485
35497
|
}
|
|
35486
35498
|
};
|
|
35487
35499
|
}
|
|
@@ -35797,7 +35809,7 @@ var init_App = __esm({
|
|
|
35797
35809
|
init_emitter();
|
|
35798
35810
|
init_ElementCanvasButtons2();
|
|
35799
35811
|
init_magic();
|
|
35800
|
-
|
|
35812
|
+
init_utils2();
|
|
35801
35813
|
init_colors();
|
|
35802
35814
|
init_MagicButton();
|
|
35803
35815
|
init_icons();
|
|
@@ -35890,6 +35902,7 @@ var init_App = __esm({
|
|
|
35890
35902
|
hitLinkElement;
|
|
35891
35903
|
lastPointerDownEvent = null;
|
|
35892
35904
|
lastPointerUpEvent = null;
|
|
35905
|
+
lastPointerMoveEvent = null;
|
|
35893
35906
|
lastViewportPosition = { x: 0, y: 0 };
|
|
35894
35907
|
laserPathManager = new LaserPathManager(this);
|
|
35895
35908
|
onChangeEmitter = new Emitter();
|
|
@@ -35897,6 +35910,8 @@ var init_App = __esm({
|
|
|
35897
35910
|
onPointerUpEmitter = new Emitter();
|
|
35898
35911
|
onUserFollowEmitter = new Emitter();
|
|
35899
35912
|
onScrollChangeEmitter = new Emitter();
|
|
35913
|
+
missingPointerEventCleanupEmitter = new Emitter();
|
|
35914
|
+
onRemoveEventListenersEmitter = new Emitter();
|
|
35900
35915
|
constructor(props) {
|
|
35901
35916
|
super(props);
|
|
35902
35917
|
const defaultAppState2 = getDefaultAppState();
|
|
@@ -37274,6 +37289,7 @@ var init_App = __esm({
|
|
|
37274
37289
|
return false;
|
|
37275
37290
|
};
|
|
37276
37291
|
async componentDidMount() {
|
|
37292
|
+
console.log("HELLO IS");
|
|
37277
37293
|
this.unmounted = false;
|
|
37278
37294
|
this.excalidrawContainerValue.container = this.excalidrawContainerRef.current;
|
|
37279
37295
|
if (define_import_meta_env_default.MODE === ENV.TEST || define_import_meta_env_default.DEV) {
|
|
@@ -37346,7 +37362,7 @@ var init_App = __esm({
|
|
|
37346
37362
|
this.scene.destroy();
|
|
37347
37363
|
this.library.destroy();
|
|
37348
37364
|
this.laserPathManager.destroy();
|
|
37349
|
-
this.onChangeEmitter.
|
|
37365
|
+
this.onChangeEmitter.clear();
|
|
37350
37366
|
ShapeCache.destroy();
|
|
37351
37367
|
SnapCache.destroy();
|
|
37352
37368
|
clearTimeout(touchTimeout);
|
|
@@ -37363,60 +37379,6 @@ var init_App = __esm({
|
|
|
37363
37379
|
}
|
|
37364
37380
|
this.setState({});
|
|
37365
37381
|
});
|
|
37366
|
-
removeEventListeners() {
|
|
37367
|
-
document.removeEventListener("pointerup" /* POINTER_UP */, this.removePointer);
|
|
37368
|
-
document.removeEventListener("copy" /* COPY */, this.onCopy);
|
|
37369
|
-
document.removeEventListener("paste" /* PASTE */, this.pasteFromClipboard);
|
|
37370
|
-
document.removeEventListener("cut" /* CUT */, this.onCut);
|
|
37371
|
-
this.excalidrawContainerRef.current?.removeEventListener(
|
|
37372
|
-
"wheel" /* WHEEL */,
|
|
37373
|
-
this.onWheel
|
|
37374
|
-
);
|
|
37375
|
-
this.nearestScrollableContainer?.removeEventListener(
|
|
37376
|
-
"scroll" /* SCROLL */,
|
|
37377
|
-
this.onScroll
|
|
37378
|
-
);
|
|
37379
|
-
document.removeEventListener("keydown" /* KEYDOWN */, this.onKeyDown, false);
|
|
37380
|
-
document.removeEventListener(
|
|
37381
|
-
"mousemove" /* MOUSE_MOVE */,
|
|
37382
|
-
this.updateCurrentCursorPosition,
|
|
37383
|
-
false
|
|
37384
|
-
);
|
|
37385
|
-
document.removeEventListener("keyup" /* KEYUP */, this.onKeyUp);
|
|
37386
|
-
window.removeEventListener("resize" /* RESIZE */, this.onResize, false);
|
|
37387
|
-
window.removeEventListener("unload" /* UNLOAD */, this.onUnload, false);
|
|
37388
|
-
window.removeEventListener("blur" /* BLUR */, this.onBlur, false);
|
|
37389
|
-
this.excalidrawContainerRef.current?.removeEventListener(
|
|
37390
|
-
"dragover" /* DRAG_OVER */,
|
|
37391
|
-
this.disableEvent,
|
|
37392
|
-
false
|
|
37393
|
-
);
|
|
37394
|
-
this.excalidrawContainerRef.current?.removeEventListener(
|
|
37395
|
-
"drop" /* DROP */,
|
|
37396
|
-
this.disableEvent,
|
|
37397
|
-
false
|
|
37398
|
-
);
|
|
37399
|
-
document.removeEventListener(
|
|
37400
|
-
"gesturestart" /* GESTURE_START */,
|
|
37401
|
-
this.onGestureStart,
|
|
37402
|
-
false
|
|
37403
|
-
);
|
|
37404
|
-
document.removeEventListener(
|
|
37405
|
-
"gesturechange" /* GESTURE_CHANGE */,
|
|
37406
|
-
this.onGestureChange,
|
|
37407
|
-
false
|
|
37408
|
-
);
|
|
37409
|
-
document.removeEventListener(
|
|
37410
|
-
"gestureend" /* GESTURE_END */,
|
|
37411
|
-
this.onGestureEnd,
|
|
37412
|
-
false
|
|
37413
|
-
);
|
|
37414
|
-
document.removeEventListener(
|
|
37415
|
-
"fullscreenchange" /* FULLSCREENCHANGE */,
|
|
37416
|
-
this.onFullscreenChange
|
|
37417
|
-
);
|
|
37418
|
-
window.removeEventListener("message" /* MESSAGE */, this.onWindowMessage, false);
|
|
37419
|
-
}
|
|
37420
37382
|
/** generally invoked only if fullscreen was invoked programmatically */
|
|
37421
37383
|
onFullscreenChange = () => {
|
|
37422
37384
|
if (
|
|
@@ -37428,71 +37390,97 @@ var init_App = __esm({
|
|
|
37428
37390
|
});
|
|
37429
37391
|
}
|
|
37430
37392
|
};
|
|
37393
|
+
removeEventListeners() {
|
|
37394
|
+
this.onRemoveEventListenersEmitter.trigger();
|
|
37395
|
+
}
|
|
37431
37396
|
addEventListeners() {
|
|
37432
37397
|
this.removeEventListeners();
|
|
37433
|
-
window.addEventListener("message" /* MESSAGE */, this.onWindowMessage, false);
|
|
37434
|
-
document.addEventListener("pointerup" /* POINTER_UP */, this.removePointer);
|
|
37435
|
-
document.addEventListener("copy" /* COPY */, this.onCopy);
|
|
37436
|
-
this.excalidrawContainerRef.current?.addEventListener(
|
|
37437
|
-
"wheel" /* WHEEL */,
|
|
37438
|
-
this.onWheel,
|
|
37439
|
-
{ passive: false }
|
|
37440
|
-
);
|
|
37441
37398
|
if (this.props.handleKeyboardGlobally) {
|
|
37442
|
-
|
|
37399
|
+
this.onRemoveEventListenersEmitter.once(
|
|
37400
|
+
addEventListener(document, "keydown" /* KEYDOWN */, this.onKeyDown, false)
|
|
37401
|
+
);
|
|
37443
37402
|
}
|
|
37444
|
-
|
|
37445
|
-
|
|
37446
|
-
|
|
37447
|
-
|
|
37448
|
-
|
|
37449
|
-
|
|
37450
|
-
|
|
37451
|
-
this.
|
|
37452
|
-
|
|
37453
|
-
|
|
37454
|
-
"
|
|
37455
|
-
this.
|
|
37456
|
-
|
|
37457
|
-
|
|
37458
|
-
|
|
37459
|
-
|
|
37460
|
-
|
|
37461
|
-
|
|
37462
|
-
|
|
37463
|
-
|
|
37464
|
-
|
|
37465
|
-
|
|
37466
|
-
|
|
37403
|
+
this.onRemoveEventListenersEmitter.once(
|
|
37404
|
+
addEventListener(
|
|
37405
|
+
this.excalidrawContainerRef.current,
|
|
37406
|
+
"wheel" /* WHEEL */,
|
|
37407
|
+
this.onWheel,
|
|
37408
|
+
{ passive: false }
|
|
37409
|
+
),
|
|
37410
|
+
addEventListener(window, "message" /* MESSAGE */, this.onWindowMessage, false),
|
|
37411
|
+
addEventListener(document, "pointerup" /* POINTER_UP */, this.removePointer),
|
|
37412
|
+
// #3553
|
|
37413
|
+
addEventListener(document, "copy" /* COPY */, this.onCopy),
|
|
37414
|
+
addEventListener(document, "keyup" /* KEYUP */, this.onKeyUp, { passive: true }),
|
|
37415
|
+
addEventListener(
|
|
37416
|
+
document,
|
|
37417
|
+
"mousemove" /* MOUSE_MOVE */,
|
|
37418
|
+
this.updateCurrentCursorPosition
|
|
37419
|
+
),
|
|
37420
|
+
// rerender text elements on font load to fix #637 && #1553
|
|
37421
|
+
addEventListener(document.fonts, "loadingdone", (event) => {
|
|
37422
|
+
const loadedFontFaces = event.fontfaces;
|
|
37423
|
+
this.fonts.onFontsLoaded(loadedFontFaces);
|
|
37424
|
+
}),
|
|
37425
|
+
// Safari-only desktop pinch zoom
|
|
37426
|
+
addEventListener(
|
|
37427
|
+
document,
|
|
37428
|
+
"gesturestart" /* GESTURE_START */,
|
|
37429
|
+
this.onGestureStart,
|
|
37430
|
+
false
|
|
37431
|
+
),
|
|
37432
|
+
addEventListener(
|
|
37433
|
+
document,
|
|
37434
|
+
"gesturechange" /* GESTURE_CHANGE */,
|
|
37435
|
+
this.onGestureChange,
|
|
37436
|
+
false
|
|
37437
|
+
),
|
|
37438
|
+
addEventListener(
|
|
37439
|
+
document,
|
|
37440
|
+
"gestureend" /* GESTURE_END */,
|
|
37441
|
+
this.onGestureEnd,
|
|
37442
|
+
false
|
|
37443
|
+
),
|
|
37444
|
+
addEventListener(window, "focus" /* FOCUS */, () => {
|
|
37445
|
+
this.maybeCleanupAfterMissingPointerUp(null);
|
|
37446
|
+
})
|
|
37467
37447
|
);
|
|
37468
37448
|
if (this.state.viewModeEnabled) {
|
|
37469
37449
|
return;
|
|
37470
37450
|
}
|
|
37471
|
-
|
|
37472
|
-
|
|
37473
|
-
|
|
37451
|
+
this.onRemoveEventListenersEmitter.once(
|
|
37452
|
+
addEventListener(
|
|
37453
|
+
document,
|
|
37454
|
+
"fullscreenchange" /* FULLSCREENCHANGE */,
|
|
37455
|
+
this.onFullscreenChange
|
|
37456
|
+
),
|
|
37457
|
+
addEventListener(document, "paste" /* PASTE */, this.pasteFromClipboard),
|
|
37458
|
+
addEventListener(document, "cut" /* CUT */, this.onCut),
|
|
37459
|
+
addEventListener(window, "resize" /* RESIZE */, this.onResize, false),
|
|
37460
|
+
addEventListener(window, "unload" /* UNLOAD */, this.onUnload, false),
|
|
37461
|
+
addEventListener(window, "blur" /* BLUR */, this.onBlur, false),
|
|
37462
|
+
addEventListener(
|
|
37463
|
+
this.excalidrawContainerRef.current,
|
|
37464
|
+
"dragover" /* DRAG_OVER */,
|
|
37465
|
+
this.disableEvent,
|
|
37466
|
+
false
|
|
37467
|
+
),
|
|
37468
|
+
addEventListener(
|
|
37469
|
+
this.excalidrawContainerRef.current,
|
|
37470
|
+
"drop" /* DROP */,
|
|
37471
|
+
this.disableEvent,
|
|
37472
|
+
false
|
|
37473
|
+
)
|
|
37474
|
+
);
|
|
37474
37475
|
if (this.props.detectScroll) {
|
|
37475
|
-
this.
|
|
37476
|
-
|
|
37477
|
-
|
|
37478
|
-
|
|
37479
|
-
|
|
37480
|
-
|
|
37476
|
+
this.onRemoveEventListenersEmitter.once(
|
|
37477
|
+
addEventListener(
|
|
37478
|
+
getNearestScrollableContainer(this.excalidrawContainerRef.current),
|
|
37479
|
+
"scroll" /* SCROLL */,
|
|
37480
|
+
this.onScroll
|
|
37481
|
+
)
|
|
37481
37482
|
);
|
|
37482
37483
|
}
|
|
37483
|
-
window.addEventListener("resize" /* RESIZE */, this.onResize, false);
|
|
37484
|
-
window.addEventListener("unload" /* UNLOAD */, this.onUnload, false);
|
|
37485
|
-
window.addEventListener("blur" /* BLUR */, this.onBlur, false);
|
|
37486
|
-
this.excalidrawContainerRef.current?.addEventListener(
|
|
37487
|
-
"dragover" /* DRAG_OVER */,
|
|
37488
|
-
this.disableEvent,
|
|
37489
|
-
false
|
|
37490
|
-
);
|
|
37491
|
-
this.excalidrawContainerRef.current?.addEventListener(
|
|
37492
|
-
"drop" /* DROP */,
|
|
37493
|
-
this.disableEvent,
|
|
37494
|
-
false
|
|
37495
|
-
);
|
|
37496
37484
|
}
|
|
37497
37485
|
componentDidUpdate(prevProps, prevState) {
|
|
37498
37486
|
this.updateEmbeddables();
|
|
@@ -37665,7 +37653,7 @@ var init_App = __esm({
|
|
|
37665
37653
|
didTapTwice = false;
|
|
37666
37654
|
}
|
|
37667
37655
|
onTouchStart = (event) => {
|
|
37668
|
-
if (
|
|
37656
|
+
if (isIOS) {
|
|
37669
37657
|
event.preventDefault();
|
|
37670
37658
|
}
|
|
37671
37659
|
if (!didTapTwice) {
|
|
@@ -37686,9 +37674,6 @@ var init_App = __esm({
|
|
|
37686
37674
|
didTapTwice = false;
|
|
37687
37675
|
clearTimeout(tappedTwiceTimer);
|
|
37688
37676
|
}
|
|
37689
|
-
if (isAndroid) {
|
|
37690
|
-
event.preventDefault();
|
|
37691
|
-
}
|
|
37692
37677
|
if (event.touches.length === 2) {
|
|
37693
37678
|
this.setState({
|
|
37694
37679
|
selectedElementIds: makeNextSelectedElementIds({}, this.state),
|
|
@@ -39018,6 +39003,7 @@ var init_App = __esm({
|
|
|
39018
39003
|
};
|
|
39019
39004
|
handleCanvasPointerMove = (event) => {
|
|
39020
39005
|
this.savePointer(event.clientX, event.clientY, this.state.cursorButton);
|
|
39006
|
+
this.lastPointerMoveEvent = event.nativeEvent;
|
|
39021
39007
|
if (gesture.pointers.has(event.pointerId)) {
|
|
39022
39008
|
gesture.pointers.set(event.pointerId, {
|
|
39023
39009
|
x: event.clientX,
|
|
@@ -39443,6 +39429,7 @@ var init_App = __esm({
|
|
|
39443
39429
|
}
|
|
39444
39430
|
}
|
|
39445
39431
|
handleCanvasPointerDown = (event) => {
|
|
39432
|
+
this.maybeCleanupAfterMissingPointerUp(event.nativeEvent);
|
|
39446
39433
|
this.maybeUnfollowRemoteUser();
|
|
39447
39434
|
if (this.state.contextMenu) {
|
|
39448
39435
|
this.setState({ contextMenu: null });
|
|
@@ -39478,7 +39465,6 @@ var init_App = __esm({
|
|
|
39478
39465
|
selection.removeAllRanges();
|
|
39479
39466
|
}
|
|
39480
39467
|
this.maybeOpenContextMenuAfterPointerDownOnTouchDevices(event);
|
|
39481
|
-
this.maybeCleanupAfterMissingPointerUp(event);
|
|
39482
39468
|
if (!this.state.penDetected && event.pointerType === "pen") {
|
|
39483
39469
|
this.setState((prevState) => {
|
|
39484
39470
|
return {
|
|
@@ -39502,7 +39488,47 @@ var init_App = __esm({
|
|
|
39502
39488
|
cursorButton: "down"
|
|
39503
39489
|
});
|
|
39504
39490
|
this.savePointer(event.clientX, event.clientY, "down");
|
|
39505
|
-
if (event.button
|
|
39491
|
+
if (event.button === POINTER_BUTTON.ERASER && this.state.activeTool.type !== TOOL_TYPE.eraser) {
|
|
39492
|
+
this.setState(
|
|
39493
|
+
{
|
|
39494
|
+
activeTool: updateActiveTool(this.state, {
|
|
39495
|
+
type: TOOL_TYPE.eraser,
|
|
39496
|
+
lastActiveToolBeforeEraser: this.state.activeTool
|
|
39497
|
+
})
|
|
39498
|
+
},
|
|
39499
|
+
() => {
|
|
39500
|
+
this.handleCanvasPointerDown(event);
|
|
39501
|
+
const onPointerUp2 = () => {
|
|
39502
|
+
unsubPointerUp();
|
|
39503
|
+
unsubCleanup?.();
|
|
39504
|
+
if (isEraserActive(this.state)) {
|
|
39505
|
+
this.setState({
|
|
39506
|
+
activeTool: updateActiveTool(this.state, {
|
|
39507
|
+
...this.state.activeTool.lastActiveTool || {
|
|
39508
|
+
type: TOOL_TYPE.selection
|
|
39509
|
+
},
|
|
39510
|
+
lastActiveToolBeforeEraser: null
|
|
39511
|
+
})
|
|
39512
|
+
});
|
|
39513
|
+
}
|
|
39514
|
+
};
|
|
39515
|
+
const unsubPointerUp = addEventListener(
|
|
39516
|
+
window,
|
|
39517
|
+
"pointerup" /* POINTER_UP */,
|
|
39518
|
+
onPointerUp2,
|
|
39519
|
+
{
|
|
39520
|
+
once: true
|
|
39521
|
+
}
|
|
39522
|
+
);
|
|
39523
|
+
let unsubCleanup;
|
|
39524
|
+
requestAnimationFrame(() => {
|
|
39525
|
+
unsubCleanup = this.missingPointerEventCleanupEmitter.once(onPointerUp2);
|
|
39526
|
+
});
|
|
39527
|
+
}
|
|
39528
|
+
);
|
|
39529
|
+
return;
|
|
39530
|
+
}
|
|
39531
|
+
if (event.button !== POINTER_BUTTON.MAIN && event.button !== POINTER_BUTTON.TOUCH && event.button !== POINTER_BUTTON.ERASER) {
|
|
39506
39532
|
return;
|
|
39507
39533
|
}
|
|
39508
39534
|
if (gesture.pointers.size > 1) {
|
|
@@ -39586,7 +39612,9 @@ var init_App = __esm({
|
|
|
39586
39612
|
const onPointerUp = this.onPointerUpFromPointerDownHandler(pointerDownState);
|
|
39587
39613
|
const onKeyDown = this.onKeyDownFromPointerDownHandler(pointerDownState);
|
|
39588
39614
|
const onKeyUp = this.onKeyUpFromPointerDownHandler(pointerDownState);
|
|
39589
|
-
|
|
39615
|
+
this.missingPointerEventCleanupEmitter.once(
|
|
39616
|
+
(_event) => onPointerUp(_event || event.nativeEvent)
|
|
39617
|
+
);
|
|
39590
39618
|
if (!this.state.viewModeEnabled || this.state.activeTool.type === "laser") {
|
|
39591
39619
|
window.addEventListener("pointermove" /* POINTER_MOVE */, onPointerMove);
|
|
39592
39620
|
window.addEventListener("pointerup" /* POINTER_UP */, onPointerUp);
|
|
@@ -39667,11 +39695,15 @@ var init_App = __esm({
|
|
|
39667
39695
|
touchTimeout = 0;
|
|
39668
39696
|
invalidateContextMenu = false;
|
|
39669
39697
|
};
|
|
39670
|
-
|
|
39671
|
-
|
|
39672
|
-
|
|
39673
|
-
|
|
39674
|
-
|
|
39698
|
+
/**
|
|
39699
|
+
* pointerup may not fire in certian cases (user tabs away...), so in order
|
|
39700
|
+
* to properly cleanup pointerdown state, we need to fire any hanging
|
|
39701
|
+
* pointerup handlers manually
|
|
39702
|
+
*/
|
|
39703
|
+
maybeCleanupAfterMissingPointerUp = (event) => {
|
|
39704
|
+
lastPointerUp?.();
|
|
39705
|
+
this.missingPointerEventCleanupEmitter.trigger(event).clear();
|
|
39706
|
+
};
|
|
39675
39707
|
// Returns whether the event is a panning
|
|
39676
39708
|
handleCanvasPanUsingWheelOrSpaceDrag = (event) => {
|
|
39677
39709
|
if (!(gesture.pointers.size <= 1 && (event.button === POINTER_BUTTON.WHEEL || event.button === POINTER_BUTTON.MAIN && isHoldingSpace || isHandToolActive(this.state) || this.state.viewModeEnabled)) || isTextElement(this.state.editingElement)) {
|
|
@@ -39823,9 +39855,9 @@ var init_App = __esm({
|
|
|
39823
39855
|
this.handlePointerMoveOverScrollbars(event2, pointerDownState);
|
|
39824
39856
|
});
|
|
39825
39857
|
const onPointerUp = withBatchedUpdates(() => {
|
|
39858
|
+
lastPointerUp = null;
|
|
39826
39859
|
isDraggingScrollBar = false;
|
|
39827
39860
|
setCursorForShape(this.interactiveCanvas, this.state);
|
|
39828
|
-
lastPointerUp = null;
|
|
39829
39861
|
this.setState({
|
|
39830
39862
|
cursorButton: "up"
|
|
39831
39863
|
});
|
|
@@ -40872,6 +40904,7 @@ var init_App = __esm({
|
|
|
40872
40904
|
}
|
|
40873
40905
|
onPointerUpFromPointerDownHandler(pointerDownState) {
|
|
40874
40906
|
return withBatchedUpdates((childEvent) => {
|
|
40907
|
+
this.removePointer(childEvent);
|
|
40875
40908
|
if (pointerDownState.eventListeners.onMove) {
|
|
40876
40909
|
pointerDownState.eventListeners.onMove.flush();
|
|
40877
40910
|
}
|
|
@@ -40951,7 +40984,7 @@ var init_App = __esm({
|
|
|
40951
40984
|
}
|
|
40952
40985
|
}
|
|
40953
40986
|
}
|
|
40954
|
-
|
|
40987
|
+
this.missingPointerEventCleanupEmitter.clear();
|
|
40955
40988
|
window.removeEventListener(
|
|
40956
40989
|
"pointermove" /* POINTER_MOVE */,
|
|
40957
40990
|
pointerDownState.eventListeners.onMove
|
|
@@ -41242,18 +41275,20 @@ var init_App = __esm({
|
|
|
41242
41275
|
});
|
|
41243
41276
|
}
|
|
41244
41277
|
}
|
|
41245
|
-
|
|
41278
|
+
const pointerStart = this.lastPointerDownEvent;
|
|
41279
|
+
const pointerEnd = this.lastPointerUpEvent || this.lastPointerMoveEvent;
|
|
41280
|
+
if (isEraserActive(this.state) && pointerStart && pointerEnd) {
|
|
41246
41281
|
const draggedDistance = distance2d(
|
|
41247
|
-
|
|
41248
|
-
|
|
41249
|
-
|
|
41250
|
-
|
|
41282
|
+
pointerStart.clientX,
|
|
41283
|
+
pointerStart.clientY,
|
|
41284
|
+
pointerEnd.clientX,
|
|
41285
|
+
pointerEnd.clientY
|
|
41251
41286
|
);
|
|
41252
41287
|
if (draggedDistance === 0) {
|
|
41253
41288
|
const scenePointer = viewportCoordsToSceneCoords(
|
|
41254
41289
|
{
|
|
41255
|
-
clientX:
|
|
41256
|
-
clientY:
|
|
41290
|
+
clientX: pointerEnd.clientX,
|
|
41291
|
+
clientY: pointerEnd.clientY
|
|
41257
41292
|
},
|
|
41258
41293
|
this.state
|
|
41259
41294
|
);
|
|
@@ -42922,7 +42957,9 @@ var init_excalidraw = __esm({
|
|
|
42922
42957
|
init_element();
|
|
42923
42958
|
init_i18n();
|
|
42924
42959
|
init_restore();
|
|
42925
|
-
|
|
42960
|
+
init_utils2();
|
|
42961
|
+
init_json();
|
|
42962
|
+
init_blob();
|
|
42926
42963
|
init_typeChecks();
|
|
42927
42964
|
init_constants();
|
|
42928
42965
|
init_mutateElement();
|
|
@@ -42938,7 +42975,10 @@ var init_excalidraw = __esm({
|
|
|
42938
42975
|
init_actionCanvas();
|
|
42939
42976
|
init_transform();
|
|
42940
42977
|
init_bounds();
|
|
42941
|
-
|
|
42978
|
+
init_appState();
|
|
42979
|
+
init_math();
|
|
42980
|
+
init_typeChecks();
|
|
42981
|
+
init_renderElement();
|
|
42942
42982
|
polyfill_default();
|
|
42943
42983
|
ExcalidrawBase = (props) => {
|
|
42944
42984
|
const {
|
|
@@ -43091,20 +43131,24 @@ export {
|
|
|
43091
43131
|
bumpVersion,
|
|
43092
43132
|
convertToExcalidrawElements,
|
|
43093
43133
|
defaultLang,
|
|
43094
|
-
elementPartiallyOverlapsWithOrContainsBBox,
|
|
43095
|
-
elementsOverlappingBBox,
|
|
43096
43134
|
exportToBlob,
|
|
43097
43135
|
exportToCanvas2 as exportToCanvas,
|
|
43098
43136
|
exportToClipboard,
|
|
43099
43137
|
exportToSvg2 as exportToSvg,
|
|
43100
43138
|
getCommonBounds,
|
|
43139
|
+
getDefaultAppState,
|
|
43140
|
+
getElementBounds,
|
|
43101
43141
|
getFreeDrawSvgPath,
|
|
43102
43142
|
getNonDeletedElements2 as getNonDeletedElements,
|
|
43103
43143
|
getSceneVersion,
|
|
43104
43144
|
getVisibleSceneBounds,
|
|
43105
|
-
|
|
43145
|
+
isArrowElement,
|
|
43146
|
+
isExcalidrawElement,
|
|
43147
|
+
isFreeDrawElement,
|
|
43106
43148
|
isInvisiblySmallElement,
|
|
43107
43149
|
isLinearElement,
|
|
43150
|
+
isTextElement,
|
|
43151
|
+
isValueInRange,
|
|
43108
43152
|
languages,
|
|
43109
43153
|
loadFromBlob,
|
|
43110
43154
|
loadLibraryFromBlob,
|
|
@@ -43118,6 +43162,7 @@ export {
|
|
|
43118
43162
|
restoreAppState,
|
|
43119
43163
|
restoreElements,
|
|
43120
43164
|
restoreLibraryItems,
|
|
43165
|
+
rotatePoint,
|
|
43121
43166
|
sceneCoordsToViewportCoords,
|
|
43122
43167
|
serializeAsJSON,
|
|
43123
43168
|
serializeLibraryAsJSON,
|