@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
|
@@ -97,8 +97,5 @@ const normalizeBoundElementsOrder = (elements) => {
|
|
|
97
97
|
return [...sortedElements];
|
|
98
98
|
};
|
|
99
99
|
export const normalizeElementOrder = (elements) => {
|
|
100
|
-
|
|
101
|
-
const ret = normalizeBoundElementsOrder(normalizeGroupElementOrder(elements));
|
|
102
|
-
// console.timeEnd();
|
|
103
|
-
return ret;
|
|
100
|
+
return normalizeBoundElementsOrder(normalizeGroupElementOrder(elements));
|
|
104
101
|
};
|
|
@@ -205,7 +205,7 @@ export type PointBinding = {
|
|
|
205
205
|
export type FixedPointBinding = Merge<PointBinding, {
|
|
206
206
|
fixedPoint: FixedPoint;
|
|
207
207
|
}>;
|
|
208
|
-
export type Arrowhead = "arrow" | "bar" | "dot" | "circle" | "circle_outline" | "triangle" | "triangle_outline" | "diamond" | "diamond_outline";
|
|
208
|
+
export type Arrowhead = "arrow" | "bar" | "dot" | "circle" | "circle_outline" | "triangle" | "triangle_outline" | "diamond" | "diamond_outline" | "crowfoot_one" | "crowfoot_many" | "crowfoot_one_or_many";
|
|
209
209
|
export type ExcalidrawLinearElement = _ExcalidrawElementBase & Readonly<{
|
|
210
210
|
type: "line" | "arrow";
|
|
211
211
|
points: readonly LocalPoint[];
|
|
@@ -215,6 +215,11 @@ export type ExcalidrawLinearElement = _ExcalidrawElementBase & Readonly<{
|
|
|
215
215
|
startArrowhead: Arrowhead | null;
|
|
216
216
|
endArrowhead: Arrowhead | null;
|
|
217
217
|
}>;
|
|
218
|
+
export type FixedSegment = {
|
|
219
|
+
start: LocalPoint;
|
|
220
|
+
end: LocalPoint;
|
|
221
|
+
index: number;
|
|
222
|
+
};
|
|
218
223
|
export type ExcalidrawArrowElement = ExcalidrawLinearElement & Readonly<{
|
|
219
224
|
type: "arrow";
|
|
220
225
|
elbowed: boolean;
|
|
@@ -223,6 +228,23 @@ export type ExcalidrawElbowArrowElement = Merge<ExcalidrawArrowElement, {
|
|
|
223
228
|
elbowed: true;
|
|
224
229
|
startBinding: FixedPointBinding | null;
|
|
225
230
|
endBinding: FixedPointBinding | null;
|
|
231
|
+
fixedSegments: FixedSegment[] | null;
|
|
232
|
+
/**
|
|
233
|
+
* Marks that the 3rd point should be used as the 2nd point of the arrow in
|
|
234
|
+
* order to temporarily hide the first segment of the arrow without losing
|
|
235
|
+
* the data from the points array. It allows creating the expected arrow
|
|
236
|
+
* path when the arrow with fixed segments is bound on a horizontal side and
|
|
237
|
+
* moved to a vertical and vica versa.
|
|
238
|
+
*/
|
|
239
|
+
startIsSpecial: boolean | null;
|
|
240
|
+
/**
|
|
241
|
+
* Marks that the 3rd point backwards from the end should be used as the 2nd
|
|
242
|
+
* point of the arrow in order to temporarily hide the last segment of the
|
|
243
|
+
* arrow without losing the data from the points array. It allows creating
|
|
244
|
+
* the expected arrow path when the arrow with fixed segments is bound on a
|
|
245
|
+
* horizontal side and moved to a vertical and vica versa.
|
|
246
|
+
*/
|
|
247
|
+
endIsSpecial: boolean | null;
|
|
226
248
|
}>;
|
|
227
249
|
export type ExcalidrawFreeDrawElement = _ExcalidrawElementBase & Readonly<{
|
|
228
250
|
type: "freedraw";
|
|
@@ -31,28 +31,12 @@ export declare class Fonts {
|
|
|
31
31
|
onLoaded: (fontFaces: readonly FontFace[]) => void;
|
|
32
32
|
/**
|
|
33
33
|
* Load font faces for a given scene and trigger scene update.
|
|
34
|
-
*
|
|
35
|
-
* FontFaceSet loadingdone event we listen on may not always
|
|
36
|
-
* fire (looking at you Safari), so on init we manually load all
|
|
37
|
-
* fonts and rerender scene text elements once done.
|
|
38
|
-
*
|
|
39
|
-
* For Safari we make sure to check against each loaded font face
|
|
40
|
-
* with the unique characters per family in the scene,
|
|
41
|
-
* otherwise fonts might remain unloaded.
|
|
42
34
|
*/
|
|
43
35
|
loadSceneFonts: () => Promise<FontFace[]>;
|
|
44
36
|
/**
|
|
45
37
|
* Load font faces for passed elements - use when the scene is unavailable (i.e. export).
|
|
46
|
-
*
|
|
47
|
-
* For Safari we make sure to check against each loaded font face,
|
|
48
|
-
* with the unique characters per family in the elements
|
|
49
|
-
* otherwise fonts might remain unloaded.
|
|
50
38
|
*/
|
|
51
39
|
static loadElementsFonts: (elements: readonly ExcalidrawElement[]) => Promise<FontFace[]>;
|
|
52
|
-
/**
|
|
53
|
-
* Load all registered font faces.
|
|
54
|
-
*/
|
|
55
|
-
static loadAllFonts: () => Promise<FontFace[]>;
|
|
56
40
|
/**
|
|
57
41
|
* Generate CSS @font-face declarations for the given elements.
|
|
58
42
|
*/
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FONT_FAMILY, FONT_FAMILY_FALLBACKS, CJK_HAND_DRAWN_FALLBACK_FONT, WINDOWS_EMOJI_FALLBACK_FONT,
|
|
1
|
+
import { FONT_FAMILY, FONT_FAMILY_FALLBACKS, CJK_HAND_DRAWN_FALLBACK_FONT, WINDOWS_EMOJI_FALLBACK_FONT, getFontFamilyFallbacks, } from "../constants";
|
|
2
2
|
import { isTextElement } from "../element";
|
|
3
3
|
import { charWidth, getContainerElement } from "../element/textElement";
|
|
4
4
|
import { containsCJK } from "../element/textWrapping";
|
|
@@ -94,43 +94,20 @@ export class Fonts {
|
|
|
94
94
|
};
|
|
95
95
|
/**
|
|
96
96
|
* Load font faces for a given scene and trigger scene update.
|
|
97
|
-
*
|
|
98
|
-
* FontFaceSet loadingdone event we listen on may not always
|
|
99
|
-
* fire (looking at you Safari), so on init we manually load all
|
|
100
|
-
* fonts and rerender scene text elements once done.
|
|
101
|
-
*
|
|
102
|
-
* For Safari we make sure to check against each loaded font face
|
|
103
|
-
* with the unique characters per family in the scene,
|
|
104
|
-
* otherwise fonts might remain unloaded.
|
|
105
97
|
*/
|
|
106
98
|
loadSceneFonts = async () => {
|
|
107
99
|
const sceneFamilies = this.getSceneFamilies();
|
|
108
|
-
const charsPerFamily =
|
|
109
|
-
? Fonts.getCharsPerFamily(this.scene.getNonDeletedElements())
|
|
110
|
-
: undefined;
|
|
100
|
+
const charsPerFamily = Fonts.getCharsPerFamily(this.scene.getNonDeletedElements());
|
|
111
101
|
return Fonts.loadFontFaces(sceneFamilies, charsPerFamily);
|
|
112
102
|
};
|
|
113
103
|
/**
|
|
114
104
|
* Load font faces for passed elements - use when the scene is unavailable (i.e. export).
|
|
115
|
-
*
|
|
116
|
-
* For Safari we make sure to check against each loaded font face,
|
|
117
|
-
* with the unique characters per family in the elements
|
|
118
|
-
* otherwise fonts might remain unloaded.
|
|
119
105
|
*/
|
|
120
106
|
static loadElementsFonts = async (elements) => {
|
|
121
107
|
const fontFamilies = Fonts.getUniqueFamilies(elements);
|
|
122
|
-
const charsPerFamily =
|
|
123
|
-
? Fonts.getCharsPerFamily(elements)
|
|
124
|
-
: undefined;
|
|
108
|
+
const charsPerFamily = Fonts.getCharsPerFamily(elements);
|
|
125
109
|
return Fonts.loadFontFaces(fontFamilies, charsPerFamily);
|
|
126
110
|
};
|
|
127
|
-
/**
|
|
128
|
-
* Load all registered font faces.
|
|
129
|
-
*/
|
|
130
|
-
static loadAllFonts = async () => {
|
|
131
|
-
const allFamilies = Fonts.getAllFamilies();
|
|
132
|
-
return Fonts.loadFontFaces(allFamilies);
|
|
133
|
-
};
|
|
134
111
|
/**
|
|
135
112
|
* Generate CSS @font-face declarations for the given elements.
|
|
136
113
|
*/
|
|
@@ -184,11 +161,9 @@ export class Fonts {
|
|
|
184
161
|
fontFamily,
|
|
185
162
|
fontSize: 16,
|
|
186
163
|
});
|
|
187
|
-
// WARN: without "text" param it does not have to mean that all font faces are loaded
|
|
188
|
-
//
|
|
189
|
-
const text =
|
|
190
|
-
? Fonts.getCharacters(charsPerFamily, fontFamily)
|
|
191
|
-
: "";
|
|
164
|
+
// WARN: without "text" param it does not have to mean that all font faces are loaded as it could be just one irrelevant font face!
|
|
165
|
+
// instead, we are always checking chars used in the family, so that no required font faces remain unloaded
|
|
166
|
+
const text = Fonts.getCharacters(charsPerFamily, fontFamily);
|
|
192
167
|
if (!window.document.fonts.check(font, text)) {
|
|
193
168
|
yield promiseTry(async () => {
|
|
194
169
|
try {
|
|
@@ -5,7 +5,7 @@ import type { ReadonlySetLike } from "./utility-types";
|
|
|
5
5
|
export declare const bindElementsToFramesAfterDuplication: (nextElements: readonly ExcalidrawElement[], oldElements: readonly ExcalidrawElement[], oldIdToDuplicatedId: Map<ExcalidrawElement["id"], ExcalidrawElement["id"]>) => void;
|
|
6
6
|
export declare function isElementIntersectingFrame(element: ExcalidrawElement, frame: ExcalidrawFrameLikeElement, elementsMap: ElementsMap): boolean;
|
|
7
7
|
export declare const getElementsCompletelyInFrame: (elements: readonly ExcalidrawElement[], frame: ExcalidrawFrameLikeElement, elementsMap: ElementsMap) => ExcalidrawElement[];
|
|
8
|
-
export declare const isElementContainingFrame: (
|
|
8
|
+
export declare const isElementContainingFrame: (element: ExcalidrawElement, frame: ExcalidrawFrameLikeElement, elementsMap: ElementsMap) => boolean;
|
|
9
9
|
export declare const getElementsIntersectingFrame: (elements: readonly ExcalidrawElement[], frame: ExcalidrawFrameLikeElement) => ExcalidrawElement[];
|
|
10
10
|
export declare const elementsAreInFrameBounds: (elements: readonly ExcalidrawElement[], frame: ExcalidrawFrameLikeElement, elementsMap: ElementsMap) => boolean;
|
|
11
11
|
export declare const elementOverlapsWithFrame: (element: ExcalidrawElement, frame: ExcalidrawFrameLikeElement, elementsMap: ElementsMap) => boolean;
|
|
@@ -31,7 +31,8 @@ export declare const getFrameLikeElements: (allElements: ExcalidrawElementsInclu
|
|
|
31
31
|
*/
|
|
32
32
|
export declare const getRootElements: (allElements: ExcalidrawElementsIncludingDeleted) => ExcalidrawElement[];
|
|
33
33
|
export declare const getElementsInResizingFrame: (allElements: ExcalidrawElementsIncludingDeleted, frame: ExcalidrawFrameLikeElement, appState: AppState, elementsMap: ElementsMap) => ExcalidrawElement[];
|
|
34
|
-
export declare const getElementsInNewFrame: (elements: ExcalidrawElementsIncludingDeleted, frame: ExcalidrawFrameLikeElement, elementsMap: ElementsMap) =>
|
|
34
|
+
export declare const getElementsInNewFrame: (elements: ExcalidrawElementsIncludingDeleted, frame: ExcalidrawFrameLikeElement, elementsMap: ElementsMap) => (import("./element/types").ExcalidrawSelectionElement | import("./element/types").ExcalidrawRectangleElement | import("./element/types").ExcalidrawDiamondElement | import("./element/types").ExcalidrawEllipseElement | import("./element/types").ExcalidrawTextElement | import("./element/types").ExcalidrawLinearElement | import("./element/types").ExcalidrawFreeDrawElement | import("./element/types").ExcalidrawImageElement | import("./element/types").ExcalidrawFrameElement | import("./element/types").ExcalidrawMagicFrameElement | import("./element/types").ExcalidrawIframeElement | import("./element/types").ExcalidrawEmbeddableElement)[];
|
|
35
|
+
export declare const omitPartialGroups: (elements: ExcalidrawElement[], frame: ExcalidrawFrameLikeElement, allElementsMap: ElementsMap) => (import("./element/types").ExcalidrawSelectionElement | import("./element/types").ExcalidrawRectangleElement | import("./element/types").ExcalidrawDiamondElement | import("./element/types").ExcalidrawEllipseElement | import("./element/types").ExcalidrawTextElement | import("./element/types").ExcalidrawLinearElement | import("./element/types").ExcalidrawFreeDrawElement | import("./element/types").ExcalidrawImageElement | import("./element/types").ExcalidrawFrameElement | import("./element/types").ExcalidrawMagicFrameElement | import("./element/types").ExcalidrawIframeElement | import("./element/types").ExcalidrawEmbeddableElement)[];
|
|
35
36
|
export declare const getContainingFrame: (element: ExcalidrawElement, elementsMap: ElementsMap) => ExcalidrawFrameLikeElement | null;
|
|
36
37
|
/** */
|
|
37
38
|
export declare const filterElementsEligibleAsFrameChildren: (elements: readonly ExcalidrawElement[], frame: ExcalidrawFrameLikeElement) => ExcalidrawElement[];
|
|
@@ -42,7 +43,7 @@ export declare const filterElementsEligibleAsFrameChildren: (elements: readonly
|
|
|
42
43
|
*
|
|
43
44
|
* @returns mutated allElements (same data structure)
|
|
44
45
|
*/
|
|
45
|
-
export declare const addElementsToFrame: <T extends ElementsMapOrArray>(allElements: T, elementsToAdd: NonDeletedExcalidrawElement[], frame: ExcalidrawFrameLikeElement) => T;
|
|
46
|
+
export declare const addElementsToFrame: <T extends ElementsMapOrArray>(allElements: T, elementsToAdd: NonDeletedExcalidrawElement[], frame: ExcalidrawFrameLikeElement, appState: AppState) => T;
|
|
46
47
|
export declare const removeElementsFromFrame: (elementsToRemove: ReadonlySetLike<NonDeletedExcalidrawElement>, elementsMap: ElementsMap) => void;
|
|
47
48
|
export declare const removeAllElementsFromFrame: <T extends ExcalidrawElement>(allElements: readonly T[], frame: ExcalidrawFrameLikeElement) => readonly T[];
|
|
48
49
|
export declare const replaceAllElementsInFrame: <T extends ExcalidrawElement>(allElements: readonly T[], nextElementsInFrame: ExcalidrawElement[], frame: ExcalidrawFrameLikeElement, app: AppClassProperties) => T[];
|
|
@@ -57,7 +58,12 @@ export declare const omitGroupsContainingFrameLikes: (allElements: ElementsMapOr
|
|
|
57
58
|
* depending on the appState, return target frame, which is the frame the given element
|
|
58
59
|
* is going to be added to or remove from
|
|
59
60
|
*/
|
|
60
|
-
export declare const getTargetFrame: (element: ExcalidrawElement, elementsMap: ElementsMap, appState: StaticCanvasAppState) =>
|
|
61
|
-
export declare const isElementInFrame: (element: ExcalidrawElement, allElementsMap: ElementsMap, appState: StaticCanvasAppState
|
|
61
|
+
export declare const getTargetFrame: (element: ExcalidrawElement, elementsMap: ElementsMap, appState: StaticCanvasAppState) => ExcalidrawFrameLikeElement | null;
|
|
62
|
+
export declare const isElementInFrame: (element: ExcalidrawElement, allElementsMap: ElementsMap, appState: StaticCanvasAppState, opts?: {
|
|
63
|
+
targetFrame?: ExcalidrawFrameLikeElement;
|
|
64
|
+
checkedGroups?: Map<string, boolean>;
|
|
65
|
+
}) => boolean;
|
|
66
|
+
export declare const shouldApplyFrameClip: (element: ExcalidrawElement, frame: ExcalidrawFrameLikeElement, appState: StaticCanvasAppState, elementsMap: ElementsMap, checkedGroups?: Map<string, boolean>) => boolean;
|
|
62
67
|
export declare const getFrameLikeTitle: (element: ExcalidrawFrameLikeElement) => string;
|
|
63
68
|
export declare const getElementsOverlappingFrame: (elements: readonly ExcalidrawElement[], frame: ExcalidrawFrameLikeElement) => NonDeletedExcalidrawElement[];
|
|
69
|
+
export declare const frameAndChildrenSelectedTogether: (selectedElements: readonly ExcalidrawElement[]) => boolean;
|
package/dist/excalidraw/frame.js
CHANGED
|
@@ -35,8 +35,8 @@ export function isElementIntersectingFrame(element, frame, elementsMap) {
|
|
|
35
35
|
}
|
|
36
36
|
export const getElementsCompletelyInFrame = (elements, frame, elementsMap) => omitGroupsContainingFrameLikes(getElementsWithinSelection(elements, frame, elementsMap, false)).filter((element) => (!isFrameLikeElement(element) && !element.frameId) ||
|
|
37
37
|
element.frameId === frame.id);
|
|
38
|
-
export const isElementContainingFrame = (
|
|
39
|
-
return getElementsWithinSelection(
|
|
38
|
+
export const isElementContainingFrame = (element, frame, elementsMap) => {
|
|
39
|
+
return getElementsWithinSelection([frame], element, elementsMap).some((e) => e.id === frame.id);
|
|
40
40
|
};
|
|
41
41
|
export const getElementsIntersectingFrame = (elements, frame) => {
|
|
42
42
|
const elementsMap = arrayToMap(elements);
|
|
@@ -53,7 +53,7 @@ export const elementsAreInFrameBounds = (elements, frame, elementsMap) => {
|
|
|
53
53
|
export const elementOverlapsWithFrame = (element, frame, elementsMap) => {
|
|
54
54
|
return (elementsAreInFrameBounds([element], frame, elementsMap) ||
|
|
55
55
|
isElementIntersectingFrame(element, frame, elementsMap) ||
|
|
56
|
-
isElementContainingFrame(
|
|
56
|
+
isElementContainingFrame(element, frame, elementsMap));
|
|
57
57
|
};
|
|
58
58
|
export const isCursorInFrame = (cursorCoords, frame, elementsMap) => {
|
|
59
59
|
const [fx1, fy1, fx2, fy2] = getElementAbsoluteCoords(frame, elementsMap);
|
|
@@ -122,7 +122,7 @@ export const getElementsInResizingFrame = (allElements, frame, appState, element
|
|
|
122
122
|
const nextElementsInFrame = new Set(prevElementsInFrame);
|
|
123
123
|
const elementsCompletelyInFrame = new Set([
|
|
124
124
|
...getElementsCompletelyInFrame(allElements, frame, elementsMap),
|
|
125
|
-
...prevElementsInFrame.filter((element) => isElementContainingFrame(
|
|
125
|
+
...prevElementsInFrame.filter((element) => isElementContainingFrame(element, frame, elementsMap)),
|
|
126
126
|
]);
|
|
127
127
|
const elementsNotCompletelyInFrame = prevElementsInFrame.filter((element) => !elementsCompletelyInFrame.has(element));
|
|
128
128
|
// for elements that are completely in the frame
|
|
@@ -178,7 +178,31 @@ export const getElementsInResizingFrame = (allElements, frame, appState, element
|
|
|
178
178
|
});
|
|
179
179
|
};
|
|
180
180
|
export const getElementsInNewFrame = (elements, frame, elementsMap) => {
|
|
181
|
-
return omitGroupsContainingFrameLikes(elements, getElementsCompletelyInFrame(elements, frame, elementsMap));
|
|
181
|
+
return omitPartialGroups(omitGroupsContainingFrameLikes(elements, getElementsCompletelyInFrame(elements, frame, elementsMap)), frame, elementsMap);
|
|
182
|
+
};
|
|
183
|
+
export const omitPartialGroups = (elements, frame, allElementsMap) => {
|
|
184
|
+
const elementsToReturn = [];
|
|
185
|
+
const checkedGroups = new Map();
|
|
186
|
+
for (const element of elements) {
|
|
187
|
+
let shouldOmit = false;
|
|
188
|
+
if (element.groupIds.length > 0) {
|
|
189
|
+
// if some partial group should be omitted, then all elements in that group should be omitted
|
|
190
|
+
if (element.groupIds.some((gid) => checkedGroups.get(gid))) {
|
|
191
|
+
shouldOmit = true;
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
const allElementsInGroup = new Set(element.groupIds.flatMap((gid) => getElementsInGroup(allElementsMap, gid)));
|
|
195
|
+
shouldOmit = !elementsAreInFrameBounds(Array.from(allElementsInGroup), frame, allElementsMap);
|
|
196
|
+
}
|
|
197
|
+
element.groupIds.forEach((gid) => {
|
|
198
|
+
checkedGroups.set(gid, shouldOmit);
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
if (!shouldOmit) {
|
|
202
|
+
elementsToReturn.push(element);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
return elementsToReturn;
|
|
182
206
|
};
|
|
183
207
|
export const getContainingFrame = (element, elementsMap) => {
|
|
184
208
|
if (!element.frameId) {
|
|
@@ -234,7 +258,7 @@ export const filterElementsEligibleAsFrameChildren = (elements, frame) => {
|
|
|
234
258
|
*
|
|
235
259
|
* @returns mutated allElements (same data structure)
|
|
236
260
|
*/
|
|
237
|
-
export const addElementsToFrame = (allElements, elementsToAdd, frame) => {
|
|
261
|
+
export const addElementsToFrame = (allElements, elementsToAdd, frame, appState) => {
|
|
238
262
|
const elementsMap = arrayToMap(allElements);
|
|
239
263
|
const currTargetFrameChildrenMap = new Map();
|
|
240
264
|
for (const element of allElements.values()) {
|
|
@@ -258,6 +282,14 @@ export const addElementsToFrame = (allElements, elementsToAdd, frame) => {
|
|
|
258
282
|
(element.frameId && otherFrames.has(element.frameId))) {
|
|
259
283
|
continue;
|
|
260
284
|
}
|
|
285
|
+
// if the element is already in another frame (which is also in elementsToAdd),
|
|
286
|
+
// it means that frame and children are selected at the same time
|
|
287
|
+
// => keep original frame membership, do not add to the target frame
|
|
288
|
+
if (element.frameId &&
|
|
289
|
+
appState.selectedElementIds[element.id] &&
|
|
290
|
+
appState.selectedElementIds[element.frameId]) {
|
|
291
|
+
continue;
|
|
292
|
+
}
|
|
261
293
|
if (!currTargetFrameChildrenMap.has(element.id)) {
|
|
262
294
|
finalElementsToAdd.push(element);
|
|
263
295
|
}
|
|
@@ -303,7 +335,7 @@ export const removeAllElementsFromFrame = (allElements, frame) => {
|
|
|
303
335
|
return allElements;
|
|
304
336
|
};
|
|
305
337
|
export const replaceAllElementsInFrame = (allElements, nextElementsInFrame, frame, app) => {
|
|
306
|
-
return addElementsToFrame(removeAllElementsFromFrame(allElements, frame), nextElementsInFrame, frame).slice();
|
|
338
|
+
return addElementsToFrame(removeAllElementsFromFrame(allElements, frame), nextElementsInFrame, frame, app.state).slice();
|
|
307
339
|
};
|
|
308
340
|
/** does not mutate elements, but returns new ones */
|
|
309
341
|
export const updateFrameMembershipOfSelectedElements = (allElements, appState, app) => {
|
|
@@ -378,6 +410,13 @@ export const getTargetFrame = (element, elementsMap, appState) => {
|
|
|
378
410
|
const _element = isTextElement(element)
|
|
379
411
|
? getContainerElement(element, elementsMap) || element
|
|
380
412
|
: element;
|
|
413
|
+
// if the element and its containing frame are both selected, then
|
|
414
|
+
// the containing frame is the target frame
|
|
415
|
+
if (_element.frameId &&
|
|
416
|
+
appState.selectedElementIds[_element.id] &&
|
|
417
|
+
appState.selectedElementIds[_element.frameId]) {
|
|
418
|
+
return getContainingFrame(_element, elementsMap);
|
|
419
|
+
}
|
|
381
420
|
return appState.selectedElementIds[_element.id] &&
|
|
382
421
|
appState.selectedElementsAreBeingDragged
|
|
383
422
|
? appState.frameToHighlight
|
|
@@ -385,44 +424,111 @@ export const getTargetFrame = (element, elementsMap, appState) => {
|
|
|
385
424
|
};
|
|
386
425
|
// TODO: this a huge bottleneck for large scenes, optimise
|
|
387
426
|
// given an element, return if the element is in some frame
|
|
388
|
-
export const isElementInFrame = (element, allElementsMap, appState) => {
|
|
389
|
-
const frame = getTargetFrame(element, allElementsMap, appState);
|
|
427
|
+
export const isElementInFrame = (element, allElementsMap, appState, opts) => {
|
|
428
|
+
const frame = opts?.targetFrame ?? getTargetFrame(element, allElementsMap, appState);
|
|
429
|
+
if (!frame) {
|
|
430
|
+
return false;
|
|
431
|
+
}
|
|
390
432
|
const _element = isTextElement(element)
|
|
391
433
|
? getContainerElement(element, allElementsMap) || element
|
|
392
434
|
: element;
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
435
|
+
const setGroupsInFrame = (isInFrame) => {
|
|
436
|
+
if (opts?.checkedGroups) {
|
|
437
|
+
_element.groupIds.forEach((groupId) => {
|
|
438
|
+
opts.checkedGroups?.set(groupId, isInFrame);
|
|
439
|
+
});
|
|
440
|
+
}
|
|
441
|
+
};
|
|
442
|
+
if (
|
|
443
|
+
// if the element is not selected, or it is selected but not being dragged,
|
|
444
|
+
// frame membership won't update, so return true
|
|
445
|
+
!appState.selectedElementIds[_element.id] ||
|
|
446
|
+
!appState.selectedElementsAreBeingDragged ||
|
|
447
|
+
// if both frame and element are selected, won't update membership, so return true
|
|
448
|
+
(appState.selectedElementIds[_element.id] &&
|
|
449
|
+
appState.selectedElementIds[frame.id])) {
|
|
450
|
+
return true;
|
|
451
|
+
}
|
|
452
|
+
if (_element.groupIds.length === 0) {
|
|
453
|
+
return elementOverlapsWithFrame(_element, frame, allElementsMap);
|
|
454
|
+
}
|
|
455
|
+
for (const gid of _element.groupIds) {
|
|
456
|
+
if (opts?.checkedGroups?.has(gid)) {
|
|
457
|
+
return opts.checkedGroups.get(gid);
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
const allElementsInGroup = new Set(_element.groupIds
|
|
461
|
+
.filter((gid) => {
|
|
462
|
+
if (opts?.checkedGroups) {
|
|
463
|
+
return !opts.checkedGroups.has(gid);
|
|
464
|
+
}
|
|
465
|
+
return true;
|
|
466
|
+
})
|
|
467
|
+
.flatMap((gid) => getElementsInGroup(allElementsMap, gid)));
|
|
468
|
+
if (appState.editingGroupId && appState.selectedElementsAreBeingDragged) {
|
|
469
|
+
const selectedElements = new Set(getSelectedElements(allElementsMap, appState));
|
|
470
|
+
const editingGroupOverlapsFrame = appState.frameToHighlight !== null;
|
|
471
|
+
if (editingGroupOverlapsFrame) {
|
|
400
472
|
return true;
|
|
401
473
|
}
|
|
402
|
-
|
|
403
|
-
|
|
474
|
+
selectedElements.forEach((selectedElement) => {
|
|
475
|
+
allElementsInGroup.delete(selectedElement);
|
|
476
|
+
});
|
|
477
|
+
}
|
|
478
|
+
for (const elementInGroup of allElementsInGroup) {
|
|
479
|
+
if (isFrameLikeElement(elementInGroup)) {
|
|
480
|
+
setGroupsInFrame(false);
|
|
481
|
+
return false;
|
|
404
482
|
}
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
return true;
|
|
411
|
-
}
|
|
412
|
-
selectedElements.forEach((selectedElement) => {
|
|
413
|
-
allElementsInGroup.delete(selectedElement);
|
|
414
|
-
});
|
|
483
|
+
}
|
|
484
|
+
for (const elementInGroup of allElementsInGroup) {
|
|
485
|
+
if (elementOverlapsWithFrame(elementInGroup, frame, allElementsMap)) {
|
|
486
|
+
setGroupsInFrame(true);
|
|
487
|
+
return true;
|
|
415
488
|
}
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
489
|
+
}
|
|
490
|
+
return false;
|
|
491
|
+
};
|
|
492
|
+
export const shouldApplyFrameClip = (element, frame, appState, elementsMap, checkedGroups) => {
|
|
493
|
+
if (!appState.frameRendering || !appState.frameRendering.clip) {
|
|
494
|
+
return false;
|
|
495
|
+
}
|
|
496
|
+
// for individual elements, only clip when the element is
|
|
497
|
+
// a. overlapping with the frame, or
|
|
498
|
+
// b. containing the frame, for example when an element is used as a background
|
|
499
|
+
// and is therefore bigger than the frame and completely contains the frame
|
|
500
|
+
const shouldClipElementItself = isElementIntersectingFrame(element, frame, elementsMap) ||
|
|
501
|
+
isElementContainingFrame(element, frame, elementsMap);
|
|
502
|
+
if (shouldClipElementItself) {
|
|
503
|
+
for (const groupId of element.groupIds) {
|
|
504
|
+
checkedGroups?.set(groupId, true);
|
|
420
505
|
}
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
506
|
+
return true;
|
|
507
|
+
}
|
|
508
|
+
// if an element is outside the frame, but is part of a group that has some elements
|
|
509
|
+
// "in" the frame, we should clip the element
|
|
510
|
+
if (!shouldClipElementItself &&
|
|
511
|
+
element.groupIds.length > 0 &&
|
|
512
|
+
!elementsAreInFrameBounds([element], frame, elementsMap)) {
|
|
513
|
+
let shouldClip = false;
|
|
514
|
+
// if no elements are being dragged, we can skip the geometry check
|
|
515
|
+
// because we know if the element is in the given frame or not
|
|
516
|
+
if (!appState.selectedElementsAreBeingDragged) {
|
|
517
|
+
shouldClip = element.frameId === frame.id;
|
|
518
|
+
for (const groupId of element.groupIds) {
|
|
519
|
+
checkedGroups?.set(groupId, shouldClip);
|
|
424
520
|
}
|
|
425
521
|
}
|
|
522
|
+
else {
|
|
523
|
+
shouldClip = isElementInFrame(element, elementsMap, appState, {
|
|
524
|
+
targetFrame: frame,
|
|
525
|
+
checkedGroups,
|
|
526
|
+
});
|
|
527
|
+
}
|
|
528
|
+
for (const groupId of element.groupIds) {
|
|
529
|
+
checkedGroups?.set(groupId, shouldClip);
|
|
530
|
+
}
|
|
531
|
+
return shouldClip;
|
|
426
532
|
}
|
|
427
533
|
return false;
|
|
428
534
|
};
|
|
@@ -444,3 +550,8 @@ export const getElementsOverlappingFrame = (elements, frame) => {
|
|
|
444
550
|
// and thus invisible in target frame
|
|
445
551
|
.filter((el) => !el.frameId || el.frameId === frame.id));
|
|
446
552
|
};
|
|
553
|
+
export const frameAndChildrenSelectedTogether = (selectedElements) => {
|
|
554
|
+
const selectedElementsMap = arrayToMap(selectedElements);
|
|
555
|
+
return (selectedElements.length > 1 &&
|
|
556
|
+
selectedElements.some((element) => element.frameId && selectedElementsMap.has(element.frameId)));
|
|
557
|
+
};
|
|
@@ -58,6 +58,9 @@ export const selectGroupsForSelectedElements = (function () {
|
|
|
58
58
|
// Gather all the elements within selected groups
|
|
59
59
|
const groupElementsIndex = {};
|
|
60
60
|
const selectedElementIdsInGroups = elements.reduce((acc, element) => {
|
|
61
|
+
if (element.isDeleted) {
|
|
62
|
+
return acc;
|
|
63
|
+
}
|
|
61
64
|
const groupId = element.groupIds.find((id) => selectedGroupIds[id]);
|
|
62
65
|
if (groupId) {
|
|
63
66
|
acc[element.id] = true;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { LibraryItem } from "../types";
|
|
2
2
|
export type SvgCache = Map<LibraryItem["id"], SVGSVGElement>;
|
|
3
|
-
export declare const libraryItemSvgsCache: import("jotai").PrimitiveAtom<SvgCache> & {
|
|
3
|
+
export declare const libraryItemSvgsCache: import("jotai/vanilla/atom").PrimitiveAtom<SvgCache> & {
|
|
4
4
|
init: SvgCache;
|
|
5
5
|
};
|
|
6
6
|
export declare const useLibraryItemSvg: (id: LibraryItem["id"] | null, elements: LibraryItem["elements"] | undefined, svgCache: SvgCache) => SVGSVGElement | undefined;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { atom, useAtom } from "jotai";
|
|
2
1
|
import { useEffect, useState } from "react";
|
|
3
2
|
import { COLOR_PALETTE } from "../colors";
|
|
4
|
-
import {
|
|
3
|
+
import { atom, useAtom } from "../editor-jotai";
|
|
5
4
|
import { exportToSvg } from "../../utils/export";
|
|
6
5
|
export const libraryItemSvgsCache = atom(new Map());
|
|
7
6
|
const exportLibraryItemToSvg = async (elements) => {
|
|
@@ -51,7 +50,7 @@ export const useLibraryItemSvg = (id, elements, svgCache) => {
|
|
|
51
50
|
return svg;
|
|
52
51
|
};
|
|
53
52
|
export const useLibraryCache = () => {
|
|
54
|
-
const [svgCache] = useAtom(libraryItemSvgsCache
|
|
53
|
+
const [svgCache] = useAtom(libraryItemSvgsCache);
|
|
55
54
|
const clearLibraryCache = () => svgCache.clear();
|
|
56
55
|
const deleteItemsFromLibraryCache = (items) => {
|
|
57
56
|
items.forEach((item) => svgCache.delete(item));
|
package/dist/excalidraw/i18n.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import fallbackLangData from "./locales/en.json";
|
|
2
2
|
import percentages from "./locales/percentages.json";
|
|
3
|
-
import {
|
|
4
|
-
import { atom, useAtomValue } from "jotai";
|
|
3
|
+
import { useAtomValue, editorJotaiStore, atom } from "./editor-jotai";
|
|
5
4
|
const COMPLETION_THRESHOLD = 85;
|
|
6
5
|
export const defaultLang = { code: "en", label: "English" };
|
|
7
6
|
export const languages = [
|
|
@@ -82,7 +81,7 @@ export const setLanguage = async (lang) => {
|
|
|
82
81
|
currentLangData = fallbackLangData;
|
|
83
82
|
}
|
|
84
83
|
}
|
|
85
|
-
|
|
84
|
+
editorJotaiStore.set(editorLangCodeAtom, lang.code);
|
|
86
85
|
};
|
|
87
86
|
export const getLanguage = () => currentLang;
|
|
88
87
|
const findPartsForData = (data, parts) => {
|
|
@@ -132,6 +131,6 @@ const editorLangCodeAtom = atom(defaultLang.code);
|
|
|
132
131
|
// - component is rendered internally by <Excalidraw>, but the component
|
|
133
132
|
// is memoized w/o being updated on `langCode`, `AppState`, or `UIAppState`
|
|
134
133
|
export const useI18n = () => {
|
|
135
|
-
const langCode = useAtomValue(editorLangCodeAtom
|
|
134
|
+
const langCode = useAtomValue(editorLangCodeAtom);
|
|
136
135
|
return { t, langCode };
|
|
137
136
|
};
|
package/dist/excalidraw/index.js
CHANGED
|
@@ -9,15 +9,14 @@ import "./css/styles.scss";
|
|
|
9
9
|
import "./fonts/fonts.css";
|
|
10
10
|
import { defaultLang } from "./i18n";
|
|
11
11
|
import { DEFAULT_UI_OPTIONS } from "./constants";
|
|
12
|
-
import {
|
|
13
|
-
import { jotaiScope, jotaiStore } from "./jotai";
|
|
12
|
+
import { EditorJotaiProvider, editorJotaiStore } from "./editor-jotai";
|
|
14
13
|
import Footer from "./components/footer/FooterCenter";
|
|
15
14
|
import MainMenu from "./components/main-menu/MainMenu";
|
|
16
15
|
import WelcomeScreen from "./components/welcome-screen/WelcomeScreen";
|
|
17
16
|
import LiveCollaborationTrigger from "./components/live-collaboration/LiveCollaborationTrigger";
|
|
18
17
|
polyfill();
|
|
19
18
|
const ExcalidrawBase = (props) => {
|
|
20
|
-
const { onChange, initialData, excalidrawAPI, isCollaborating = false, onPointerUpdate, renderTopRightUI, langCode = defaultLang.code, viewModeEnabled, zenModeEnabled, gridModeEnabled, libraryReturnUrl, theme, name, renderCustomStats, onPaste, detectScroll = true, handleKeyboardGlobally = false, onLibraryChange, autoFocus = false, generateIdForFile, onLinkOpen, generateLinkForSelection, onPointerDown, onPointerUp, onScrollChange, children, validateEmbeddable, renderEmbeddable, aiEnabled, showDeprecatedFonts, } = props;
|
|
19
|
+
const { onChange, initialData, excalidrawAPI, isCollaborating = false, onPointerUpdate, renderTopRightUI, langCode = defaultLang.code, viewModeEnabled, zenModeEnabled, gridModeEnabled, libraryReturnUrl, theme, name, renderCustomStats, onPaste, detectScroll = true, handleKeyboardGlobally = false, onLibraryChange, autoFocus = false, generateIdForFile, onLinkOpen, generateLinkForSelection, onPointerDown, onPointerUp, onScrollChange, onDuplicate, children, validateEmbeddable, renderEmbeddable, aiEnabled, showDeprecatedFonts, } = props;
|
|
21
20
|
const canvasActions = props.UIOptions?.canvasActions;
|
|
22
21
|
// FIXME normalize/set defaults in parent component so that the memo resolver
|
|
23
22
|
// compares the same values
|
|
@@ -60,7 +59,7 @@ const ExcalidrawBase = (props) => {
|
|
|
60
59
|
document.removeEventListener("touchmove", handleTouchMove);
|
|
61
60
|
};
|
|
62
61
|
}, []);
|
|
63
|
-
return (_jsx(
|
|
62
|
+
return (_jsx(EditorJotaiProvider, { store: editorJotaiStore, children: _jsx(InitializeApp, { langCode: langCode, theme: theme, children: _jsx(App, { onChange: onChange, initialData: initialData, excalidrawAPI: excalidrawAPI, isCollaborating: isCollaborating, onPointerUpdate: onPointerUpdate, renderTopRightUI: renderTopRightUI, langCode: langCode, viewModeEnabled: viewModeEnabled, zenModeEnabled: zenModeEnabled, gridModeEnabled: gridModeEnabled, libraryReturnUrl: libraryReturnUrl, theme: theme, name: name, renderCustomStats: renderCustomStats, UIOptions: UIOptions, onPaste: onPaste, detectScroll: detectScroll, handleKeyboardGlobally: handleKeyboardGlobally, onLibraryChange: onLibraryChange, autoFocus: autoFocus, generateIdForFile: generateIdForFile, onLinkOpen: onLinkOpen, generateLinkForSelection: generateLinkForSelection, onPointerDown: onPointerDown, onPointerUp: onPointerUp, onScrollChange: onScrollChange, onDuplicate: onDuplicate, validateEmbeddable: validateEmbeddable, renderEmbeddable: renderEmbeddable, aiEnabled: aiEnabled !== false, showDeprecatedFonts: showDeprecatedFonts, children: children }) }) }));
|
|
64
63
|
};
|
|
65
64
|
const areEqual = (prevProps, nextProps) => {
|
|
66
65
|
// short-circuit early
|
|
@@ -46,6 +46,10 @@
|
|
|
46
46
|
"arrowhead_triangle_outline": "Triangle (outline)",
|
|
47
47
|
"arrowhead_diamond": "Diamond",
|
|
48
48
|
"arrowhead_diamond_outline": "Diamond (outline)",
|
|
49
|
+
"arrowhead_crowfoot_many": "Crow's foot (many)",
|
|
50
|
+
"arrowhead_crowfoot_one": "Crow's foot (one)",
|
|
51
|
+
"arrowhead_crowfoot_one_or_many": "Crow's foot (one or many)",
|
|
52
|
+
"more_options": "More options",
|
|
49
53
|
"arrowtypes": "Arrow type",
|
|
50
54
|
"arrowtype_sharp": "Sharp arrow",
|
|
51
55
|
"arrowtype_round": "Curved arrow",
|
|
@@ -157,8 +161,11 @@
|
|
|
157
161
|
"zoomToFit": "Zoom to fit all elements",
|
|
158
162
|
"installPWA": "Install Excalidraw locally (PWA)",
|
|
159
163
|
"autoResize": "Enable text auto-resizing",
|
|
164
|
+
"imageCropping": "Image cropping",
|
|
165
|
+
"unCroppedDimension": "Uncropped dimension",
|
|
160
166
|
"copyElementLink": "Copy link to object",
|
|
161
|
-
"linkToElement": "Link to object"
|
|
167
|
+
"linkToElement": "Link to object",
|
|
168
|
+
"wrapSelectionInFrame": "Wrap selection in frame"
|
|
162
169
|
},
|
|
163
170
|
"elementLink": {
|
|
164
171
|
"title": "Link to object",
|