@excalidraw/excalidraw 0.17.1-c0b80a0 → 0.17.1-c329470
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-JGDL4H2X.js → chunk-3DLVY5XU.js} +8272 -6864
- package/dist/browser/dev/excalidraw-assets-dev/chunk-3DLVY5XU.js.map +7 -0
- package/dist/browser/dev/excalidraw-assets-dev/{chunk-V7NFEZA6.js → chunk-NOAEU4NM.js} +9 -2
- package/dist/browser/dev/excalidraw-assets-dev/chunk-NOAEU4NM.js.map +7 -0
- package/dist/browser/dev/excalidraw-assets-dev/{en-ZSVWGT55.js → en-7IBTMWBG.js} +2 -2
- package/dist/browser/dev/excalidraw-assets-dev/{image-RJG3J34Y.js → image-N5AC7SEK.js} +2 -6
- package/dist/browser/dev/index.css +85 -50
- package/dist/browser/dev/index.css.map +3 -3
- package/dist/browser/dev/index.js +4375 -3766
- package/dist/browser/dev/index.js.map +4 -4
- package/dist/browser/prod/excalidraw-assets/{chunk-LDVEIXGO.js → chunk-7CSIPVOW.js} +2 -2
- package/dist/browser/prod/excalidraw-assets/chunk-TX3BU7T2.js +47 -0
- package/dist/browser/prod/excalidraw-assets/{en-UPNEHLDS.js → en-LOGQBETY.js} +1 -1
- package/dist/browser/prod/excalidraw-assets/image-3V4U7GZE.js +1 -0
- package/dist/browser/prod/index.css +1 -1
- package/dist/browser/prod/index.js +40 -40
- package/dist/dev/index.css +85 -50
- package/dist/dev/index.css.map +3 -3
- package/dist/dev/index.js +8688 -6706
- package/dist/dev/index.js.map +4 -4
- package/dist/{prod/locales/en-ZXYG7GCR.json → dev/locales/en-V6KXFSCK.json} +8 -1
- package/dist/excalidraw/actions/actionAlign.d.ts +7 -6
- package/dist/excalidraw/actions/actionAlign.js +14 -14
- package/dist/excalidraw/actions/actionClipboard.d.ts +7 -3
- package/dist/excalidraw/actions/actionDeleteSelected.d.ts +7 -3
- package/dist/excalidraw/actions/actionDeleteSelected.js +103 -34
- package/dist/excalidraw/actions/actionDuplicateSelection.js +105 -95
- package/dist/excalidraw/actions/actionFlip.js +16 -7
- package/dist/excalidraw/actions/actionFrame.d.ts +493 -0
- package/dist/excalidraw/actions/actionFrame.js +45 -2
- package/dist/excalidraw/actions/actionGroup.js +6 -4
- package/dist/excalidraw/actions/actionProperties.js +145 -116
- package/dist/excalidraw/actions/actionSelectAll.js +4 -3
- package/dist/excalidraw/actions/shortcuts.d.ts +1 -1
- package/dist/excalidraw/actions/shortcuts.js +1 -0
- package/dist/excalidraw/actions/types.d.ts +1 -1
- package/dist/excalidraw/align.d.ts +2 -1
- package/dist/excalidraw/align.js +15 -6
- package/dist/excalidraw/clipboard.d.ts +27 -5
- package/dist/excalidraw/clipboard.js +55 -28
- package/dist/excalidraw/components/Actions.d.ts +2 -1
- package/dist/excalidraw/components/Actions.js +4 -2
- package/dist/excalidraw/components/ActiveConfirmDialog.d.ts +1 -1
- package/dist/excalidraw/components/ActiveConfirmDialog.js +2 -3
- package/dist/excalidraw/components/App.d.ts +1 -0
- package/dist/excalidraw/components/App.js +216 -111
- package/dist/excalidraw/components/ColorPicker/ColorInput.js +2 -3
- package/dist/excalidraw/components/ColorPicker/ColorPicker.js +2 -3
- package/dist/excalidraw/components/ColorPicker/CustomColorList.js +1 -1
- package/dist/excalidraw/components/ColorPicker/Picker.js +1 -1
- package/dist/excalidraw/components/ColorPicker/PickerColorList.js +1 -1
- package/dist/excalidraw/components/ColorPicker/ShadeList.js +1 -1
- package/dist/excalidraw/components/ColorPicker/colorPickerUtils.d.ts +1 -1
- package/dist/excalidraw/components/ColorPicker/colorPickerUtils.js +1 -1
- package/dist/excalidraw/components/CommandPalette/CommandPalette.js +3 -3
- package/dist/excalidraw/components/ConfirmDialog.js +17 -5
- package/dist/excalidraw/components/Dialog.js +2 -3
- package/dist/excalidraw/components/EyeDropper.d.ts +1 -1
- package/dist/excalidraw/components/EyeDropper.js +1 -1
- package/dist/excalidraw/components/IconPicker.d.ts +2 -2
- package/dist/excalidraw/components/IconPicker.js +56 -53
- package/dist/excalidraw/components/LayerUI.js +6 -6
- package/dist/excalidraw/components/LibraryMenu.d.ts +2 -16
- package/dist/excalidraw/components/LibraryMenu.js +70 -28
- package/dist/excalidraw/components/LibraryMenuHeaderContent.js +4 -5
- package/dist/excalidraw/components/MobileMenu.js +1 -1
- package/dist/excalidraw/components/OverwriteConfirm/OverwriteConfirm.js +2 -3
- package/dist/excalidraw/components/OverwriteConfirm/OverwriteConfirmState.d.ts +1 -1
- package/dist/excalidraw/components/OverwriteConfirm/OverwriteConfirmState.js +2 -3
- package/dist/excalidraw/components/Range.d.ts +9 -0
- package/dist/excalidraw/components/Range.js +24 -0
- package/dist/excalidraw/components/SearchMenu.d.ts +1 -1
- package/dist/excalidraw/components/SearchMenu.js +3 -4
- package/dist/excalidraw/components/Sidebar/Sidebar.d.ts +1 -1
- package/dist/excalidraw/components/Sidebar/Sidebar.js +2 -3
- package/dist/excalidraw/components/Stats/Collapsible.d.ts +2 -1
- package/dist/excalidraw/components/Stats/Collapsible.js +2 -2
- package/dist/excalidraw/components/Stats/Dimension.js +94 -8
- package/dist/excalidraw/components/Stats/MultiDimension.js +8 -5
- package/dist/excalidraw/components/Stats/Position.js +63 -3
- package/dist/excalidraw/components/Stats/index.js +21 -4
- package/dist/excalidraw/components/Stats/utils.d.ts +1 -1
- package/dist/excalidraw/components/Stats/utils.js +2 -55
- package/dist/excalidraw/components/TTDDialog/TTDDialog.js +1 -1
- package/dist/excalidraw/components/ToolButton.js +4 -9
- package/dist/excalidraw/components/hoc/withInternalFallback.js +3 -3
- package/dist/excalidraw/components/hyperlink/Hyperlink.js +6 -12
- package/dist/excalidraw/components/icons.d.ts +9 -0
- package/dist/excalidraw/components/icons.js +4 -4
- package/dist/excalidraw/components/main-menu/DefaultItems.js +2 -3
- package/dist/excalidraw/constants.d.ts +5 -1
- package/dist/excalidraw/constants.js +9 -1
- package/dist/excalidraw/context/tunnels.d.ts +2 -1
- package/dist/excalidraw/context/tunnels.js +3 -1
- package/dist/excalidraw/data/blob.d.ts +1 -0
- package/dist/excalidraw/data/blob.js +7 -3
- package/dist/excalidraw/data/filesystem.d.ts +2 -1
- package/dist/excalidraw/data/filesystem.js +1 -0
- package/dist/excalidraw/data/image.d.ts +0 -6
- package/dist/excalidraw/data/image.js +1 -43
- package/dist/excalidraw/data/index.js +6 -6
- package/dist/excalidraw/data/library.d.ts +9 -3
- package/dist/excalidraw/data/library.js +43 -6
- package/dist/excalidraw/data/restore.js +26 -8
- package/dist/excalidraw/data/url.d.ts +0 -1
- package/dist/excalidraw/data/url.js +2 -4
- package/dist/excalidraw/editor-jotai.d.ts +56 -0
- package/dist/excalidraw/editor-jotai.js +8 -0
- package/dist/excalidraw/element/binding.d.ts +9 -6
- package/dist/excalidraw/element/binding.js +124 -44
- package/dist/excalidraw/element/bounds.js +10 -0
- package/dist/excalidraw/element/cropElement.d.ts +5 -0
- package/dist/excalidraw/element/cropElement.js +28 -1
- package/dist/excalidraw/element/dragElements.js +13 -7
- package/dist/excalidraw/element/elbowArrow.d.ts +16 -0
- package/dist/excalidraw/element/elbowArrow.js +1268 -0
- package/dist/excalidraw/element/embeddable.js +4 -5
- package/dist/excalidraw/element/flowchart.d.ts +1 -1
- package/dist/excalidraw/element/flowchart.js +25 -9
- package/dist/excalidraw/element/heading.d.ts +5 -1
- package/dist/excalidraw/element/heading.js +5 -1
- package/dist/excalidraw/element/image.js +19 -5
- package/dist/excalidraw/element/linearElementEditor.d.ts +9 -10
- package/dist/excalidraw/element/linearElementEditor.js +97 -38
- package/dist/excalidraw/element/mutateElement.d.ts +3 -1
- package/dist/excalidraw/element/mutateElement.js +31 -4
- package/dist/excalidraw/element/newElement.d.ts +8 -12
- package/dist/excalidraw/element/newElement.js +36 -21
- package/dist/excalidraw/element/resizeElements.d.ts +20 -5
- package/dist/excalidraw/element/resizeElements.js +593 -361
- package/dist/excalidraw/element/sortElements.js +1 -4
- package/dist/excalidraw/element/types.d.ts +23 -1
- package/dist/excalidraw/fonts/Fonts.d.ts +0 -16
- package/dist/excalidraw/fonts/Fonts.js +6 -31
- package/dist/excalidraw/frame.d.ts +11 -5
- package/dist/excalidraw/frame.js +146 -35
- package/dist/excalidraw/groups.js +3 -0
- package/dist/excalidraw/hooks/useLibraryItemSvg.d.ts +1 -1
- package/dist/excalidraw/hooks/useLibraryItemSvg.js +2 -3
- package/dist/excalidraw/hooks/useScrollPosition.js +1 -1
- package/dist/excalidraw/i18n.js +3 -4
- package/dist/excalidraw/index.js +3 -4
- package/dist/excalidraw/locales/en.json +8 -1
- package/dist/excalidraw/renderer/interactiveScene.js +43 -32
- package/dist/excalidraw/renderer/staticScene.js +6 -4
- package/dist/excalidraw/renderer/staticSvgScene.js +1 -1
- package/dist/excalidraw/scene/Shape.js +40 -17
- package/dist/excalidraw/scene/comparisons.d.ts +0 -477
- package/dist/excalidraw/scene/comparisons.js +0 -37
- package/dist/excalidraw/scene/export.d.ts +7 -0
- package/dist/excalidraw/scene/export.js +107 -43
- package/dist/excalidraw/scene/index.d.ts +1 -1
- package/dist/excalidraw/scene/index.js +1 -1
- package/dist/excalidraw/scene/selection.js +4 -1
- package/dist/excalidraw/types.d.ts +15 -0
- package/dist/excalidraw/utility-types.d.ts +1 -0
- package/dist/excalidraw/utils.d.ts +8 -1
- package/dist/excalidraw/utils.js +9 -0
- package/dist/excalidraw/visualdebug.d.ts +8 -1
- package/dist/excalidraw/visualdebug.js +3 -0
- package/dist/math/line.d.ts +19 -0
- package/dist/math/line.js +32 -3
- package/dist/math/point.d.ts +10 -0
- package/dist/math/point.js +12 -1
- package/dist/prod/index.css +1 -1
- package/dist/prod/index.js +29 -44
- package/dist/{dev/locales/en-ZXYG7GCR.json → prod/locales/en-V6KXFSCK.json} +8 -1
- package/package.json +5 -2
- package/dist/browser/dev/excalidraw-assets-dev/chunk-JGDL4H2X.js.map +0 -7
- package/dist/browser/dev/excalidraw-assets-dev/chunk-V7NFEZA6.js.map +0 -7
- package/dist/browser/prod/excalidraw-assets/chunk-S2XKB3DE.js +0 -62
- package/dist/browser/prod/excalidraw-assets/image-OFI2YYMP.js +0 -1
- package/dist/excalidraw/element/routing.d.ts +0 -12
- package/dist/excalidraw/element/routing.js +0 -642
- package/dist/excalidraw/jotai.d.ts +0 -34
- package/dist/excalidraw/jotai.js +0 -18
- /package/dist/browser/dev/excalidraw-assets-dev/{en-ZSVWGT55.js.map → en-7IBTMWBG.js.map} +0 -0
- /package/dist/browser/dev/excalidraw-assets-dev/{image-RJG3J34Y.js.map → image-N5AC7SEK.js.map} +0 -0
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import { pointFrom, pointRotateRads } from "../../../math";
|
|
2
2
|
import { bindOrUnbindLinearElements, updateBoundElements, } from "../../element/binding";
|
|
3
3
|
import { mutateElement } from "../../element/mutateElement";
|
|
4
|
-
import {
|
|
5
|
-
import { getApproxMinLineHeight, getApproxMinLineWidth, getBoundTextElement, getBoundTextMaxWidth, handleBindTextResize, } from "../../element/textElement";
|
|
4
|
+
import { getBoundTextElement } from "../../element/textElement";
|
|
6
5
|
import { isFrameLikeElement, isLinearElement, isTextElement, } from "../../element/typeChecks";
|
|
7
6
|
import { getSelectedGroupIds, getElementsInGroup, isInGroup, } from "../../groups";
|
|
8
|
-
import { getFontString } from "../../utils";
|
|
9
7
|
export const SMALLEST_DELTA = 0.01;
|
|
10
8
|
export const isPropertyEditable = (element, property) => {
|
|
11
9
|
if (property === "height" && isTextElement(element)) {
|
|
@@ -55,57 +53,6 @@ export const newOrigin = (x1, y1, w1, h1, w2, h2, angle) => {
|
|
|
55
53
|
((h2 - h1) / 2) * Math.cos(angle),
|
|
56
54
|
};
|
|
57
55
|
};
|
|
58
|
-
export const resizeElement = (nextWidth, nextHeight, keepAspectRatio, origElement, elementsMap, elements, scene, shouldInformMutation = true) => {
|
|
59
|
-
const latestElement = elementsMap.get(origElement.id);
|
|
60
|
-
if (!latestElement) {
|
|
61
|
-
return;
|
|
62
|
-
}
|
|
63
|
-
let boundTextFont = {};
|
|
64
|
-
const boundTextElement = getBoundTextElement(latestElement, elementsMap);
|
|
65
|
-
if (boundTextElement) {
|
|
66
|
-
const minWidth = getApproxMinLineWidth(getFontString(boundTextElement), boundTextElement.lineHeight);
|
|
67
|
-
const minHeight = getApproxMinLineHeight(boundTextElement.fontSize, boundTextElement.lineHeight);
|
|
68
|
-
nextWidth = Math.max(nextWidth, minWidth);
|
|
69
|
-
nextHeight = Math.max(nextHeight, minHeight);
|
|
70
|
-
}
|
|
71
|
-
mutateElement(latestElement, {
|
|
72
|
-
...newOrigin(latestElement.x, latestElement.y, latestElement.width, latestElement.height, nextWidth, nextHeight, latestElement.angle),
|
|
73
|
-
width: nextWidth,
|
|
74
|
-
height: nextHeight,
|
|
75
|
-
...rescalePointsInElement(origElement, nextWidth, nextHeight, true),
|
|
76
|
-
}, shouldInformMutation);
|
|
77
|
-
updateBindings(latestElement, elementsMap, elements, scene, {
|
|
78
|
-
newSize: {
|
|
79
|
-
width: nextWidth,
|
|
80
|
-
height: nextHeight,
|
|
81
|
-
},
|
|
82
|
-
});
|
|
83
|
-
if (boundTextElement) {
|
|
84
|
-
boundTextFont = {
|
|
85
|
-
fontSize: boundTextElement.fontSize,
|
|
86
|
-
};
|
|
87
|
-
if (keepAspectRatio) {
|
|
88
|
-
const updatedElement = {
|
|
89
|
-
...latestElement,
|
|
90
|
-
width: nextWidth,
|
|
91
|
-
height: nextHeight,
|
|
92
|
-
};
|
|
93
|
-
const nextFont = measureFontSizeFromWidth(boundTextElement, elementsMap, getBoundTextMaxWidth(updatedElement, boundTextElement));
|
|
94
|
-
boundTextFont = {
|
|
95
|
-
fontSize: nextFont?.size ?? boundTextElement.fontSize,
|
|
96
|
-
};
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
updateBoundElements(latestElement, elementsMap, {
|
|
100
|
-
newSize: { width: nextWidth, height: nextHeight },
|
|
101
|
-
});
|
|
102
|
-
if (boundTextElement && boundTextFont) {
|
|
103
|
-
mutateElement(boundTextElement, {
|
|
104
|
-
fontSize: boundTextFont.fontSize,
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
handleBindTextResize(latestElement, elementsMap, "e", keepAspectRatio);
|
|
108
|
-
};
|
|
109
56
|
export const moveElement = (newTopLeftX, newTopLeftY, originalElement, elementsMap, elements, scene, originalElementsMap, shouldInformMutation = true) => {
|
|
110
57
|
const latestElement = elementsMap.get(originalElement.id);
|
|
111
58
|
if (!latestElement) {
|
|
@@ -153,7 +100,7 @@ export const getAtomicUnits = (targetElements, appState) => {
|
|
|
153
100
|
};
|
|
154
101
|
export const updateBindings = (latestElement, elementsMap, elements, scene, options) => {
|
|
155
102
|
if (isLinearElement(latestElement)) {
|
|
156
|
-
bindOrUnbindLinearElements([latestElement], elementsMap, elements, scene, true, []);
|
|
103
|
+
bindOrUnbindLinearElements([latestElement], elementsMap, elements, scene, true, [], options?.zoom);
|
|
157
104
|
}
|
|
158
105
|
else {
|
|
159
106
|
updateBoundElements(latestElement, elementsMap, options);
|
|
@@ -17,7 +17,7 @@ import { TTDDialogPanels } from "./TTDDialogPanels";
|
|
|
17
17
|
import { convertMermaidToExcalidraw, insertToEditor, saveMermaidDataToStorage, } from "./common";
|
|
18
18
|
import { ArrowRightIcon } from "../icons";
|
|
19
19
|
import "./TTDDialog.scss";
|
|
20
|
-
import { atom, useAtom } from "jotai";
|
|
20
|
+
import { atom, useAtom } from "../../editor-jotai";
|
|
21
21
|
import { trackEvent } from "../../analytics";
|
|
22
22
|
import { InlineIcon } from "../InlineIcon";
|
|
23
23
|
import { TTDDialogSubmitShortcut } from "./TTDDialogSubmitShortcut";
|
|
@@ -6,11 +6,11 @@ import { useExcalidrawContainer } from "./App";
|
|
|
6
6
|
import { AbortError } from "../errors";
|
|
7
7
|
import Spinner from "./Spinner";
|
|
8
8
|
import { isPromiseLike } from "../utils";
|
|
9
|
-
export const ToolButton = React.forwardRef((props, ref) => {
|
|
9
|
+
export const ToolButton = React.forwardRef(({ size = "medium", visible = true, className = "", ...props }, ref) => {
|
|
10
10
|
const { id: excalId } = useExcalidrawContainer();
|
|
11
11
|
const innerRef = React.useRef(null);
|
|
12
12
|
React.useImperativeHandle(ref, () => innerRef.current);
|
|
13
|
-
const sizeCn = `ToolIcon_size_${
|
|
13
|
+
const sizeCn = `ToolIcon_size_${size}`;
|
|
14
14
|
const [isLoading, setIsLoading] = useState(false);
|
|
15
15
|
const isMountedRef = useRef(true);
|
|
16
16
|
const onClick = async (event) => {
|
|
@@ -46,7 +46,7 @@ export const ToolButton = React.forwardRef((props, ref) => {
|
|
|
46
46
|
props.type === "icon" ||
|
|
47
47
|
props.type === "submit") {
|
|
48
48
|
const type = (props.type === "icon" ? "button" : props.type);
|
|
49
|
-
return (_jsxs("button", { className: clsx("ToolIcon_type_button", sizeCn,
|
|
49
|
+
return (_jsxs("button", { className: clsx("ToolIcon_type_button", sizeCn, className, visible && !props.hidden
|
|
50
50
|
? "ToolIcon_type_button--show"
|
|
51
51
|
: "ToolIcon_type_button--hide", {
|
|
52
52
|
ToolIcon: !props.hidden,
|
|
@@ -54,7 +54,7 @@ export const ToolButton = React.forwardRef((props, ref) => {
|
|
|
54
54
|
"ToolIcon--plain": props.type === "icon",
|
|
55
55
|
}), style: props.style, "data-testid": props["data-testid"], hidden: props.hidden, title: props.title, "aria-label": props["aria-label"], type: type, onClick: onClick, ref: innerRef, disabled: isLoading || props.isLoading || !!props.disabled, children: [(props.icon || props.label) && (_jsxs("div", { className: "ToolIcon__icon", "aria-hidden": "true", "aria-disabled": !!props.disabled, children: [props.icon || props.label, props.keyBindingLabel && (_jsx("span", { className: "ToolIcon__keybinding", children: props.keyBindingLabel })), props.isLoading && _jsx(Spinner, {})] })), props.showAriaLabel && (_jsxs("div", { className: "ToolIcon__label", children: [props["aria-label"], " ", isLoading && _jsx(Spinner, {})] })), props.children] }));
|
|
56
56
|
}
|
|
57
|
-
return (_jsxs("label", { className: clsx("ToolIcon",
|
|
57
|
+
return (_jsxs("label", { className: clsx("ToolIcon", className), title: props.title, onPointerDown: (event) => {
|
|
58
58
|
lastPointerTypeRef.current = event.pointerType || null;
|
|
59
59
|
props.onPointerDown?.({ pointerType: event.pointerType || null });
|
|
60
60
|
}, onPointerUp: () => {
|
|
@@ -65,9 +65,4 @@ export const ToolButton = React.forwardRef((props, ref) => {
|
|
|
65
65
|
props.onChange?.({ pointerType: lastPointerTypeRef.current });
|
|
66
66
|
}, checked: props.checked, ref: innerRef }), _jsxs("div", { className: "ToolIcon__icon", children: [props.icon, props.keyBindingLabel && (_jsx("span", { className: "ToolIcon__keybinding", children: props.keyBindingLabel }))] })] }));
|
|
67
67
|
});
|
|
68
|
-
ToolButton.defaultProps = {
|
|
69
|
-
visible: true,
|
|
70
|
-
className: "",
|
|
71
|
-
size: "medium",
|
|
72
|
-
};
|
|
73
68
|
ToolButton.displayName = "ToolButton";
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { atom, useAtom } from "jotai";
|
|
3
2
|
import { useLayoutEffect, useRef } from "react";
|
|
4
3
|
import { useTunnels } from "../../context/tunnels";
|
|
4
|
+
import { atom } from "../../editor-jotai";
|
|
5
5
|
export const withInternalFallback = (componentName, Component) => {
|
|
6
6
|
const renderAtom = atom(0);
|
|
7
7
|
const WrapperComponent = (props) => {
|
|
8
|
-
const {
|
|
8
|
+
const { tunnelsJotai: { useAtom }, } = useTunnels();
|
|
9
9
|
// for rerenders
|
|
10
|
-
const [, setCounter] = useAtom(renderAtom
|
|
10
|
+
const [, setCounter] = useAtom(renderAtom);
|
|
11
11
|
// for initial & subsequent renders. Tracked as component state
|
|
12
12
|
// due to excalidraw multi-instance scanerios.
|
|
13
13
|
const metaRef = useRef({
|
|
@@ -118,12 +118,14 @@ export const Hyperlink = ({ element, elementsMap, setAppState, onLinkOpen, setTo
|
|
|
118
118
|
};
|
|
119
119
|
}, [handleSubmit]);
|
|
120
120
|
useEffect(() => {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
inputRef.current &&
|
|
121
|
+
if (isEditing &&
|
|
122
|
+
inputRef?.current &&
|
|
124
123
|
!(device.viewport.isMobile || device.isTouchScreen)) {
|
|
125
124
|
inputRef.current.select();
|
|
126
125
|
}
|
|
126
|
+
}, [isEditing, device.viewport.isMobile, device.isTouchScreen]);
|
|
127
|
+
useEffect(() => {
|
|
128
|
+
let timeoutId = null;
|
|
127
129
|
const handlePointerMove = (event) => {
|
|
128
130
|
if (isEditing) {
|
|
129
131
|
return;
|
|
@@ -145,15 +147,7 @@ export const Hyperlink = ({ element, elementsMap, setAppState, onLinkOpen, setTo
|
|
|
145
147
|
clearTimeout(timeoutId);
|
|
146
148
|
}
|
|
147
149
|
};
|
|
148
|
-
}, [
|
|
149
|
-
appState,
|
|
150
|
-
element,
|
|
151
|
-
isEditing,
|
|
152
|
-
setAppState,
|
|
153
|
-
elementsMap,
|
|
154
|
-
device.viewport.isMobile,
|
|
155
|
-
device.isTouchScreen,
|
|
156
|
-
]);
|
|
150
|
+
}, [appState, element, isEditing, setAppState, elementsMap]);
|
|
157
151
|
const handleRemove = useCallback(() => {
|
|
158
152
|
trackEvent("hyperlink", "delete");
|
|
159
153
|
mutateElement(element, { link: null });
|
|
@@ -135,6 +135,15 @@ export declare const ArrowheadDiamondIcon: React.MemoExoticComponent<({ flip }:
|
|
|
135
135
|
export declare const ArrowheadDiamondOutlineIcon: React.MemoExoticComponent<({ flip }: {
|
|
136
136
|
flip?: boolean | undefined;
|
|
137
137
|
}) => JSX.Element>;
|
|
138
|
+
export declare const ArrowheadCrowfootIcon: React.MemoExoticComponent<({ flip }: {
|
|
139
|
+
flip?: boolean | undefined;
|
|
140
|
+
}) => JSX.Element>;
|
|
141
|
+
export declare const ArrowheadCrowfootOneIcon: React.MemoExoticComponent<({ flip }: {
|
|
142
|
+
flip?: boolean | undefined;
|
|
143
|
+
}) => JSX.Element>;
|
|
144
|
+
export declare const ArrowheadCrowfootOneOrManyIcon: React.MemoExoticComponent<({ flip }: {
|
|
145
|
+
flip?: boolean | undefined;
|
|
146
|
+
}) => JSX.Element>;
|
|
138
147
|
export declare const FontSizeSmallIcon: JSX.Element;
|
|
139
148
|
export declare const FontSizeMediumIcon: JSX.Element;
|
|
140
149
|
export declare const FontSizeLargeIcon: JSX.Element;
|
|
@@ -184,10 +184,7 @@ export const SloppinessCartoonistIcon = createIcon(_jsx("path", { d: "M2.5 11.93
|
|
|
184
184
|
export const EdgeSharpIcon = createIcon(_jsxs("svg", { strokeWidth: "1.5", children: [_jsx("path", { d: "M3.33334 9.99998V6.66665C3.33334 6.04326 3.33403 4.9332 3.33539 3.33646C4.95233 3.33436 6.06276 3.33331 6.66668 3.33331H10" }), _jsx("path", { d: "M13.3333 3.33331V3.34331" }), _jsx("path", { d: "M16.6667 3.33331V3.34331" }), _jsx("path", { d: "M16.6667 6.66669V6.67669" }), _jsx("path", { d: "M16.6667 10V10.01" }), _jsx("path", { d: "M3.33334 13.3333V13.3433" }), _jsx("path", { d: "M16.6667 13.3333V13.3433" }), _jsx("path", { d: "M3.33334 16.6667V16.6767" }), _jsx("path", { d: "M6.66666 16.6667V16.6767" }), _jsx("path", { d: "M10 16.6667V16.6767" }), _jsx("path", { d: "M13.3333 16.6667V16.6767" }), _jsx("path", { d: "M16.6667 16.6667V16.6767" })] }), modifiedTablerIconProps);
|
|
185
185
|
// tabler-icons: border-radius
|
|
186
186
|
export const EdgeRoundIcon = createIcon(_jsxs("g", { strokeWidth: "1.5", stroke: "currentColor", strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("path", { stroke: "none", d: "M0 0h24v24H0z", fill: "none" }), _jsx("path", { d: "M4 12v-4a4 4 0 0 1 4 -4h4" }), _jsx("line", { x1: "16", y1: "4", x2: "16", y2: "4.01" }), _jsx("line", { x1: "20", y1: "4", x2: "20", y2: "4.01" }), _jsx("line", { x1: "20", y1: "8", x2: "20", y2: "8.01" }), _jsx("line", { x1: "20", y1: "12", x2: "20", y2: "12.01" }), _jsx("line", { x1: "4", y1: "16", x2: "4", y2: "16.01" }), _jsx("line", { x1: "20", y1: "16", x2: "20", y2: "16.01" }), _jsx("line", { x1: "4", y1: "20", x2: "4", y2: "20.01" }), _jsx("line", { x1: "8", y1: "20", x2: "8", y2: "20.01" }), _jsx("line", { x1: "12", y1: "20", x2: "12", y2: "20.01" }), _jsx("line", { x1: "16", y1: "20", x2: "16", y2: "20.01" }), _jsx("line", { x1: "20", y1: "20", x2: "20", y2: "20.01" })] }), tablerIconProps);
|
|
187
|
-
export const ArrowheadNoneIcon = createIcon(_jsx("path", { d: "
|
|
188
|
-
width: 40,
|
|
189
|
-
height: 20,
|
|
190
|
-
});
|
|
187
|
+
export const ArrowheadNoneIcon = createIcon(_jsxs("g", { stroke: "currentColor", opacity: 0.3, strokeWidth: 2, children: [_jsx("path", { d: "M12 12l9 0" }), _jsx("path", { d: "M3 9l6 6" }), _jsx("path", { d: "M3 15l6 -6" })] }), tablerIconProps);
|
|
191
188
|
export const ArrowheadArrowIcon = React.memo(({ flip = false }) => createIcon(_jsxs("g", { transform: flip ? "translate(40, 0) scale(-1, 1)" : "", stroke: "currentColor", strokeWidth: 2, fill: "none", children: [_jsx("path", { d: "M34 10H6M34 10L27 5M34 10L27 15" }), _jsx("path", { d: "M27.5 5L34.5 10L27.5 15" })] }), { width: 40, height: 20 }));
|
|
192
189
|
export const ArrowheadCircleIcon = React.memo(({ flip = false }) => createIcon(_jsxs("g", { stroke: "currentColor", fill: "currentColor", transform: flip ? "translate(40, 0) scale(-1, 1)" : "", children: [_jsx("path", { d: "M32 10L6 10", strokeWidth: 2 }), _jsx("circle", { r: "4", transform: "matrix(-1 0 0 1 30 10)" })] }), { width: 40, height: 20 }));
|
|
193
190
|
export const ArrowheadCircleOutlineIcon = React.memo(({ flip = false }) => createIcon(_jsxs("g", { stroke: "currentColor", fill: "none", transform: flip ? "translate(40, 0) scale(-1, 1)" : "", strokeWidth: 2, children: [_jsx("path", { d: "M26 10L6 10" }), _jsx("circle", { r: "4", transform: "matrix(-1 0 0 1 30 10)" })] }), { width: 40, height: 20 }));
|
|
@@ -196,6 +193,9 @@ export const ArrowheadTriangleIcon = React.memo(({ flip = false }) => createIcon
|
|
|
196
193
|
export const ArrowheadTriangleOutlineIcon = React.memo(({ flip = false }) => createIcon(_jsxs("g", { stroke: "currentColor", fill: "none", transform: flip ? "translate(40, 0) scale(-1, 1)" : "", strokeWidth: 2, strokeLinejoin: "round", children: [_jsx("path", { d: "M6,9.5H27" }), _jsx("path", { d: "M27,5L34,10L27,14Z", fill: "none" })] }), { width: 40, height: 20 }));
|
|
197
194
|
export const ArrowheadDiamondIcon = React.memo(({ flip = false }) => createIcon(_jsxs("g", { stroke: "currentColor", fill: "currentColor", transform: flip ? "translate(40, 0) scale(-1, 1)" : "", strokeLinejoin: "round", strokeWidth: 2, children: [_jsx("path", { d: "M6,9.5H20" }), _jsx("path", { d: "M27,5L34,10L27,14L20,9.5Z" })] }), { width: 40, height: 20 }));
|
|
198
195
|
export const ArrowheadDiamondOutlineIcon = React.memo(({ flip = false }) => createIcon(_jsxs("g", { stroke: "currentColor", fill: "none", transform: flip ? "translate(40, 0) scale(-1, 1)" : "", strokeLinejoin: "round", strokeWidth: 2, children: [_jsx("path", { d: "M6,9.5H20" }), _jsx("path", { d: "M27,5L34,10L27,14L20,9.5Z" })] }), { width: 40, height: 20 }));
|
|
196
|
+
export const ArrowheadCrowfootIcon = React.memo(({ flip = false }) => createIcon(_jsx("g", { stroke: "currentColor", fill: "none", transform: flip ? "" : "translate(40, 0) scale(-1, 1)", strokeLinejoin: "round", strokeWidth: 2, children: _jsx("path", { d: "M34,10 H6 M15,10 L7,5 M15,10 L7,15" }) }), { width: 40, height: 20 }));
|
|
197
|
+
export const ArrowheadCrowfootOneIcon = React.memo(({ flip = false }) => createIcon(_jsx("g", { stroke: "currentColor", fill: "none", transform: flip ? "" : "translate(40, 0) scale(-1, 1)", strokeLinejoin: "round", strokeWidth: 2, children: _jsx("path", { d: "M34,10 H6 M15,10 L15,15 L15,5" }) }), { width: 40, height: 20 }));
|
|
198
|
+
export const ArrowheadCrowfootOneOrManyIcon = React.memo(({ flip = false }) => createIcon(_jsx("g", { stroke: "currentColor", fill: "none", transform: flip ? "" : "translate(40, 0) scale(-1, 1)", strokeLinejoin: "round", strokeWidth: 2, children: _jsx("path", { d: "M34,10 H6 M15,10 L15,16 L15,4 M15,10 L7,5 M15,10 L7,15" }) }), { width: 40, height: 20 }));
|
|
199
199
|
export const FontSizeSmallIcon = createIcon(_jsxs(_Fragment, { children: [_jsx("g", { clipPath: "url(#a)", children: _jsx("path", { d: "M14.167 6.667a3.333 3.333 0 0 0-3.334-3.334H9.167a3.333 3.333 0 0 0 0 6.667h1.666a3.333 3.333 0 0 1 0 6.667H9.167a3.333 3.333 0 0 1-3.334-3.334", stroke: "currentColor", strokeWidth: "1.25", strokeLinecap: "round", strokeLinejoin: "round" }) }), _jsx("defs", { children: _jsx("clipPath", { id: "a", children: _jsx("path", { fill: "#fff", d: "M0 0h20v20H0z" }) }) })] }), modifiedTablerIconProps);
|
|
200
200
|
export const FontSizeMediumIcon = createIcon(_jsxs(_Fragment, { children: [_jsx("g", { clipPath: "url(#a)", children: _jsx("path", { d: "M5 16.667V3.333L10 15l5-11.667v13.334", stroke: "currentColor", strokeWidth: "1.25", strokeLinecap: "round", strokeLinejoin: "round" }) }), _jsx("defs", { children: _jsx("clipPath", { id: "a", children: _jsx("path", { fill: "#fff", d: "M0 0h20v20H0z" }) }) })] }), modifiedTablerIconProps);
|
|
201
201
|
export const FontSizeLargeIcon = createIcon(_jsxs(_Fragment, { children: [_jsx("g", { clipPath: "url(#a)", children: _jsx("path", { d: "M5.833 3.333v13.334h8.334", stroke: "currentColor", strokeWidth: "1.25", strokeLinecap: "round", strokeLinejoin: "round" }) }), _jsx("defs", { children: _jsx("clipPath", { id: "a", children: _jsx("path", { fill: "#fff", d: "M0 0h20v20H0z" }) }) })] }), modifiedTablerIconProps);
|
|
@@ -8,9 +8,8 @@ import DropdownMenuItem from "../dropdownMenu/DropdownMenuItem";
|
|
|
8
8
|
import DropdownMenuItemLink from "../dropdownMenu/DropdownMenuItemLink";
|
|
9
9
|
import { actionClearCanvas, actionLoadScene, actionSaveToActiveFile, actionShortcuts, actionToggleSearchMenu, actionToggleTheme, } from "../../actions";
|
|
10
10
|
import clsx from "clsx";
|
|
11
|
-
import { useSetAtom } from "jotai";
|
|
12
11
|
import { activeConfirmDialogAtom } from "../ActiveConfirmDialog";
|
|
13
|
-
import {
|
|
12
|
+
import { useSetAtom } from "../../editor-jotai";
|
|
14
13
|
import { useUIAppState } from "../../context/ui-appState";
|
|
15
14
|
import { openConfirmModal } from "../OverwriteConfirm/OverwriteConfirmState";
|
|
16
15
|
import Trans from "../Trans";
|
|
@@ -79,7 +78,7 @@ export const Help = () => {
|
|
|
79
78
|
Help.displayName = "Help";
|
|
80
79
|
export const ClearCanvas = () => {
|
|
81
80
|
const { t } = useI18n();
|
|
82
|
-
const setActiveConfirmDialog = useSetAtom(activeConfirmDialogAtom
|
|
81
|
+
const setActiveConfirmDialog = useSetAtom(activeConfirmDialogAtom);
|
|
83
82
|
const actionManager = useExcalidrawActionManager();
|
|
84
83
|
if (!actionManager.isActionEnabled(actionClearCanvas)) {
|
|
85
84
|
return null;
|
|
@@ -161,7 +161,6 @@ export declare const IMAGE_MIME_TYPES: {
|
|
|
161
161
|
readonly avif: "image/avif";
|
|
162
162
|
readonly jfif: "image/jfif";
|
|
163
163
|
};
|
|
164
|
-
export declare const ALLOWED_PASTE_MIME_TYPES: readonly ["text/plain", "text/html"];
|
|
165
164
|
export declare const MIME_TYPES: {
|
|
166
165
|
readonly svg: "image/svg+xml";
|
|
167
166
|
readonly png: "image/png";
|
|
@@ -172,6 +171,8 @@ export declare const MIME_TYPES: {
|
|
|
172
171
|
readonly ico: "image/x-icon";
|
|
173
172
|
readonly avif: "image/avif";
|
|
174
173
|
readonly jfif: "image/jfif";
|
|
174
|
+
readonly text: "text/plain";
|
|
175
|
+
readonly html: "text/html";
|
|
175
176
|
readonly json: "application/json";
|
|
176
177
|
readonly excalidraw: "application/vnd.excalidraw+json";
|
|
177
178
|
readonly excalidrawlib: "application/vnd.excalidrawlib+json";
|
|
@@ -179,6 +180,7 @@ export declare const MIME_TYPES: {
|
|
|
179
180
|
readonly "excalidraw.png": "image/png";
|
|
180
181
|
readonly binary: "application/octet-stream";
|
|
181
182
|
};
|
|
183
|
+
export declare const ALLOWED_PASTE_MIME_TYPES: readonly ["text/plain", "text/html", ...("image/svg+xml" | "image/png" | "image/jpeg" | "image/gif" | "image/webp" | "image/bmp" | "image/x-icon" | "image/avif" | "image/jfif")[]];
|
|
182
184
|
export declare const EXPORT_IMAGE_TYPES: {
|
|
183
185
|
readonly png: "png";
|
|
184
186
|
readonly svg: "svg";
|
|
@@ -312,3 +314,5 @@ export declare const ARROW_TYPE: {
|
|
|
312
314
|
};
|
|
313
315
|
export declare const DEFAULT_REDUCED_GLOBAL_ALPHA = 0.3;
|
|
314
316
|
export declare const ELEMENT_LINK_KEY = "element";
|
|
317
|
+
/** used in tests */
|
|
318
|
+
export declare const ORIG_ID: unique symbol;
|
|
@@ -183,8 +183,9 @@ export const IMAGE_MIME_TYPES = {
|
|
|
183
183
|
avif: "image/avif",
|
|
184
184
|
jfif: "image/jfif",
|
|
185
185
|
};
|
|
186
|
-
export const ALLOWED_PASTE_MIME_TYPES = ["text/plain", "text/html"];
|
|
187
186
|
export const MIME_TYPES = {
|
|
187
|
+
text: "text/plain",
|
|
188
|
+
html: "text/html",
|
|
188
189
|
json: "application/json",
|
|
189
190
|
// excalidraw data
|
|
190
191
|
excalidraw: "application/vnd.excalidraw+json",
|
|
@@ -197,6 +198,11 @@ export const MIME_TYPES = {
|
|
|
197
198
|
// image
|
|
198
199
|
...IMAGE_MIME_TYPES,
|
|
199
200
|
};
|
|
201
|
+
export const ALLOWED_PASTE_MIME_TYPES = [
|
|
202
|
+
MIME_TYPES.text,
|
|
203
|
+
MIME_TYPES.html,
|
|
204
|
+
...Object.values(IMAGE_MIME_TYPES),
|
|
205
|
+
];
|
|
200
206
|
export const EXPORT_IMAGE_TYPES = {
|
|
201
207
|
png: "png",
|
|
202
208
|
svg: "svg",
|
|
@@ -372,3 +378,5 @@ export const ARROW_TYPE = {
|
|
|
372
378
|
};
|
|
373
379
|
export const DEFAULT_REDUCED_GLOBAL_ALPHA = 0.3;
|
|
374
380
|
export const ELEMENT_LINK_KEY = "element";
|
|
381
|
+
/** used in tests */
|
|
382
|
+
export const ORIG_ID = Symbol.for("__test__originalId__");
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import tunnel from "tunnel-rat";
|
|
3
|
+
import { createIsolation } from "jotai-scope";
|
|
3
4
|
export type Tunnel = ReturnType<typeof tunnel>;
|
|
4
5
|
type TunnelsContextValue = {
|
|
5
6
|
MainMenuTunnel: Tunnel;
|
|
@@ -12,7 +13,7 @@ type TunnelsContextValue = {
|
|
|
12
13
|
DefaultSidebarTabTriggersTunnel: Tunnel;
|
|
13
14
|
OverwriteConfirmDialogTunnel: Tunnel;
|
|
14
15
|
TTDDialogTriggerTunnel: Tunnel;
|
|
15
|
-
|
|
16
|
+
tunnelsJotai: ReturnType<typeof createIsolation>;
|
|
16
17
|
};
|
|
17
18
|
export declare const TunnelsContext: React.Context<TunnelsContextValue>;
|
|
18
19
|
export declare const useTunnels: () => TunnelsContextValue;
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import tunnel from "tunnel-rat";
|
|
3
|
+
import { createIsolation } from "jotai-scope";
|
|
3
4
|
export const TunnelsContext = React.createContext(null);
|
|
4
5
|
export const useTunnels = () => React.useContext(TunnelsContext);
|
|
6
|
+
const tunnelsJotai = createIsolation();
|
|
5
7
|
export const useInitializeTunnels = () => {
|
|
6
8
|
return React.useMemo(() => {
|
|
7
9
|
return {
|
|
@@ -15,7 +17,7 @@ export const useInitializeTunnels = () => {
|
|
|
15
17
|
DefaultSidebarTabTriggersTunnel: tunnel(),
|
|
16
18
|
OverwriteConfirmDialogTunnel: tunnel(),
|
|
17
19
|
TTDDialogTriggerTunnel: tunnel(),
|
|
18
|
-
|
|
20
|
+
tunnelsJotai,
|
|
19
21
|
};
|
|
20
22
|
}, []);
|
|
21
23
|
};
|
|
@@ -8,6 +8,7 @@ export declare const getMimeType: (blob: Blob | string) => string;
|
|
|
8
8
|
export declare const getFileHandleType: (handle: FileSystemHandle | null) => string | null;
|
|
9
9
|
export declare const isImageFileHandleType: (type: string | null) => type is "png" | "svg";
|
|
10
10
|
export declare const isImageFileHandle: (handle: FileSystemHandle | null) => boolean;
|
|
11
|
+
export declare const isSupportedImageFileType: (type: string | null | undefined) => boolean;
|
|
11
12
|
export declare const isSupportedImageFile: (blob: Blob | null | undefined) => blob is Blob & {
|
|
12
13
|
type: ValueOf<typeof IMAGE_MIME_TYPES>;
|
|
13
14
|
};
|
|
@@ -4,6 +4,7 @@ import { IMAGE_MIME_TYPES, MIME_TYPES } from "../constants";
|
|
|
4
4
|
import { clearElementsForExport } from "../element";
|
|
5
5
|
import { CanvasError, ImageSceneDataError } from "../errors";
|
|
6
6
|
import { calculateScrollCenter } from "../scene";
|
|
7
|
+
import { decodeSvgBase64Payload } from "../scene/export";
|
|
7
8
|
import { bytesToHexString, isPromiseLike } from "../utils";
|
|
8
9
|
import { base64ToString, stringToBase64, toByteString } from "./encode";
|
|
9
10
|
import { nativeFileSystemSupported } from "./filesystem";
|
|
@@ -41,7 +42,7 @@ const parseFileContents = async (blob) => {
|
|
|
41
42
|
}
|
|
42
43
|
if (blob.type === MIME_TYPES.svg) {
|
|
43
44
|
try {
|
|
44
|
-
return (
|
|
45
|
+
return decodeSvgBase64Payload({
|
|
45
46
|
svg: contents,
|
|
46
47
|
});
|
|
47
48
|
}
|
|
@@ -95,9 +96,12 @@ export const isImageFileHandle = (handle) => {
|
|
|
95
96
|
const type = getFileHandleType(handle);
|
|
96
97
|
return type === "png" || type === "svg";
|
|
97
98
|
};
|
|
99
|
+
export const isSupportedImageFileType = (type) => {
|
|
100
|
+
return !!type && Object.values(IMAGE_MIME_TYPES).includes(type);
|
|
101
|
+
};
|
|
98
102
|
export const isSupportedImageFile = (blob) => {
|
|
99
103
|
const { type } = blob || {};
|
|
100
|
-
return
|
|
104
|
+
return isSupportedImageFileType(type);
|
|
101
105
|
};
|
|
102
106
|
export const loadSceneOrLibraryFromBlob = async (blob,
|
|
103
107
|
/** @see restore.localAppState */
|
|
@@ -258,7 +262,7 @@ export const resizeImageFile = async (file, opts) => {
|
|
|
258
262
|
if (!isSupportedImageFile(file)) {
|
|
259
263
|
throw new Error("Error: unsupported file type", { cause: "UNSUPPORTED" });
|
|
260
264
|
}
|
|
261
|
-
return new File([await reduce.toBlob(file, { max: opts.maxWidthOrHeight })], file.name, {
|
|
265
|
+
return new File([await reduce.toBlob(file, { max: opts.maxWidthOrHeight, alpha: true })], file.name, {
|
|
262
266
|
type: opts.outputType || file.type,
|
|
263
267
|
});
|
|
264
268
|
};
|
|
@@ -12,9 +12,10 @@ export declare const fileSave: (blob: Blob | Promise<Blob>, opts: {
|
|
|
12
12
|
name: string;
|
|
13
13
|
/** file extension */
|
|
14
14
|
extension: FILE_EXTENSION;
|
|
15
|
+
mimeTypes?: string[];
|
|
15
16
|
description: string;
|
|
16
17
|
/** existing FileSystemHandle */
|
|
17
18
|
fileHandle?: FileSystemHandle | null;
|
|
18
19
|
}) => Promise<FileSystemHandle | null>;
|
|
19
|
-
export type { FileSystemHandle };
|
|
20
20
|
export { nativeFileSystemSupported };
|
|
21
|
+
export type { FileSystemHandle };
|
|
@@ -60,6 +60,7 @@ export const fileSave = (blob, opts) => {
|
|
|
60
60
|
fileName: `${opts.name}.${opts.extension}`,
|
|
61
61
|
description: opts.description,
|
|
62
62
|
extensions: [`.${opts.extension}`],
|
|
63
|
+
mimeTypes: opts.mimeTypes,
|
|
63
64
|
}, opts.fileHandle);
|
|
64
65
|
};
|
|
65
66
|
export { nativeFileSystemSupported };
|
|
@@ -7,9 +7,3 @@ export declare const encodePngMetadata: ({ blob, metadata, }: {
|
|
|
7
7
|
metadata: string;
|
|
8
8
|
}) => Promise<Blob>;
|
|
9
9
|
export declare const decodePngMetadata: (blob: Blob) => Promise<string>;
|
|
10
|
-
export declare const encodeSvgMetadata: ({ text }: {
|
|
11
|
-
text: string;
|
|
12
|
-
}) => string;
|
|
13
|
-
export declare const decodeSvgMetadata: ({ svg }: {
|
|
14
|
-
svg: string;
|
|
15
|
-
}) => string;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import decodePng from "png-chunks-extract";
|
|
2
2
|
import tEXt from "png-chunk-text";
|
|
3
3
|
import encodePng from "png-chunks-encode";
|
|
4
|
-
import {
|
|
4
|
+
import { encode, decode } from "./encode";
|
|
5
5
|
import { EXPORT_DATA_TYPES, MIME_TYPES } from "../constants";
|
|
6
6
|
import { blobToArrayBuffer } from "./blob";
|
|
7
7
|
// -----------------------------------------------------------------------------
|
|
@@ -47,45 +47,3 @@ export const decodePngMetadata = async (blob) => {
|
|
|
47
47
|
}
|
|
48
48
|
throw new Error("INVALID");
|
|
49
49
|
};
|
|
50
|
-
// -----------------------------------------------------------------------------
|
|
51
|
-
// SVG
|
|
52
|
-
// -----------------------------------------------------------------------------
|
|
53
|
-
export const encodeSvgMetadata = ({ text }) => {
|
|
54
|
-
const base64 = stringToBase64(JSON.stringify(encode({ text })), true /* is already byte string */);
|
|
55
|
-
let metadata = "";
|
|
56
|
-
metadata += `<!-- payload-type:${MIME_TYPES.excalidraw} -->`;
|
|
57
|
-
metadata += `<!-- payload-version:2 -->`;
|
|
58
|
-
metadata += "<!-- payload-start -->";
|
|
59
|
-
metadata += base64;
|
|
60
|
-
metadata += "<!-- payload-end -->";
|
|
61
|
-
return metadata;
|
|
62
|
-
};
|
|
63
|
-
export const decodeSvgMetadata = ({ svg }) => {
|
|
64
|
-
if (svg.includes(`payload-type:${MIME_TYPES.excalidraw}`)) {
|
|
65
|
-
const match = svg.match(/<!-- payload-start -->\s*(.+?)\s*<!-- payload-end -->/);
|
|
66
|
-
if (!match) {
|
|
67
|
-
throw new Error("INVALID");
|
|
68
|
-
}
|
|
69
|
-
const versionMatch = svg.match(/<!-- payload-version:(\d+) -->/);
|
|
70
|
-
const version = versionMatch?.[1] || "1";
|
|
71
|
-
const isByteString = version !== "1";
|
|
72
|
-
try {
|
|
73
|
-
const json = base64ToString(match[1], isByteString);
|
|
74
|
-
const encodedData = JSON.parse(json);
|
|
75
|
-
if (!("encoded" in encodedData)) {
|
|
76
|
-
// legacy, un-encoded scene JSON
|
|
77
|
-
if ("type" in encodedData &&
|
|
78
|
-
encodedData.type === EXPORT_DATA_TYPES.excalidraw) {
|
|
79
|
-
return json;
|
|
80
|
-
}
|
|
81
|
-
throw new Error("FAILED");
|
|
82
|
-
}
|
|
83
|
-
return decode(encodedData);
|
|
84
|
-
}
|
|
85
|
-
catch (error) {
|
|
86
|
-
console.error(error);
|
|
87
|
-
throw new Error("FAILED");
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
throw new Error("INVALID");
|
|
91
|
-
};
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { copyBlobToClipboardAsPng, copyTextToSystemClipboard, } from "../clipboard";
|
|
2
|
-
import { DEFAULT_EXPORT_PADDING, DEFAULT_FILENAME, isFirefox, MIME_TYPES, } from "../constants";
|
|
2
|
+
import { DEFAULT_EXPORT_PADDING, DEFAULT_FILENAME, IMAGE_MIME_TYPES, isFirefox, MIME_TYPES, } from "../constants";
|
|
3
3
|
import { getNonDeletedElements } from "../element";
|
|
4
4
|
import { isFrameLikeElement } from "../element/typeChecks";
|
|
5
|
+
import { getElementsOverlappingFrame } from "../frame";
|
|
5
6
|
import { t } from "../i18n";
|
|
6
|
-
import {
|
|
7
|
+
import { getSelectedElements, isSomeElementSelected } from "../scene";
|
|
7
8
|
import { exportToCanvas, exportToSvg } from "../scene/export";
|
|
8
9
|
import { cloneJSON } from "../utils";
|
|
9
10
|
import { canvasToBlob } from "./blob";
|
|
10
11
|
import { fileSave } from "./filesystem";
|
|
11
12
|
import { serializeAsJSON } from "./json";
|
|
12
|
-
import { getElementsOverlappingFrame } from "../frame";
|
|
13
13
|
export { loadFromBlob } from "./blob";
|
|
14
14
|
export { loadFromJSON, saveAsJSON } from "./json";
|
|
15
15
|
export const prepareElementsForExport = (elements, { selectedElementIds }, exportSelectionOnly) => {
|
|
@@ -60,6 +60,7 @@ export const exportCanvas = async (type, elements, appState, files, { exportBack
|
|
|
60
60
|
description: "Export to SVG",
|
|
61
61
|
name,
|
|
62
62
|
extension: appState.exportEmbedScene ? "excalidraw.svg" : "svg",
|
|
63
|
+
mimeTypes: [IMAGE_MIME_TYPES.svg],
|
|
63
64
|
fileHandle,
|
|
64
65
|
});
|
|
65
66
|
}
|
|
@@ -91,9 +92,8 @@ export const exportCanvas = async (type, elements, appState, files, { exportBack
|
|
|
91
92
|
return fileSave(blob, {
|
|
92
93
|
description: "Export to PNG",
|
|
93
94
|
name,
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
extension: /* appState.exportEmbedScene ? "excalidraw.png" : */ "png",
|
|
95
|
+
extension: appState.exportEmbedScene ? "excalidraw.png" : "png",
|
|
96
|
+
mimeTypes: [IMAGE_MIME_TYPES.png],
|
|
97
97
|
fileHandle,
|
|
98
98
|
});
|
|
99
99
|
}
|
|
@@ -37,7 +37,7 @@ export interface LibraryMigrationAdapter {
|
|
|
37
37
|
/** clears entire storage afterwards */
|
|
38
38
|
clear(): MaybePromise<void>;
|
|
39
39
|
}
|
|
40
|
-
export declare const libraryItemsAtom: import("jotai").PrimitiveAtom<{
|
|
40
|
+
export declare const libraryItemsAtom: import("jotai/vanilla/atom").PrimitiveAtom<{
|
|
41
41
|
status: "loading" | "loaded";
|
|
42
42
|
/** indicates whether library is initialized with library items (has gone
|
|
43
43
|
* through at least one update). Used in UI. Specific to this atom only. */
|
|
@@ -83,6 +83,7 @@ declare class Library {
|
|
|
83
83
|
}
|
|
84
84
|
export default Library;
|
|
85
85
|
export declare const distributeLibraryItemsOnSquareGrid: (libraryItems: LibraryItems) => ExcalidrawElement[];
|
|
86
|
+
export declare const validateLibraryUrl: (libraryUrl: string, validator?: string[] | ((libraryUrl: string) => boolean)) => true;
|
|
86
87
|
export declare const parseLibraryTokensFromUrl: () => {
|
|
87
88
|
libraryUrl: string;
|
|
88
89
|
idToken: string | null;
|
|
@@ -90,9 +91,14 @@ export declare const parseLibraryTokensFromUrl: () => {
|
|
|
90
91
|
export declare const getLibraryItemsHash: (items: LibraryItems) => number;
|
|
91
92
|
export declare const useHandleLibrary: (opts: {
|
|
92
93
|
excalidrawAPI: ExcalidrawImperativeAPI | null;
|
|
94
|
+
/**
|
|
95
|
+
* Return `true` if the library install url should be allowed.
|
|
96
|
+
* If not supplied, only the excalidraw.com base domain is allowed.
|
|
97
|
+
*/
|
|
98
|
+
validateLibraryUrl?: ((libraryUrl: string) => boolean) | undefined;
|
|
93
99
|
} & ({
|
|
94
100
|
/** @deprecated we recommend using `opts.adapter` instead */
|
|
95
|
-
getInitialLibraryItems?: () => MaybePromise<LibraryItemsSource
|
|
101
|
+
getInitialLibraryItems?: (() => MaybePromise<LibraryItemsSource>) | undefined;
|
|
96
102
|
} | {
|
|
97
103
|
adapter: LibraryPersistenceAdapter;
|
|
98
104
|
/**
|
|
@@ -102,5 +108,5 @@ export declare const useHandleLibrary: (opts: {
|
|
|
102
108
|
*
|
|
103
109
|
* Can be a different LibraryPersistenceAdapter.
|
|
104
110
|
*/
|
|
105
|
-
migrationAdapter?: LibraryMigrationAdapter;
|
|
111
|
+
migrationAdapter?: LibraryMigrationAdapter | undefined;
|
|
106
112
|
})) => void;
|